From 8e78ce50b59cc33e02cb0dac7e75a83a33c75f23 Mon Sep 17 00:00:00 2001 From: Tetardtek Date: Sun, 15 Mar 2026 02:45:50 +0100 Subject: [PATCH] feat: profile avatar, callback setUser fix, admin description/thumbnail, pagination limit=100 --- frontend/src/components/UserBadge.tsx | 11 ++ frontend/src/context/AuthContext.tsx | 1 + frontend/src/pages/AdminPage.tsx | 28 +++-- frontend/src/pages/CallbackPage.tsx | 19 +++- frontend/src/pages/ProfilePage.tsx | 149 +++++++++++++++++--------- 5 files changed, 144 insertions(+), 64 deletions(-) diff --git a/frontend/src/components/UserBadge.tsx b/frontend/src/components/UserBadge.tsx index 2aba2b5..045c4b2 100644 --- a/frontend/src/components/UserBadge.tsx +++ b/frontend/src/components/UserBadge.tsx @@ -9,6 +9,17 @@ export default function UserBadge({ user }: UserBadgeProps) { return ( + {user.avatar ? ( + {user.nickname} + ) : ( + + {user.nickname[0].toUpperCase()} + + )} {user.nickname} {planLabel} diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx index 475e37b..65ef699 100644 --- a/frontend/src/context/AuthContext.tsx +++ b/frontend/src/context/AuthContext.tsx @@ -5,6 +5,7 @@ export interface User { id: string; email: string | null; nickname: string; + avatar?: string | null; plan?: { slug: string; name: string; level: number } | null; subscriptionLevel?: number; roles: string[]; diff --git a/frontend/src/pages/AdminPage.tsx b/frontend/src/pages/AdminPage.tsx index d671aec..063cdeb 100644 --- a/frontend/src/pages/AdminPage.tsx +++ b/frontend/src/pages/AdminPage.tsx @@ -97,7 +97,8 @@ function VideosTab() { const [fetchError, setFetchError] = useState(null); const [actionError, setActionError] = useState(null); const [form, setForm] = useState({ - title: '', storageType: 'youtube', storageKey: '', + title: '', description: '', thumbnailUrl: '', + storageType: 'youtube', storageKey: '', requiredLevel: 0, isPublished: false, }); const [saving, setSaving] = useState(false); @@ -106,7 +107,7 @@ function VideosTab() { const [error, setError] = useState(null); useEffect(() => { - apiFetch<{ success: boolean; data: { videos: Video[] } }>('/admin/videos') + apiFetch<{ success: boolean; data: { videos: Video[] } }>('/admin/videos?limit=100') .then((r) => setVideos(r.data.videos)) .catch(() => setFetchError('Impossible de charger les vidéos.')) .finally(() => setLoading(false)); @@ -144,7 +145,7 @@ function VideosTab() { { method: 'POST', body: JSON.stringify(form) } ); setVideos((v) => [r.data.video, ...v]); - setForm({ title: '', storageType: 'youtube', storageKey: '', requiredLevel: 0, isPublished: false }); + setForm({ title: '', description: '', thumbnailUrl: '', storageType: 'youtube', storageKey: '', requiredLevel: 0, isPublished: false }); } catch { setError('Erreur lors de la création.'); } @@ -189,6 +190,21 @@ function VideosTab() { className="rounded border border-od-border bg-od-bg px-3 py-2 text-sm text-od-text placeholder-od-muted outline-none focus:border-od-accent" /> +