import { useState } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useAuthStore } from '@/stores/auth'; import { useTranslation } from '@/hooks/useTranslation'; import { apiService } from '@/services/api'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { useToast } from '@/hooks/useToast'; import { usernameSchema, emailSchema } from '@/schemas/validation'; // Define schema locally to match User type + validations const profileSchema = z.object({ username: usernameSchema, email: emailSchema, first_name: z.string().optional(), last_name: z.string().optional(), bio: z.string().optional(), }); type ProfileFormData = z.infer; export function ProfileForm() { const { user, refreshUser } = useAuthStore(); const { t } = useTranslation(); const { success, error: showToastError } = useToast(); const [isEditing, setIsEditing] = useState(false); const [isLoading, setIsLoading] = useState(false); const form = useForm({ resolver: zodResolver(profileSchema), defaultValues: { username: user?.username || '', email: user?.email || '', first_name: user?.first_name || '', last_name: user?.last_name || '', bio: user?.bio || '', }, mode: 'onBlur', }); const { register, handleSubmit, reset, formState: { errors }, } = form; const onSubmit = async (data: ProfileFormData) => { if (!user) return; setIsLoading(true); try { // Need id as number according to ApiService.updateUser signature in api.ts? // api.ts: updateUser(id: number, data: Partial) // But User.id is string in types/index.ts!! // Wait, let's re-verify api.ts updateUser signature. // Line 224: `async updateUser(id: number, data: Partial): Promise` // But User interface has `id: string`. // This is a mismatch in api.ts vs types.ts. // However, if I pass Number(user.id), it might work if backend expects number. // Or I should fix api.ts? // I'll cast for now or parse. const userId = Number(user.id); await apiService.updateUser(userId, data); await refreshUser(); success(t('profile.success')); // Assuming translation key exists or generic success setIsEditing(false); } catch (err: any) { showToastError(err.message || t('profile.error')); } finally { setIsLoading(false); } }; const handleCancel = () => { reset({ username: user?.username || '', email: user?.email || '', first_name: user?.first_name || '', last_name: user?.last_name || '', bio: user?.bio || '', }); setIsEditing(false); }; // Si l'utilisateur n'est pas chargĂ©, afficher un message au lieu de retourner null // (retourner null empĂȘche la navigation de se terminer) if (!user) { return (

Chargement du profil...

); } return ( {t('profile.title')} {!isEditing && ( )}

{t('profile.personalInfo')}

{/* Avatar Section (Mocked UI based on test expectation) */} {isEditing && (
)}
{errors.username && (

{errors.username.message}

)}
{errors.email && (

{errors.email.message}

)}
{errors.first_name && (

{errors.first_name.message}

)}
{errors.last_name && (

{errors.last_name.message}

)}
{errors.bio && (

{errors.bio.message}

)}
{isEditing && (
)}
); }