2026-02-05 20:50:17 +00:00
|
|
|
import { Link } from 'react-router-dom';
|
|
|
|
|
import { Checkbox } from '@/components/ui/checkbox';
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
import { AlertCircle, Loader2, Check, X } from 'lucide-react';
|
|
|
|
|
import { AuthInput } from '../AuthInput';
|
|
|
|
|
import { AuthButton } from '../AuthButton';
|
2026-02-05 20:50:17 +00:00
|
|
|
import { PasswordStrengthIndicator } from '../PasswordStrengthIndicator';
|
|
|
|
|
import type { RegisterFormData } from '../../types';
|
|
|
|
|
import type { FormErrors } from './useRegisterPage';
|
|
|
|
|
|
|
|
|
|
interface RegisterPageFormProps {
|
|
|
|
|
formData: RegisterFormData;
|
|
|
|
|
errors: FormErrors;
|
|
|
|
|
acceptedTerms: boolean;
|
|
|
|
|
onAcceptedTermsChange: (checked: boolean) => void;
|
|
|
|
|
onErrorsChange: (updater: (prev: FormErrors) => FormErrors) => void;
|
|
|
|
|
loading: boolean;
|
|
|
|
|
error: Error | null;
|
|
|
|
|
usernameAvailable: boolean | null;
|
|
|
|
|
checkingUsername: boolean;
|
|
|
|
|
onFieldChange: (field: keyof RegisterFormData, value: string) => void;
|
|
|
|
|
onFieldBlur: (field: keyof RegisterFormData) => void;
|
|
|
|
|
onSubmit: (e: React.FormEvent) => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function RegisterPageForm({
|
|
|
|
|
formData,
|
|
|
|
|
errors,
|
|
|
|
|
acceptedTerms,
|
|
|
|
|
onAcceptedTermsChange,
|
|
|
|
|
onErrorsChange,
|
|
|
|
|
loading,
|
|
|
|
|
error,
|
|
|
|
|
usernameAvailable,
|
|
|
|
|
checkingUsername,
|
|
|
|
|
onFieldChange,
|
|
|
|
|
onFieldBlur,
|
|
|
|
|
onSubmit,
|
|
|
|
|
}: RegisterPageFormProps) {
|
|
|
|
|
return (
|
|
|
|
|
<form
|
|
|
|
|
onSubmit={onSubmit}
|
|
|
|
|
className="space-y-4"
|
|
|
|
|
aria-label="Formulaire d'inscription"
|
|
|
|
|
>
|
|
|
|
|
{error && (
|
|
|
|
|
<div
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
className="bg-destructive/10 border border-destructive/30 text-destructive px-4 py-3 rounded-lg text-sm flex items-center gap-2 animate-in fade-in slide-in-from-top-1"
|
2026-02-05 20:50:17 +00:00
|
|
|
role="alert"
|
|
|
|
|
aria-live="assertive"
|
|
|
|
|
>
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
<AlertCircle className="w-4 h-4 flex-shrink-0" />
|
|
|
|
|
<p>{error.message}</p>
|
2026-02-05 20:50:17 +00:00
|
|
|
</div>
|
|
|
|
|
)}
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
{/* Username */}
|
|
|
|
|
<div>
|
|
|
|
|
<AuthInput
|
|
|
|
|
id="register-username"
|
|
|
|
|
type="text"
|
|
|
|
|
label="Nom d'utilisateur"
|
|
|
|
|
value={formData.username}
|
|
|
|
|
onChange={(e) => onFieldChange('username', e.target.value)}
|
|
|
|
|
onBlur={() => onFieldBlur('username')}
|
|
|
|
|
required
|
|
|
|
|
autoComplete="username"
|
|
|
|
|
error={errors.username}
|
|
|
|
|
/>
|
|
|
|
|
{formData.username.length >= 3 && (
|
|
|
|
|
<div className="mt-1.5" aria-live="polite" aria-atomic="true">
|
|
|
|
|
{checkingUsername ? (
|
|
|
|
|
<p className="text-xs text-muted-foreground flex items-center gap-1.5" role="status">
|
|
|
|
|
<span className="h-3 w-3 border-2 border-muted-foreground border-t-transparent rounded-full animate-spin" />
|
|
|
|
|
<span>Vérification...</span>
|
|
|
|
|
</p>
|
|
|
|
|
) : usernameAvailable === true ? (
|
|
|
|
|
<p className="text-xs text-success flex items-center gap-1.5" role="status">
|
|
|
|
|
<Check className="h-3 w-3" />
|
|
|
|
|
<span>Ce nom d'utilisateur est disponible</span>
|
|
|
|
|
</p>
|
|
|
|
|
) : usernameAvailable === false ? (
|
|
|
|
|
<p className="text-xs text-destructive flex items-center gap-1.5" role="alert">
|
|
|
|
|
<X className="h-3 w-3" />
|
|
|
|
|
<span>Ce nom d'utilisateur est déjà pris</span>
|
|
|
|
|
</p>
|
|
|
|
|
) : null}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Email */}
|
|
|
|
|
<AuthInput
|
2026-02-05 20:50:17 +00:00
|
|
|
id="register-email"
|
|
|
|
|
type="email"
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
label="Email"
|
2026-02-05 20:50:17 +00:00
|
|
|
value={formData.email}
|
|
|
|
|
onChange={(e) => onFieldChange('email', e.target.value)}
|
|
|
|
|
onBlur={() => onFieldBlur('email')}
|
|
|
|
|
required
|
|
|
|
|
autoComplete="email"
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
error={errors.email}
|
2026-02-05 20:50:17 +00:00
|
|
|
/>
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
|
|
|
|
|
{/* Password */}
|
|
|
|
|
<div>
|
|
|
|
|
<AuthInput
|
|
|
|
|
id="register-password"
|
|
|
|
|
type="password"
|
|
|
|
|
label="Mot de passe"
|
|
|
|
|
value={formData.password}
|
|
|
|
|
onChange={(e) => onFieldChange('password', e.target.value)}
|
|
|
|
|
onBlur={() => onFieldBlur('password')}
|
|
|
|
|
required
|
|
|
|
|
autoComplete="new-password"
|
|
|
|
|
showPasswordToggle
|
|
|
|
|
error={errors.password}
|
|
|
|
|
/>
|
|
|
|
|
<PasswordStrengthIndicator password={formData.password} />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Confirm password */}
|
|
|
|
|
<AuthInput
|
2026-02-05 20:50:17 +00:00
|
|
|
id="register-password_confirm"
|
|
|
|
|
type="password"
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
label="Confirmer le mot de passe"
|
2026-02-05 20:50:17 +00:00
|
|
|
value={formData.password_confirm}
|
|
|
|
|
onChange={(e) => onFieldChange('password_confirm', e.target.value)}
|
|
|
|
|
onBlur={() => onFieldBlur('password_confirm')}
|
|
|
|
|
required
|
|
|
|
|
autoComplete="new-password"
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
showPasswordToggle
|
|
|
|
|
error={errors.password_confirm}
|
2026-02-05 20:50:17 +00:00
|
|
|
/>
|
|
|
|
|
</div>
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
|
|
|
|
|
{/* Terms */}
|
|
|
|
|
<div className="flex items-start gap-3 pt-1">
|
|
|
|
|
<div className="pt-0.5">
|
|
|
|
|
<Checkbox
|
|
|
|
|
id="register-terms"
|
|
|
|
|
checked={acceptedTerms}
|
|
|
|
|
onCheckedChange={(checked) => {
|
|
|
|
|
onAcceptedTermsChange(checked as boolean);
|
|
|
|
|
if (errors.terms) onErrorsChange((prev) => ({ ...prev, terms: undefined }));
|
|
|
|
|
}}
|
|
|
|
|
required
|
|
|
|
|
aria-invalid={errors.terms ? 'true' : 'false'}
|
|
|
|
|
aria-describedby={errors.terms ? 'terms-error' : 'terms-description'}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<label htmlFor="register-terms" className="text-sm text-muted-foreground leading-relaxed cursor-pointer">
|
2026-02-05 20:50:17 +00:00
|
|
|
J'accepte les{' '}
|
|
|
|
|
<Link
|
|
|
|
|
to="/terms"
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
className="text-foreground hover:underline underline-offset-4 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded"
|
2026-02-05 20:50:17 +00:00
|
|
|
aria-label="Lire les conditions d'utilisation"
|
|
|
|
|
>
|
|
|
|
|
conditions d'utilisation
|
|
|
|
|
</Link>{' '}
|
|
|
|
|
et la{' '}
|
|
|
|
|
<Link
|
|
|
|
|
to="/privacy"
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
className="text-foreground hover:underline underline-offset-4 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded"
|
2026-02-05 20:50:17 +00:00
|
|
|
aria-label="Lire la politique de confidentialité"
|
|
|
|
|
>
|
|
|
|
|
politique de confidentialité
|
|
|
|
|
</Link>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<p id="terms-description" className="sr-only">
|
|
|
|
|
Vous devez accepter les conditions d'utilisation et la politique de confidentialité pour créer un compte
|
|
|
|
|
</p>
|
|
|
|
|
{errors.terms && (
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
<p id="terms-error" className="text-sm text-destructive animate-shake" role="alert">
|
2026-02-05 20:50:17 +00:00
|
|
|
{errors.terms}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
|
|
|
|
|
<AuthButton
|
|
|
|
|
type="submit"
|
|
|
|
|
loading={loading}
|
2026-02-12 01:09:29 +00:00
|
|
|
className="w-full bg-primary text-primary-foreground hover:opacity-90 shadow-sm"
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
>
|
2026-02-05 20:50:17 +00:00
|
|
|
{loading ? (
|
|
|
|
|
<>
|
|
|
|
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
|
|
|
Inscription en cours...
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
"S'inscrire"
|
|
|
|
|
)}
|
feat(ui): premium auth pages polish
AuthLayout:
- Full-screen gradient background with animated pulse blobs
- Glass-morphism card (bg-card/80, backdrop-blur-md, shadow-2xl)
- New animate-auth-enter animation (fade + scale + translateY)
OAuth buttons: real provider icons (Google SVG, GitHub, Discord)
Password strength: 4-segment bar, color-coded labels, checklist icons
Login: Checkbox component for Remember Me, animated error alerts
Register: migrated to AuthInput, username check with spinner/icons
Verification notice: Mail icon, success-tinted circle, AuthButton
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:33:35 +00:00
|
|
|
</AuthButton>
|
2026-02-05 20:50:17 +00:00
|
|
|
</form>
|
|
|
|
|
);
|
|
|
|
|
}
|