Mon Profil
+Gérez vos informations personnelles
+diff --git a/dev.db b/dev.db index 5629128..26e613c 100644 Binary files a/dev.db and b/dev.db differ diff --git a/src/actions/profile.ts b/src/actions/profile.ts new file mode 100644 index 0000000..f4dc3c7 --- /dev/null +++ b/src/actions/profile.ts @@ -0,0 +1,58 @@ +'use server'; + +import { auth } from '@/lib/auth'; +import { updateUserProfile, updateUserPassword, getUserById } from '@/services/auth'; + +export async function getProfileAction() { + const session = await auth(); + if (!session?.user?.id) { + return { success: false, error: 'Non authentifié', data: null }; + } + + const user = await getUserById(session.user.id); + if (!user) { + return { success: false, error: 'Utilisateur non trouvé', data: null }; + } + + return { + success: true, + data: { + id: user.id, + name: user.name, + email: user.email, + createdAt: user.createdAt, + }, + }; +} + +export async function updateProfileAction(data: { name?: string; email?: string }) { + const session = await auth(); + if (!session?.user?.id) { + return { success: false, error: 'Non authentifié' }; + } + + const result = await updateUserProfile(session.user.id, data); + return result; +} + +export async function updatePasswordAction(data: { + currentPassword: string; + newPassword: string; +}) { + const session = await auth(); + if (!session?.user?.id) { + return { success: false, error: 'Non authentifié' }; + } + + if (data.newPassword.length < 6) { + return { success: false, error: 'Le nouveau mot de passe doit faire au moins 6 caractères' }; + } + + const result = await updateUserPassword( + session.user.id, + data.currentPassword, + data.newPassword + ); + return result; +} + diff --git a/src/app/profile/PasswordForm.tsx b/src/app/profile/PasswordForm.tsx new file mode 100644 index 0000000..37b0a69 --- /dev/null +++ b/src/app/profile/PasswordForm.tsx @@ -0,0 +1,115 @@ +'use client'; + +import { useState, useTransition } from 'react'; +import { Input, Button } from '@/components/ui'; +import { updatePasswordAction } from '@/actions/profile'; + +export function PasswordForm() { + const [isPending, startTransition] = useTransition(); + const [currentPassword, setCurrentPassword] = useState(''); + const [newPassword, setNewPassword] = useState(''); + const [confirmPassword, setConfirmPassword] = useState(''); + const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); + + const canSubmit = + currentPassword.length > 0 && + newPassword.length >= 6 && + newPassword === confirmPassword; + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + setMessage(null); + + if (newPassword !== confirmPassword) { + setMessage({ type: 'error', text: 'Les mots de passe ne correspondent pas' }); + return; + } + + startTransition(async () => { + const result = await updatePasswordAction({ currentPassword, newPassword }); + + if (result.success) { + setMessage({ type: 'success', text: 'Mot de passe modifié avec succès' }); + setCurrentPassword(''); + setNewPassword(''); + setConfirmPassword(''); + } else { + setMessage({ type: 'error', text: result.error || 'Erreur lors de la modification' }); + } + }); + } + + return ( +
+ ); +} + diff --git a/src/app/profile/ProfileForm.tsx b/src/app/profile/ProfileForm.tsx new file mode 100644 index 0000000..60b0879 --- /dev/null +++ b/src/app/profile/ProfileForm.tsx @@ -0,0 +1,84 @@ +'use client'; + +import { useState, useTransition } from 'react'; +import { useRouter } from 'next/navigation'; +import { Input, Button } from '@/components/ui'; +import { updateProfileAction } from '@/actions/profile'; + +interface ProfileFormProps { + initialData: { + name: string; + email: string; + }; +} + +export function ProfileForm({ initialData }: ProfileFormProps) { + const router = useRouter(); + const [isPending, startTransition] = useTransition(); + const [name, setName] = useState(initialData.name); + const [email, setEmail] = useState(initialData.email); + const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); + + const hasChanges = name !== initialData.name || email !== initialData.email; + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + setMessage(null); + + startTransition(async () => { + const result = await updateProfileAction({ name, email }); + + if (result.success) { + setMessage({ type: 'success', text: 'Profil mis à jour avec succès' }); + router.refresh(); + } else { + setMessage({ type: 'error', text: result.error || 'Erreur lors de la mise à jour' }); + } + }); + } + + return ( + + ); +} + diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx new file mode 100644 index 0000000..2c18ce2 --- /dev/null +++ b/src/app/profile/page.tsx @@ -0,0 +1,75 @@ +import { auth } from '@/lib/auth'; +import { redirect } from 'next/navigation'; +import { getUserById } from '@/services/auth'; +import { ProfileForm } from './ProfileForm'; +import { PasswordForm } from './PasswordForm'; + +export default async function ProfilePage() { + const session = await auth(); + + if (!session?.user?.id) { + redirect('/login'); + } + + const user = await getUserById(session.user.id); + + if (!user) { + redirect('/login'); + } + + return ( +Gérez vos informations personnelles
+