/** * Form Validation Schemas * Using Zod for type-safe validation */ import { z } from "zod" /** * Login form validation schema */ export const loginSchema = z.object({ email: z .string() .email("Adresse email invalide") .min(1, "Email requis"), password: z .string() .min(1, "Mot de passe requis") .min(6, "Le mot de passe doit contenir au moins 6 caractères"), }) export type LoginFormData = z.infer /** * Registration form validation schema */ export const registerSchema = z.object({ firstName: z .string() .min(1, "Prénom requis") .min(2, "Le prénom doit contenir au moins 2 caractères") .max(50, "Le prénom ne doit pas dépasser 50 caractères"), lastName: z .string() .min(1, "Nom requis") .min(2, "Le nom doit contenir au moins 2 caractères") .max(50, "Le nom ne doit pas dépasser 50 caractères"), email: z .string() .email("Adresse email invalide") .min(1, "Email requis"), citizenId: z .string() .min(1, "Numéro de citoyen requis") .min(5, "Le numéro de citoyen doit contenir au moins 5 caractères") .max(20, "Le numéro de citoyen ne doit pas dépasser 20 caractères"), password: z .string() .min(8, "Le mot de passe doit contenir au moins 8 caractères") .regex(/[A-Z]/, "Le mot de passe doit contenir au moins une majuscule") .regex(/[0-9]/, "Le mot de passe doit contenir au moins un chiffre") .regex(/[!@#$%^&*]/, "Le mot de passe doit contenir au moins un caractère spécial (!@#$%^&*)"), passwordConfirm: z .string() .min(1, "Confirmation du mot de passe requise"), }).refine( (data) => data.password === data.passwordConfirm, { message: "Les mots de passe ne correspondent pas", path: ["passwordConfirm"], } ) export type RegisterFormData = z.infer /** * Profile update validation schema */ export const profileUpdateSchema = z.object({ firstName: z .string() .min(1, "Prénom requis") .min(2, "Le prénom doit contenir au moins 2 caractères") .max(50, "Le prénom ne doit pas dépasser 50 caractères"), lastName: z .string() .min(1, "Nom requis") .min(2, "Le nom doit contenir au least 2 caractères") .max(50, "Le nom ne doit pas dépasser 50 caractères"), email: z .string() .email("Adresse email invalide") .min(1, "Email requis"), phone: z .string() .regex(/^[+\d\s\-()]*$/, "Numéro de téléphone invalide") .optional() .or(z.literal("")), address: z .string() .max(100, "L'adresse ne doit pas dépasser 100 caractères") .optional() .or(z.literal("")), city: z .string() .max(50, "La ville ne doit pas dépasser 50 caractères") .optional() .or(z.literal("")), postalCode: z .string() .regex(/^\d{5}$/, "Code postal invalide (doit être 5 chiffres)") .optional() .or(z.literal("")), country: z .string() .max(50, "Le pays ne doit pas dépasser 50 caractères") .optional() .or(z.literal("")), }) export type ProfileUpdateFormData = z.infer /** * Password change validation schema */ export const passwordChangeSchema = z.object({ currentPassword: z .string() .min(1, "Mot de passe actuel requis"), newPassword: z .string() .min(8, "Le nouveau mot de passe doit contenir au moins 8 caractères") .regex(/[A-Z]/, "Le mot de passe doit contenir au moins une majuscule") .regex(/[0-9]/, "Le mot de passe doit contenir au moins un chiffre") .regex(/[!@#$%^&*]/, "Le mot de passe doit contenir au moins un caractère spécial"), confirmPassword: z .string() .min(1, "Confirmation du mot de passe requise"), }).refine( (data) => data.newPassword === data.confirmPassword, { message: "Les nouveaux mots de passe ne correspondent pas", path: ["confirmPassword"], } ) export type PasswordChangeFormData = z.infer /** * Vote submission validation schema */ export const voteSubmissionSchema = z.object({ electionId: z .number() .min(1, "Élection requise"), choix: z .string() .min(1, "Candidat requis"), }) export type VoteSubmissionFormData = z.infer