From b3778b22afc7fac67014a357b96738abd3048502 Mon Sep 17 00:00:00 2001 From: Guillermo Pages Date: Fri, 7 Nov 2025 08:55:53 +0100 Subject: [PATCH] feat(design): extend professional slate theme throughout manager portal Extended the professional slate gray color scheme from the landing page to all admin components and navigation. Replaced all purple/pink/indigo gradients with clean slate-900/600/200 colors for a timeless, enterprise-focused aesthetic. Changes: - Updated AdminClubsList.tsx with slate theme - Updated AdminClubDetail.tsx with slate theme - Updated AdminAuthGuard.tsx loading states with slate colors - Updated Navigation.tsx header, menu items, and footer with slate theme - Updated layout.tsx body and footer with slate colors - Added ~30 new translation keys to dictionaries/en.json Design system: - Primary: slate-900 (almost black) - Text: slate-900 (headings), slate-600 (body), slate-500 (muted) - Borders: slate-200 (2px), slate-300 on hover - Backgrounds: white, slate-50, slate-100 - Professional rounded corners: rounded-2xl, rounded-xl, rounded-lg - Clean typography: tracking-tight, font-bold/medium/light --- dictionaries/en.json | 32 ++++- .../[locale]/admin/clubs/AdminClubsList.tsx | 74 +++++----- .../admin/clubs/[club_id]/AdminClubDetail.tsx | 126 +++++++++--------- src/app/[locale]/layout.tsx | 8 +- src/components/AdminAuthGuard.tsx | 12 +- src/components/Navigation.tsx | 107 ++++++++------- 6 files changed, 193 insertions(+), 166 deletions(-) diff --git a/dictionaries/en.json b/dictionaries/en.json index 01af7b5..ca68bf0 100644 --- a/dictionaries/en.json +++ b/dictionaries/en.json @@ -836,5 +836,35 @@ "swap request": "swap request", "Waiting for": "Waiting for", "approval(s)": "approval(s)", - "All approved": "All approved" + "All approved": "All approved", + "Club Management": "Club Management", + "View and manage your venue locations": "View and manage your venue locations", + "Clubs": "Clubs", + "Coming soon": "Coming soon", + "Schedules": "Schedules", + "Bookings": "Bookings", + "Loading clubs...": "Loading clubs...", + "Error Loading Clubs": "Error Loading Clubs", + "Error code": "Error code", + "No Clubs Assigned": "No Clubs Assigned", + "You are not currently assigned as an administrator for any clubs. Contact your organization to request access.": "You are not currently assigned as an administrator for any clubs. Contact your organization to request access.", + "Courts": "Courts", + "Loading club details...": "Loading club details...", + "Access Denied": "Access Denied", + "Back to clubs": "Back to clubs", + "Error Loading Club": "Error Loading Club", + "Provider Information": "Provider Information", + "Type": "Type", + "Manages Slot Storage": "Manages Slot Storage", + "Supports Payment Verification": "Supports Payment Verification", + "No courts configured": "No courts configured", + "Slot Definitions": "Slot Definitions", + "No slot definitions configured": "No slot definitions configured", + "Slot definition": "Slot definition", + "Upcoming Slots": "Upcoming Slots", + "No upcoming slots available": "No upcoming slots available", + "Checking authentication...": "Checking authentication...", + "Redirecting to login...": "Redirecting to login...", + "Please log in to access the venue management portal.": "Please log in to access the venue management portal.", + "If you are a venue administrator and do not have access, please contact support.": "If you are a venue administrator and do not have access, please contact support." } diff --git a/src/app/[locale]/admin/clubs/AdminClubsList.tsx b/src/app/[locale]/admin/clubs/AdminClubsList.tsx index d754fb6..24fce3b 100644 --- a/src/app/[locale]/admin/clubs/AdminClubsList.tsx +++ b/src/app/[locale]/admin/clubs/AdminClubsList.tsx @@ -35,10 +35,10 @@ export default function AdminClubsList() { // Loading state if (loading) { return ( -
+
- -

{t('Loading clubs...')}

+ +

{t('Loading clubs...')}

); @@ -47,19 +47,19 @@ export default function AdminClubsList() { // Authentication error (401) if (error && error.status === 401) { return ( -
+
-
+
- +
-

+

{t('Authentication Required')}

-

+

{t('Please log in to access the venue management portal.')}

-

+

{t('If you are a venue administrator and do not have access, please contact support.')}

@@ -73,19 +73,19 @@ export default function AdminClubsList() { // Other API errors if (error) { return ( -
+
-
+
-

+

{t('Error Loading Clubs')}

-

+

{error.detail}

-

+

{t('Error code')}: {error.code}

@@ -99,23 +99,23 @@ export default function AdminClubsList() { // No clubs assigned if (!clubs || clubs.length === 0) { return ( -
+
-

+

{t('Club Management')}

-

+

{t('View and manage your venue locations')}

-
-
- -

+
+
+ +

{t('No Clubs Assigned')}

-

+

{t('You are not currently assigned as an administrator for any clubs. Contact your organization to request access.')}

@@ -126,12 +126,12 @@ export default function AdminClubsList() { // Success - render clubs list return ( -
-
-

+
+
+

{t('Club Management')}

-

+

{t('View and manage your venue locations')}

@@ -141,27 +141,27 @@ export default function AdminClubsList() { -
-
-
- +
+
+
+
-

+

{club.name}

-

+

{club.timezone}

-
-
- {t('Courts')} - {club.courts} +
+
+ {t('Courts')} + {club.courts}
diff --git a/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx b/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx index 27aa527..9e8140f 100644 --- a/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx +++ b/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx @@ -39,10 +39,10 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp // Loading state if (loading) { return ( -
+
- -

{t('Loading club details...')}

+ +

{t('Loading club details...')}

); @@ -51,16 +51,16 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp // Authentication error (401) if (error && error.status === 401) { return ( -
+
-
+
- +
-

+

{t('Authentication Required')}

-

+

{t('Please log in to access the venue management portal.')}

@@ -74,21 +74,21 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp // Forbidden error (403) if (error && error.status === 403) { return ( -
+
-
+
-

+

{t('Access Denied')}

-

+

{error.detail}

{t('Back to clubs')} @@ -104,24 +104,24 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp // Other API errors if (error) { return ( -
+
-
+
-
-

+
+

{t('Error Loading Club')}

-

+

{error.detail}

-

+

{t('Error code')}: {error.code}

{t('Back to clubs')} @@ -140,12 +140,12 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp // Success - render club detail return ( -
+
{/* Breadcrumb */} -
+
{t('Back to clubs')} @@ -153,45 +153,43 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
{/* Club Header */} -
-
-
- +
+
+
+
-

+

{clubDetail.club.name}

-
-
- - {clubDetail.club.timezone} -
+
+ + {clubDetail.club.timezone}
{/* Provider Info */} -
-
- -

{t('Provider Information')}

+
+
+ +

{t('Provider Information')}

-
-
- {t('Type')}: - {clubDetail.provider.remote_type} +
+
+ {t('Type')}: + {clubDetail.provider.remote_type}
-
- {t('Manages Slot Storage')}: - +
+ {t('Manages Slot Storage')}: + {clubDetail.provider.capabilities.manages_slot_storage ? t('Yes') : t('No')}
-
- {t('Supports Payment Verification')}: - +
+ {t('Supports Payment Verification')}: + {clubDetail.provider.capabilities.supports_payment_verification ? t('Yes') : t('No')}
@@ -199,18 +197,18 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
{/* Courts */} -
-

{t('Courts')}

+
+

{t('Courts')}

{clubDetail.courts.length === 0 ? ( -

{t('No courts configured')}

+

{t('No courts configured')}

) : (
{clubDetail.courts.map((court) => (
-

{court.name}

+

{court.name}

))}
@@ -218,21 +216,21 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
{/* Slot Definitions */} -
-
- -

{t('Slot Definitions')}

+
+
+ +

{t('Slot Definitions')}

{clubDetail.slot_definitions.length === 0 ? ( -

{t('No slot definitions configured')}

+

{t('No slot definitions configured')}

) : (
{clubDetail.slot_definitions.map((slotDef, index) => (
-

{t('Slot definition')} #{index + 1}

+

{t('Slot definition')} #{index + 1}

))}
@@ -240,18 +238,18 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
{/* Upcoming Slots */} -
-

{t('Upcoming Slots')}

+
+

{t('Upcoming Slots')}

{clubDetail.upcoming_slots.length === 0 ? ( -

{t('No upcoming slots available')}

+

{t('No upcoming slots available')}

) : (
{clubDetail.upcoming_slots.map((slot, index) => (
-

{t('Slot')} #{index + 1}

+

{t('Slot')} #{index + 1}

))}
diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index bf07ef9..b075000 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -26,20 +26,20 @@ export default async function RootLayout({ return ( - +
{children}
-