feat: revue de code, doc CODE_REVIEW, forfaits 2026, traduction LLM, providers avec modèle

Made-with: Cursor
This commit is contained in:
Sepehr Ramezani
2026-03-07 11:42:58 +01:00
parent 3d37ce4582
commit 473b3e26c7
181 changed files with 30617 additions and 7170 deletions

View File

@@ -0,0 +1,126 @@
'use client';
import { useState, useEffect } from 'react';
import Link from 'next/link';
import { Eye, EyeOff, Mail, Lock, ArrowRight, Loader2, Languages } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { useNotification } from '@/components/ui/notification';
import { useLogin } from './useLogin';
export function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
const loginMutation = useLogin();
const { notify } = useNotification();
useEffect(() => {
if (loginMutation.isError && loginMutation.error) {
notify({
title: 'Erreur de connexion',
description: loginMutation.error.message,
variant: 'destructive',
});
}
}, [loginMutation.isError, loginMutation.error, notify]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
loginMutation.mutate({ email, password });
};
return (
<Card variant="elevated" className="w-full max-w-md mx-auto" hover={false}>
<CardHeader className="text-center pb-6">
<Link href="/" className="inline-flex items-center gap-3 mb-6 group">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-primary text-primary-foreground shadow-lg">
<Languages className="h-6 w-6" />
</div>
<span className="text-2xl font-semibold text-foreground">
Office Translator
</span>
</Link>
<CardTitle className="text-2xl font-bold">
Welcome back
</CardTitle>
<CardDescription>
Sign in to continue translating
</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
leftIcon={<Mail className="h-4 w-4" />}
required
/>
</div>
<div className="space-y-2">
<div className="flex justify-between items-center">
<Label htmlFor="password">Password</Label>
<Link href="/auth/forgot-password" className="text-sm text-primary hover:underline">
Forgot password?
</Link>
</div>
<div className="relative">
<Input
id="password"
type={showPassword ? 'text' : 'password'}
placeholder="••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
leftIcon={<Lock className="h-4 w-4" />}
required
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
>
{showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
</button>
</div>
</div>
<Button
type="submit"
disabled={loginMutation.isPending || !email || !password}
className="w-full"
>
{loginMutation.isPending ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Signing in...
</>
) : (
<>
Sign In
<ArrowRight className="ml-2 h-4 w-4" />
</>
)}
</Button>
</form>
<p className="text-center text-sm text-muted-foreground">
Don&apos;t have an account?{' '}
<Link href="/auth/register" className="text-primary hover:underline">
Sign up for free
</Link>
</p>
</CardContent>
</Card>
);
}