diff --git a/src/features/admin/pages/ProfilePage.client.js b/src/features/admin/pages/ProfilePage.client.js index 925c116..b75344e 100644 --- a/src/features/admin/pages/ProfilePage.client.js +++ b/src/features/admin/pages/ProfilePage.client.js @@ -1,142 +1,83 @@ 'use client'; import { registerPage } from '../registry.js'; -import React, { useState, useEffect, useRef } from 'react'; -import { Card, Input, Button } from '@zen/core/shared/components'; +import { useState, useEffect, useRef } from 'react'; +import { Card, Input, Button, TabNav, UserAvatar } from '@zen/core/shared/components'; import { useToast } from '@zen/core/toast'; import AdminHeader from '../components/AdminHeader.js'; +const TABS = [ + { id: 'informations', label: 'Informations' }, + { id: 'photo', label: 'Photo de profil' }, +]; + const ProfilePage = ({ user: initialUser }) => { const toast = useToast(); + const fileInputRef = useRef(null); + const [activeTab, setActiveTab] = useState('informations'); const [user, setUser] = useState(initialUser); const [loading, setLoading] = useState(false); const [uploadingImage, setUploadingImage] = useState(false); - const [imagePreview, setImagePreview] = useState(null); - const fileInputRef = useRef(null); - const [formData, setFormData] = useState({ - name: initialUser?.name || '' - }); - - // Helper function to get image URL from storage key - const getImageUrl = (imageKey) => { - if (!imageKey) return null; - return `/zen/api/storage/${imageKey}`; - }; + const [formData, setFormData] = useState({ name: initialUser?.name || '' }); useEffect(() => { - if (initialUser) { - setFormData({ - name: initialUser.name || '' - }); - setImagePreview(getImageUrl(initialUser.image)); - } + if (initialUser) setFormData({ name: initialUser.name || '' }); }, [initialUser]); - const handleChange = (value) => { - setFormData(prev => ({ - ...prev, - name: value - })); - }; + const hasChanges = formData.name !== user?.name; const handleSubmit = async (e) => { e.preventDefault(); - if (!formData.name.trim()) { toast.error('Le nom est requis'); return; } - setLoading(true); - try { const response = await fetch('/zen/api/users/profile', { method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, + headers: { 'Content-Type': 'application/json' }, credentials: 'include', - body: JSON.stringify({ - name: formData.name.trim() - }) + body: JSON.stringify({ name: formData.name.trim() }), }); - const data = await response.json(); - - if (!response.ok || !data.success) { - throw new Error(data.error || 'Échec de la mise à jour du profil'); - } - + if (!response.ok || !data.success) throw new Error(data.error || 'Échec de la mise à jour du profil'); setUser(data.user); toast.success('Profil mis à jour avec succès'); - - // Refresh the page to update the user data in the header - setTimeout(() => { - window.location.reload(); - }, 1000); + setTimeout(() => window.location.reload(), 1000); } catch (error) { - console.error('Error updating profile:', error); toast.error(error.message || 'Échec de la mise à jour du profil'); } finally { setLoading(false); } }; - const handleReset = () => { - setFormData({ - name: user?.name || '' - }); - }; - const handleImageSelect = async (e) => { const file = e.target.files?.[0]; if (!file) return; - - // Validate file type if (!file.type.startsWith('image/')) { toast.error('Veuillez sélectionner un fichier image'); return; } - - // Validate file size (5MB) if (file.size > 5 * 1024 * 1024) { toast.error("L'image doit faire moins de 5MB"); return; } - - // Show preview - const reader = new FileReader(); - reader.onloadend = () => { - setImagePreview(reader.result); - }; - reader.readAsDataURL(file); - - // Upload image setUploadingImage(true); try { - const formData = new FormData(); - formData.append('file', file); - + const body = new FormData(); + body.append('file', file); const response = await fetch('/zen/api/users/profile/picture', { method: 'POST', credentials: 'include', - body: formData + body, }); - const data = await response.json(); - - if (!response.ok || !data.success) { - throw new Error(data.message || 'Échec du téléchargement de l\'image'); - } - + if (!response.ok || !data.success) throw new Error(data.message || "Échec du téléchargement de l'image"); setUser(data.user); - setImagePreview(getImageUrl(data.user.image)); toast.success('Photo de profil mise à jour avec succès'); } catch (error) { - console.error('Error uploading image:', error); - toast.error(error.message || 'Échec du téléchargement de l\'image'); - // Revert preview on error - setImagePreview(getImageUrl(user?.image)); + toast.error(error.message || "Échec du téléchargement de l'image"); } finally { setUploadingImage(false); } @@ -144,79 +85,103 @@ const ProfilePage = ({ user: initialUser }) => { const handleRemoveImage = async () => { if (!user?.image) return; - setUploadingImage(true); try { const response = await fetch('/zen/api/users/profile/picture', { method: 'DELETE', - credentials: 'include' + credentials: 'include', }); - const data = await response.json(); - - if (!response.ok || !data.success) { - throw new Error(data.message || 'Échec de la suppression de l\'image'); - } - + if (!response.ok || !data.success) throw new Error(data.message || "Échec de la suppression de l'image"); setUser(data.user); - setImagePreview(null); toast.success('Photo de profil supprimée avec succès'); } catch (error) { - console.error('Error removing image:', error); - toast.error(error.message || 'Échec de la suppression de l\'image'); + toast.error(error.message || "Échec de la suppression de l'image"); } finally { setUploadingImage(false); } }; - const getUserInitials = (name) => { - if (!name) return 'U'; - return name - .split(' ') - .map(n => n[0]) - .join('') - .toUpperCase() - .slice(0, 2); - }; - - const hasChanges = formData.name !== user?.name; - return (
- Téléchargez une nouvelle photo de profil. Taille max 5MB. -
+ + )} + + {activeTab === 'photo' && ( ++ Téléchargez une nouvelle photo de profil. Taille max 5MB. +
+