Files
memegoat/frontend/src/app/(auth)/register/page.tsx
Avnyr a4d0c6aa8c feat(auth): enhance validation rules for username and password
- Updated username validation to allow only lowercase letters, numbers, and underscores.
- Strengthened password requirements to include at least 8 characters, one uppercase letter, one lowercase letter, one number, and one special character.
- Adjusted frontend forms and backend DTOs to reflect new validation rules.
2026-01-28 21:48:23 +01:00

171 lines
4.7 KiB
TypeScript

"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { ArrowLeft } from "lucide-react";
import Link from "next/link";
import * as React from "react";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { useAuth } from "@/providers/auth-provider";
const registerSchema = z.object({
username: z
.string()
.min(3, { message: "Le pseudo doit faire au moins 3 caractères" })
.regex(/^[a-z0-9_]+$/, {
message: "Le pseudo ne doit contenir que des minuscules, chiffres et underscores",
}),
email: z.string().email({ message: "Email invalide" }),
password: z
.string()
.min(8, { message: "Le mot de passe doit faire au moins 8 caractères" })
.regex(/[A-Z]/, {
message: "Le mot de passe doit contenir au moins une majuscule",
})
.regex(/[a-z]/, {
message: "Le mot de passe doit contenir au moins une minuscule",
})
.regex(/[0-9]/, { message: "Le mot de passe doit contenir au moins un chiffre" })
.regex(/[^A-Za-z0-9]/, {
message: "Le mot de passe doit contenir au moins un caractère spécial",
}),
displayName: z.string().optional(),
});
type RegisterFormValues = z.infer<typeof registerSchema>;
export default function RegisterPage() {
const { register } = useAuth();
const [loading, setLoading] = React.useState(false);
const form = useForm<RegisterFormValues>({
resolver: zodResolver(registerSchema),
defaultValues: {
username: "",
email: "",
password: "",
displayName: "",
},
});
async function onSubmit(values: RegisterFormValues) {
setLoading(true);
try {
await register(values);
} catch (_error) {
// Error handled in useAuth
} finally {
setLoading(false);
}
}
return (
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-zinc-950 p-4">
<div className="w-full max-w-md space-y-4">
<Link
href="/"
className="inline-flex items-center text-sm text-muted-foreground hover:text-primary transition-colors"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Retour à l'accueil
</Link>
<Card>
<CardHeader>
<CardTitle className="text-2xl">Inscription</CardTitle>
<CardDescription>
Rejoignez la communauté MemeGoat dès aujourd'hui.
</CardDescription>
</CardHeader>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="displayName"
render={({ field }) => (
<FormItem>
<FormLabel>Nom d'affichage (Optionnel)</FormLabel>
<FormControl>
<Input placeholder="Le Roi des Chèvres" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Pseudo (minuscule)</FormLabel>
<FormControl>
<Input placeholder="supergoat" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="goat@example.com" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Mot de passe</FormLabel>
<FormControl>
<Input type="password" placeholder="••••••••" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="w-full" disabled={loading}>
{loading ? "Création du compte..." : "S'inscrire"}
</Button>
</form>
</Form>
</CardContent>
<CardFooter className="flex flex-col space-y-2">
<p className="text-sm text-center text-muted-foreground">
Vous avez déjà un compte ?{" "}
<Link href="/login" className="text-primary hover:underline font-medium">
Se connecter
</Link>
</p>
</CardFooter>
</Card>
</div>
</div>
);
}