From adfe136d74bf7ddd14f33819138e495ff4548329 Mon Sep 17 00:00:00 2001 From: Seazn Date: Sun, 15 Mar 2026 14:18:27 +0100 Subject: [PATCH] feat: add guest role to user management and update statistics display --- src/app/admin/user-management/page.tsx | 13 +++++--- src/app/coffee-abonnements/summary/page.tsx | 26 +++++++++++++++- src/app/components/nav/Header.tsx | 34 ++++++++++----------- src/app/profile/components/mediaSection.tsx | 10 ++++-- src/app/profile/page.tsx | 23 +++++++++++++- 5 files changed, 81 insertions(+), 25 deletions(-) diff --git a/src/app/admin/user-management/page.tsx b/src/app/admin/user-management/page.tsx index 9af0735..278ce0e 100644 --- a/src/app/admin/user-management/page.tsx +++ b/src/app/admin/user-management/page.tsx @@ -14,7 +14,7 @@ import useAuthStore from '../../store/authStore' type UserType = 'personal' | 'company' type UserStatus = 'active' | 'pending' | 'disabled' | 'inactive' | 'suspended' | 'archived' -type UserRole = 'user' | 'admin' +type UserRole = 'user' | 'admin' | 'guest' interface User { id: number @@ -32,7 +32,7 @@ interface User { const STATUSES: UserStatus[] = ['active','pending','disabled','inactive'] const TYPES: UserType[] = ['personal','company'] -const ROLES: UserRole[] = ['user','admin'] +const ROLES: UserRole[] = ['user','admin','guest'] export default function AdminUserManagementPage() { const { isAdmin } = useAdminUsers() @@ -122,6 +122,7 @@ export default function AdminUserManagementPage() { const stats = useMemo(() => ({ total: allUsers.length, admins: allUsers.filter(u => u.role === 'admin').length, + guests: allUsers.filter(u => u.role === 'guest').length, personal: allUsers.filter(u => u.user_type === 'personal').length, company: allUsers.filter(u => u.user_type === 'company').length, active: allUsers.filter(u => u.status === 'active').length, @@ -232,7 +233,7 @@ export default function AdminUserManagementPage() { t==='personal' ? badge('Personal','blue') : badge('Company','purple') const roleBadge = (r: UserRole) => - r==='admin' ? badge('Admin','indigo') : badge('User','gray') + r==='admin' ? badge('Admin','indigo') : r==='guest' ? badge('Guest','amber') : badge('User','gray') // Action handler for opening edit modal const onEdit = (id: string) => { @@ -256,7 +257,7 @@ export default function AdminUserManagementPage() { {/* Statistic Section + Verify Button */}
-
+
Total Users
{stats.total}
@@ -265,6 +266,10 @@ export default function AdminUserManagementPage() {
Admins
{stats.admins}
+
+
Guests
+
{stats.guests}
+
Personal
{stats.personal}
diff --git a/src/app/coffee-abonnements/summary/page.tsx b/src/app/coffee-abonnements/summary/page.tsx index b3b549d..2973494 100644 --- a/src/app/coffee-abonnements/summary/page.tsx +++ b/src/app/coffee-abonnements/summary/page.tsx @@ -327,7 +327,31 @@ export default function SummaryPage() { > Fill fields with logged in data - {/* "For someone else" is disabled for now — only self-subscriptions */} + {/* Toggle: For myself / For someone else */} +
+ + +
{/* inputs translated */}
diff --git a/src/app/components/nav/Header.tsx b/src/app/components/nav/Header.tsx index 194483c..1ba6636 100644 --- a/src/app/components/nav/Header.tsx +++ b/src/app/components/nav/Header.tsx @@ -504,18 +504,18 @@ export default function Header({ setGlobalLoggingOut }: HeaderProps) { Personal Matrix )} - - {DISPLAY_ABONEMENTS && hasSubscribePerm && ( - - )} )} + {userPresent && DISPLAY_ABONEMENTS && hasSubscribePerm && ( + + )} + {/* Information dropdown already removed here */} @@ -737,16 +737,16 @@ export default function Header({ setGlobalLoggingOut }: HeaderProps) { Personal Matrix )} - {DISPLAY_ABONEMENTS && hasSubscribePerm && ( - - )} )} + {DISPLAY_ABONEMENTS && hasSubscribePerm && ( + + )} {/* Admin navigation – LAST */} {isAdmin && ( diff --git a/src/app/profile/components/mediaSection.tsx b/src/app/profile/components/mediaSection.tsx index 2a5c3bc..10a821e 100644 --- a/src/app/profile/components/mediaSection.tsx +++ b/src/app/profile/components/mediaSection.tsx @@ -23,8 +23,14 @@ export default function MediaSection({ documents }: { documents: any[] }) { {doc.type} {doc.uploaded} - - + {doc.signedUrl ? ( + <> + Download + Preview + + ) : ( + No file + )} ))} diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index 0b88028..a8d2526 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -184,7 +184,28 @@ export default function ProfilePage() { } }, [profileDataApi, user, progressPercent]) - const documents = Array.isArray(mediaData?.documents) ? mediaData.documents : [] + const documents = React.useMemo(() => { + const contracts = Array.isArray(mediaData?.contracts) ? mediaData.contracts : [] + const idDocs = Array.isArray(mediaData?.idDocuments) ? mediaData.idDocuments : [] + + const contractItems = contracts.map((doc: any) => ({ + id: `contract-${doc.id}`, + name: doc.original_filename || 'Contract', + type: 'Contract', + uploaded: doc.created_at ? new Date(doc.created_at).toLocaleDateString() : '-', + signedUrl: doc.signedUrl, + })) + + const idDocItems = idDocs.filter((d: any) => d.object_storage_id).map((doc: any) => ({ + id: `id-${doc.user_id_document_id}-${doc.side}`, + name: doc.original_filename || `ID Document (${doc.side})`, + type: `${doc.id_type || 'ID'} – ${doc.side}`, + uploaded: doc.expiry_date ? new Date(doc.expiry_date).toLocaleDateString() : '-', + signedUrl: doc.signedUrl, + })) + + return [...contractItems, ...idDocItems] + }, [mediaData]) useEffect(() => { if (showRefreshing && !profileLoading && !mediaLoading && !completionLoading) {