feat(design): extend professional slate theme throughout manager portal
continuous-integration/drone/push Build is passing Details

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
master
Guillermo Pages 1 month ago
parent af1f119906
commit b3778b22af

@ -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."
}

@ -35,10 +35,10 @@ export default function AdminClubsList() {
// Loading state
if (loading) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="flex flex-col items-center justify-center space-y-4">
<Loader2 className="w-12 h-12 text-indigo-600 animate-spin" />
<p className="text-gray-600">{t('Loading clubs...')}</p>
<Loader2 className="w-12 h-12 text-slate-900 animate-spin" />
<p className="text-slate-600 font-medium">{t('Loading clubs...')}</p>
</div>
</div>
);
@ -47,19 +47,19 @@ export default function AdminClubsList() {
// Authentication error (401)
if (error && error.status === 401) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="max-w-2xl mx-auto">
<div className="bg-yellow-50 border border-yellow-200 rounded-xl p-8">
<div className="bg-amber-50 border-2 border-amber-200 rounded-2xl p-8">
<div className="flex items-start space-x-4">
<Lock className="w-8 h-8 text-yellow-600 flex-shrink-0 mt-1" />
<Lock className="w-8 h-8 text-amber-700 flex-shrink-0 mt-1" />
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-4">
<h2 className="text-2xl font-bold text-slate-900 mb-4">
{t('Authentication Required')}
</h2>
<p className="text-gray-700 mb-4">
<p className="text-slate-700 mb-4 leading-relaxed">
{t('Please log in to access the venue management portal.')}
</p>
<p className="text-sm text-gray-600">
<p className="text-sm text-slate-600">
{t('If you are a venue administrator and do not have access, please contact support.')}
</p>
</div>
@ -73,19 +73,19 @@ export default function AdminClubsList() {
// Other API errors
if (error) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="max-w-2xl mx-auto">
<div className="bg-red-50 border border-red-200 rounded-xl p-8">
<div className="bg-red-50 border-2 border-red-200 rounded-2xl p-8">
<div className="flex items-start space-x-4">
<AlertCircle className="w-8 h-8 text-red-600 flex-shrink-0 mt-1" />
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-4">
<h2 className="text-2xl font-bold text-slate-900 mb-4">
{t('Error Loading Clubs')}
</h2>
<p className="text-gray-700 mb-4">
<p className="text-slate-700 mb-4 leading-relaxed">
{error.detail}
</p>
<p className="text-sm text-gray-600 font-mono">
<p className="text-sm text-slate-600 font-mono">
{t('Error code')}: {error.code}
</p>
</div>
@ -99,23 +99,23 @@ export default function AdminClubsList() {
// No clubs assigned
if (!clubs || clubs.length === 0) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-2">
<h1 className="text-4xl font-bold text-slate-900 mb-2 tracking-tight">
{t('Club Management')}
</h1>
<p className="text-gray-600">
<p className="text-lg text-slate-600 font-light">
{t('View and manage your venue locations')}
</p>
</div>
<div className="bg-blue-50 border border-blue-200 rounded-xl p-8">
<div className="flex flex-col items-center text-center space-y-4">
<Building className="w-16 h-16 text-blue-600" />
<h2 className="text-xl font-bold text-gray-900">
<div className="bg-slate-50 border-2 border-slate-200 rounded-2xl p-12">
<div className="flex flex-col items-center text-center space-y-6">
<Building className="w-20 h-20 text-slate-400" />
<h2 className="text-2xl font-bold text-slate-900">
{t('No Clubs Assigned')}
</h2>
<p className="text-gray-600 max-w-md">
<p className="text-slate-600 max-w-md leading-relaxed">
{t('You are not currently assigned as an administrator for any clubs. Contact your organization to request access.')}
</p>
</div>
@ -126,12 +126,12 @@ export default function AdminClubsList() {
// Success - render clubs list
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-2">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="mb-10">
<h1 className="text-4xl font-bold text-slate-900 mb-3 tracking-tight">
{t('Club Management')}
</h1>
<p className="text-gray-600">
<p className="text-lg text-slate-600 font-light">
{t('View and manage your venue locations')}
</p>
</div>
@ -141,27 +141,27 @@ export default function AdminClubsList() {
<Link
key={club.club_id}
href={`/${locale}/admin/clubs/${club.club_id}`}
className="bg-white border border-gray-200 rounded-xl p-6 hover:shadow-lg hover:border-indigo-300 transition-all duration-200"
className="group bg-white border-2 border-slate-200 rounded-2xl p-6 hover:border-slate-300 hover:shadow-xl transition-all duration-200"
>
<div className="flex items-start justify-between mb-4">
<div className="flex items-start space-x-4">
<div className="p-3 bg-indigo-100 rounded-lg">
<Building className="w-6 h-6 text-indigo-600" />
<div className="flex items-start justify-between mb-5">
<div className="flex items-start space-x-4 flex-1">
<div className="p-3 bg-slate-900 rounded-lg group-hover:scale-110 transition-transform duration-200">
<Building className="w-6 h-6 text-white" />
</div>
<div className="flex-1">
<h3 className="text-lg font-bold text-gray-900 mb-1">
<h3 className="text-xl font-bold text-slate-900 mb-2 group-hover:text-slate-700 transition-colors">
{club.name}
</h3>
<p className="text-sm text-gray-600">
<p className="text-sm text-slate-600 font-medium">
{club.timezone}
</p>
</div>
</div>
</div>
<div className="mt-4 pt-4 border-t border-gray-100">
<div className="flex items-center justify-between text-sm">
<span className="text-gray-600">{t('Courts')}</span>
<span className="font-semibold text-gray-900">{club.courts}</span>
<div className="mt-5 pt-5 border-t-2 border-slate-100">
<div className="flex items-center justify-between">
<span className="text-sm font-medium text-slate-600">{t('Courts')}</span>
<span className="text-2xl font-bold text-slate-900">{club.courts}</span>
</div>
</div>
</Link>

@ -39,10 +39,10 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
// Loading state
if (loading) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="flex flex-col items-center justify-center space-y-4">
<Loader2 className="w-12 h-12 text-indigo-600 animate-spin" />
<p className="text-gray-600">{t('Loading club details...')}</p>
<Loader2 className="w-12 h-12 text-slate-900 animate-spin" />
<p className="text-slate-600 font-medium">{t('Loading club details...')}</p>
</div>
</div>
);
@ -51,16 +51,16 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
// Authentication error (401)
if (error && error.status === 401) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="max-w-2xl mx-auto">
<div className="bg-yellow-50 border border-yellow-200 rounded-xl p-8">
<div className="bg-amber-50 border-2 border-amber-200 rounded-2xl p-8">
<div className="flex items-start space-x-4">
<Lock className="w-8 h-8 text-yellow-600 flex-shrink-0 mt-1" />
<Lock className="w-8 h-8 text-amber-700 flex-shrink-0 mt-1" />
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-4">
<h2 className="text-2xl font-bold text-slate-900 mb-4">
{t('Authentication Required')}
</h2>
<p className="text-gray-700 mb-4">
<p className="text-slate-700 leading-relaxed">
{t('Please log in to access the venue management portal.')}
</p>
</div>
@ -74,21 +74,21 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
// Forbidden error (403)
if (error && error.status === 403) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="max-w-2xl mx-auto">
<div className="bg-red-50 border border-red-200 rounded-xl p-8">
<div className="bg-red-50 border-2 border-red-200 rounded-2xl p-8">
<div className="flex items-start space-x-4">
<Lock className="w-8 h-8 text-red-600 flex-shrink-0 mt-1" />
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-4">
<h2 className="text-2xl font-bold text-slate-900 mb-4">
{t('Access Denied')}
</h2>
<p className="text-gray-700 mb-4">
<p className="text-slate-700 mb-6 leading-relaxed">
{error.detail}
</p>
<Link
href={`/${locale}/admin/clubs`}
className="inline-flex items-center text-indigo-600 hover:text-indigo-700 font-medium"
className="inline-flex items-center px-4 py-2 bg-slate-900 text-white font-semibold rounded-lg hover:bg-slate-800 transition-colors"
>
<ArrowLeft className="w-4 h-4 mr-2" />
{t('Back to clubs')}
@ -104,24 +104,24 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
// Other API errors
if (error) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="max-w-2xl mx-auto">
<div className="bg-red-50 border border-red-200 rounded-xl p-8">
<div className="bg-red-50 border-2 border-red-200 rounded-2xl p-8">
<div className="flex items-start space-x-4">
<AlertCircle className="w-8 h-8 text-red-600 flex-shrink-0 mt-1" />
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-4">
<div className="flex-1">
<h2 className="text-2xl font-bold text-slate-900 mb-4">
{t('Error Loading Club')}
</h2>
<p className="text-gray-700 mb-4">
<p className="text-slate-700 mb-4 leading-relaxed">
{error.detail}
</p>
<p className="text-sm text-gray-600 font-mono mb-4">
<p className="text-sm text-slate-600 font-mono mb-6">
{t('Error code')}: {error.code}
</p>
<Link
href={`/${locale}/admin/clubs`}
className="inline-flex items-center text-indigo-600 hover:text-indigo-700 font-medium"
className="inline-flex items-center px-4 py-2 bg-slate-900 text-white font-semibold rounded-lg hover:bg-slate-800 transition-colors"
>
<ArrowLeft className="w-4 h-4 mr-2" />
{t('Back to clubs')}
@ -140,12 +140,12 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
// Success - render club detail
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
{/* Breadcrumb */}
<div className="mb-6">
<div className="mb-8">
<Link
href={`/${locale}/admin/clubs`}
className="inline-flex items-center text-gray-600 hover:text-gray-900"
className="inline-flex items-center text-slate-600 hover:text-slate-900 font-medium transition-colors"
>
<ArrowLeft className="w-4 h-4 mr-2" />
{t('Back to clubs')}
@ -153,45 +153,43 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
</div>
{/* Club Header */}
<div className="bg-white border border-gray-200 rounded-xl p-6 mb-6">
<div className="flex items-start space-x-4">
<div className="p-3 bg-indigo-100 rounded-lg">
<Building className="w-8 h-8 text-indigo-600" />
<div className="bg-white border-2 border-slate-200 rounded-2xl p-8 mb-6 shadow-sm">
<div className="flex items-start space-x-5">
<div className="p-4 bg-slate-900 rounded-xl">
<Building className="w-10 h-10 text-white" />
</div>
<div className="flex-1">
<h1 className="text-3xl font-bold text-gray-900 mb-2">
<h1 className="text-4xl font-bold text-slate-900 mb-3 tracking-tight">
{clubDetail.club.name}
</h1>
<div className="flex items-center text-gray-600 space-x-4">
<div className="flex items-center">
<MapPin className="w-4 h-4 mr-1" />
<span>{clubDetail.club.timezone}</span>
</div>
<div className="flex items-center text-slate-600 space-x-2">
<MapPin className="w-5 h-5" />
<span className="text-lg font-medium">{clubDetail.club.timezone}</span>
</div>
</div>
</div>
</div>
{/* Provider Info */}
<div className="bg-white border border-gray-200 rounded-xl p-6 mb-6">
<div className="flex items-center space-x-3 mb-4">
<Server className="w-5 h-5 text-gray-600" />
<h2 className="text-xl font-bold text-gray-900">{t('Provider Information')}</h2>
<div className="bg-white border-2 border-slate-200 rounded-2xl p-8 mb-6 shadow-sm">
<div className="flex items-center space-x-3 mb-6">
<Server className="w-6 h-6 text-slate-700" />
<h2 className="text-2xl font-bold text-slate-900">{t('Provider Information')}</h2>
</div>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-gray-600">{t('Type')}:</span>
<span className="font-medium text-gray-900">{clubDetail.provider.remote_type}</span>
<div className="space-y-4">
<div className="flex justify-between items-center py-3 border-b border-slate-100">
<span className="text-slate-600 font-medium">{t('Type')}:</span>
<span className="font-semibold text-slate-900">{clubDetail.provider.remote_type}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600">{t('Manages Slot Storage')}:</span>
<span className="font-medium text-gray-900">
<div className="flex justify-between items-center py-3 border-b border-slate-100">
<span className="text-slate-600 font-medium">{t('Manages Slot Storage')}:</span>
<span className="font-semibold text-slate-900">
{clubDetail.provider.capabilities.manages_slot_storage ? t('Yes') : t('No')}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600">{t('Supports Payment Verification')}:</span>
<span className="font-medium text-gray-900">
<div className="flex justify-between items-center py-3">
<span className="text-slate-600 font-medium">{t('Supports Payment Verification')}:</span>
<span className="font-semibold text-slate-900">
{clubDetail.provider.capabilities.supports_payment_verification ? t('Yes') : t('No')}
</span>
</div>
@ -199,18 +197,18 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
</div>
{/* Courts */}
<div className="bg-white border border-gray-200 rounded-xl p-6 mb-6">
<h2 className="text-xl font-bold text-gray-900 mb-4">{t('Courts')}</h2>
<div className="bg-white border-2 border-slate-200 rounded-2xl p-8 mb-6 shadow-sm">
<h2 className="text-2xl font-bold text-slate-900 mb-6">{t('Courts')}</h2>
{clubDetail.courts.length === 0 ? (
<p className="text-gray-600">{t('No courts configured')}</p>
<p className="text-slate-600 font-medium">{t('No courts configured')}</p>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{clubDetail.courts.map((court) => (
<div
key={court.court_id}
className="border border-gray-200 rounded-lg p-4"
className="border-2 border-slate-200 rounded-xl p-5 hover:border-slate-300 transition-colors"
>
<p className="font-medium text-gray-900">{court.name}</p>
<p className="font-bold text-slate-900 text-lg">{court.name}</p>
</div>
))}
</div>
@ -218,21 +216,21 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
</div>
{/* Slot Definitions */}
<div className="bg-white border border-gray-200 rounded-xl p-6 mb-6">
<div className="flex items-center space-x-3 mb-4">
<Calendar className="w-5 h-5 text-gray-600" />
<h2 className="text-xl font-bold text-gray-900">{t('Slot Definitions')}</h2>
<div className="bg-white border-2 border-slate-200 rounded-2xl p-8 mb-6 shadow-sm">
<div className="flex items-center space-x-3 mb-6">
<Calendar className="w-6 h-6 text-slate-700" />
<h2 className="text-2xl font-bold text-slate-900">{t('Slot Definitions')}</h2>
</div>
{clubDetail.slot_definitions.length === 0 ? (
<p className="text-gray-600">{t('No slot definitions configured')}</p>
<p className="text-slate-600 font-medium">{t('No slot definitions configured')}</p>
) : (
<div className="space-y-3">
{clubDetail.slot_definitions.map((slotDef, index) => (
<div
key={index}
className="border border-gray-200 rounded-lg p-4"
className="border-2 border-slate-200 rounded-xl p-5 hover:border-slate-300 transition-colors"
>
<p className="text-sm text-gray-600">{t('Slot definition')} #{index + 1}</p>
<p className="text-sm text-slate-600 font-medium">{t('Slot definition')} #{index + 1}</p>
</div>
))}
</div>
@ -240,18 +238,18 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
</div>
{/* Upcoming Slots */}
<div className="bg-white border border-gray-200 rounded-xl p-6">
<h2 className="text-xl font-bold text-gray-900 mb-4">{t('Upcoming Slots')}</h2>
<div className="bg-white border-2 border-slate-200 rounded-2xl p-8 shadow-sm">
<h2 className="text-2xl font-bold text-slate-900 mb-6">{t('Upcoming Slots')}</h2>
{clubDetail.upcoming_slots.length === 0 ? (
<p className="text-gray-600">{t('No upcoming slots available')}</p>
<p className="text-slate-600 font-medium">{t('No upcoming slots available')}</p>
) : (
<div className="space-y-3">
{clubDetail.upcoming_slots.map((slot, index) => (
<div
key={index}
className="border border-gray-200 rounded-lg p-4"
className="border-2 border-slate-200 rounded-xl p-5 hover:border-slate-300 transition-colors"
>
<p className="text-sm text-gray-600">{t('Slot')} #{index + 1}</p>
<p className="text-sm text-slate-600 font-medium">{t('Slot')} #{index + 1}</p>
</div>
))}
</div>

@ -26,20 +26,20 @@ export default async function RootLayout({
return (
<html lang={locale}>
<body className="font-sans bg-gradient-to-br from-slate-50 via-white to-indigo-50 text-gray-900 antialiased">
<body className="font-sans bg-white text-slate-900 antialiased">
<Providers translations={translations} locale={locale}>
<div className="min-h-screen flex flex-col relative">
<NavigationWrapper />
<main className="flex-1 relative z-0">
{children}
</main>
<footer className="bg-white/80 backdrop-blur-sm border-t border-gray-200/50 mt-auto">
<footer className="bg-white border-t border-slate-200 mt-auto">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div className="flex flex-col sm:flex-row justify-between items-center space-y-4 sm:space-y-0">
<p className="text-sm text-gray-600">
<p className="text-sm text-slate-600 font-medium">
{t('© 2024 Playchoo Manager. Venue administration portal.')}
</p>
<div className="flex items-center space-x-6 text-sm text-gray-500">
<div className="flex items-center space-x-6 text-sm text-slate-500">
<span>v{process.env.NEXT_PUBLIC_APP_VERSION}</span>
</div>
</div>

@ -34,9 +34,9 @@ export default function AdminAuthGuard({ children }: AdminAuthGuardProps) {
// Show loading state while checking auth
if (loading) {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
<Loader2 className="w-12 h-12 text-indigo-600 animate-spin mb-4" />
<p className="text-gray-600">{t('Checking authentication...')}</p>
<div className="flex flex-col items-center justify-center min-h-screen space-y-4">
<Loader2 className="w-12 h-12 text-slate-900 animate-spin" />
<p className="text-slate-600 font-medium">{t('Checking authentication...')}</p>
</div>
);
}
@ -44,9 +44,9 @@ export default function AdminAuthGuard({ children }: AdminAuthGuardProps) {
// Show loading state while redirecting
if (!user) {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
<Loader2 className="w-12 h-12 text-indigo-600 animate-spin mb-4" />
<p className="text-gray-600">{t('Redirecting to login...')}</p>
<div className="flex flex-col items-center justify-center min-h-screen space-y-4">
<Loader2 className="w-12 h-12 text-slate-900 animate-spin" />
<p className="text-slate-600 font-medium">{t('Redirecting to login...')}</p>
</div>
);
}

@ -169,21 +169,21 @@ export default function Navigation({ pageTitle }: NavigationProps) {
return (
<>
<header className="bg-white/90 backdrop-blur-lg shadow-sm border-b border-gray-200/50 sticky top-0 z-50">
<header className="bg-white shadow-sm border-b border-slate-200 sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
{/* Logo */}
<div className="flex items-center">
<Link href={localizedLink("/")} className="flex items-center group">
<div className="relative">
<h1 className="text-2xl font-bold bg-gradient-to-r from-indigo-600 via-purple-600 to-pink-600 bg-clip-text text-transparent">
<h1 className="text-2xl font-bold text-slate-900">
Playchoo
</h1>
<div className="absolute -bottom-1 left-0 w-0 h-0.5 bg-gradient-to-r from-indigo-600 to-purple-600 group-hover:w-full transition-all duration-300"></div>
<div className="absolute -bottom-1 left-0 w-0 h-0.5 bg-slate-900 group-hover:w-full transition-all duration-300"></div>
</div>
</Link>
{pageTitle && (
<span className="text-xl text-gray-600 font-normal ml-3 pl-3 border-l-2 border-gray-300">{pageTitle}</span>
<span className="text-xl text-slate-600 font-normal ml-3 pl-3 border-l-2 border-slate-300">{pageTitle}</span>
)}
</div>
@ -195,13 +195,13 @@ export default function Navigation({ pageTitle }: NavigationProps) {
<>
<button
onClick={() => login()}
className="px-4 py-2 text-sm font-medium text-gray-700 hover:text-indigo-600 transition-colors duration-200"
className="px-4 py-2 text-sm font-medium text-slate-700 hover:text-slate-900 transition-colors duration-200"
>
{t('Login')}
</button>
<button
onClick={() => login()}
className="px-4 py-2 text-sm font-medium bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-lg hover:from-indigo-700 hover:to-purple-700 transform hover:scale-105 transition-all duration-200 shadow-lg hover:shadow-xl"
className="px-4 py-2 text-sm font-medium bg-slate-900 text-white rounded-lg hover:bg-slate-800 transform hover:scale-105 transition-all duration-200 shadow-lg hover:shadow-xl"
>
{t('Register')}
</button>
@ -211,7 +211,7 @@ export default function Navigation({ pageTitle }: NavigationProps) {
{/* Hamburger menu button - always visible on mobile, only for logged-in users on desktop */}
<button
onClick={toggleMenu}
className={`relative p-2 rounded-xl bg-gradient-to-r from-indigo-600 to-purple-600 text-white shadow-lg hover:shadow-xl transform hover:scale-105 transition-all duration-200 group ${!isLoggedIn ? 'block sm:hidden' : 'block'}`}
className={`relative p-2 rounded-xl bg-slate-900 text-white shadow-lg hover:shadow-xl hover:bg-slate-800 transition-all duration-200 group ${!isLoggedIn ? 'block sm:hidden' : 'block'}`}
>
<motion.div
animate={{ rotate: isMenuOpen ? 180 : 0 }}
@ -219,7 +219,6 @@ export default function Navigation({ pageTitle }: NavigationProps) {
>
{isMenuOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
</motion.div>
<div className="absolute inset-0 rounded-xl bg-white/20 opacity-0 group-hover:opacity-100 transition-opacity duration-200"></div>
</button>
</div>
</div>
@ -250,7 +249,7 @@ export default function Navigation({ pageTitle }: NavigationProps) {
>
<div className="flex flex-col h-full overflow-hidden">
{/* Header */}
<div className="bg-white border-b border-gray-200 p-6 flex-shrink-0">
<div className="bg-white border-b border-slate-200 p-6 flex-shrink-0">
<div className="flex items-center justify-between">
{isLoggedIn && appUser && currentUserData ? (
<Link
@ -258,25 +257,25 @@ export default function Navigation({ pageTitle }: NavigationProps) {
onClick={closeMenu}
className="flex items-center space-x-3 group"
>
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center text-white font-semibold text-sm">
<div className="w-10 h-10 rounded-full bg-slate-900 flex items-center justify-center text-white font-semibold text-sm">
{currentUserData.initials}
</div>
<div>
<div className="font-medium text-gray-900 group-hover:text-indigo-600 transition-colors">
<div className="font-medium text-slate-900 group-hover:text-slate-700 transition-colors">
{currentUserData.name}
</div>
<div className="text-xs text-gray-500">{t('View Profile')}</div>
<div className="text-xs text-slate-500">{t('View Profile')}</div>
</div>
</Link>
) : (
<div>
<h2 className="text-xl font-bold text-gray-900">{t('Menu')}</h2>
<p className="text-gray-500 text-sm">{t('Navigate your game')}</p>
<h2 className="text-xl font-bold text-slate-900">{t('Menu')}</h2>
<p className="text-slate-500 text-sm">{t('Navigate your game')}</p>
</div>
)}
<button
onClick={closeMenu}
className="p-2 pl-6 rounded-lg hover:bg-purple-50 transition-colors duration-200 text-purple-600"
className="p-2 pl-6 rounded-lg hover:bg-slate-50 transition-colors duration-200 text-slate-600"
>
<X className="w-5 h-5" />
</button>
@ -295,12 +294,12 @@ export default function Navigation({ pageTitle }: NavigationProps) {
>
<button
onClick={() => { login(); closeMenu(); }}
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-gray-50 transition-colors duration-200 group w-full"
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-slate-50 transition-colors duration-200 group w-full"
>
<div className="p-2 rounded-lg bg-indigo-100 group-hover:bg-indigo-200 transition-colors duration-200">
<User className="w-5 h-5 text-indigo-600" />
<div className="p-2 rounded-lg bg-slate-100 group-hover:bg-slate-200 transition-colors duration-200">
<User className="w-5 h-5 text-slate-700" />
</div>
<span className="font-medium">{t('Login')}</span>
<span className="font-medium text-slate-900">{t('Login')}</span>
</button>
</motion.div>
@ -312,12 +311,12 @@ export default function Navigation({ pageTitle }: NavigationProps) {
>
<button
onClick={() => { login(); closeMenu(); }}
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-gray-50 transition-colors duration-200 group w-full"
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-slate-50 transition-colors duration-200 group w-full"
>
<div className="p-2 rounded-lg bg-purple-100 group-hover:bg-purple-200 transition-colors duration-200">
<Users className="w-5 h-5 text-purple-600" />
<div className="p-2 rounded-lg bg-slate-100 group-hover:bg-slate-200 transition-colors duration-200">
<Users className="w-5 h-5 text-slate-700" />
</div>
<span className="font-medium">{t('Register')}</span>
<span className="font-medium text-slate-900">{t('Register')}</span>
</button>
</motion.div>
</>
@ -332,12 +331,12 @@ export default function Navigation({ pageTitle }: NavigationProps) {
<Link
href={localizedLink("/dashboard")}
onClick={closeMenu}
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-gray-50 transition-colors duration-200 group"
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-slate-50 transition-colors duration-200 group"
>
<div className="p-2 rounded-lg bg-purple-100 group-hover:bg-purple-200 transition-colors duration-200">
<BarChart3 className="w-5 h-5 text-purple-600" />
<div className="p-2 rounded-lg bg-slate-100 group-hover:bg-slate-200 transition-colors duration-200">
<BarChart3 className="w-5 h-5 text-slate-700" />
</div>
<span className="font-medium">{t('Dashboard')}</span>
<span className="font-medium text-slate-900">{t('Dashboard')}</span>
</Link>
</motion.div>
@ -354,17 +353,17 @@ export default function Navigation({ pageTitle }: NavigationProps) {
router.push(bookingLink);
}, 100);
}}
className="w-full flex items-center space-x-3 p-4 rounded-xl hover:bg-gray-50 transition-colors duration-200 group text-left"
className="w-full flex items-center space-x-3 p-4 rounded-xl hover:bg-slate-50 transition-colors duration-200 group text-left"
>
<div className="p-2 rounded-lg bg-indigo-100 group-hover:bg-indigo-200 transition-colors duration-200">
<Calendar className="w-5 h-5 text-indigo-600" />
<div className="p-2 rounded-lg bg-slate-100 group-hover:bg-slate-200 transition-colors duration-200">
<Calendar className="w-5 h-5 text-slate-700" />
</div>
<span className="font-medium">{t('Booking')}</span>
<span className="font-medium text-slate-900">{t('Booking')}</span>
</button>
</motion.div>
{/* Divider */}
<div className="my-2 border-t border-gray-100"></div>
<div className="my-2 border-t border-slate-100"></div>
<motion.div
custom={2}
@ -384,12 +383,12 @@ export default function Navigation({ pageTitle }: NavigationProps) {
setShowClaimModal(true);
}
}}
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-gray-50 transition-colors duration-200 group cursor-pointer"
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-slate-50 transition-colors duration-200 group cursor-pointer"
>
<div className="p-2 rounded-lg bg-green-100 group-hover:bg-green-200 transition-colors duration-200">
<Users className="w-5 h-5 text-green-600" />
<div className="p-2 rounded-lg bg-slate-100 group-hover:bg-slate-200 transition-colors duration-200">
<Users className="w-5 h-5 text-slate-700" />
</div>
<span className="font-medium">{t('Player Lookup')}</span>
<span className="font-medium text-slate-900">{t('Player Lookup')}</span>
</div>
</motion.div>
@ -402,19 +401,19 @@ export default function Navigation({ pageTitle }: NavigationProps) {
<Link
href={localizedLink("/assessment")}
onClick={closeMenu}
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-gray-50 transition-colors duration-200 group"
className="flex items-center space-x-3 p-4 rounded-xl hover:bg-slate-50 transition-colors duration-200 group"
>
<div className="p-2 rounded-lg bg-amber-100 group-hover:bg-amber-200 transition-colors duration-200">
<HelpCircle className="w-5 h-5 text-amber-600" />
<div className="p-2 rounded-lg bg-slate-100 group-hover:bg-slate-200 transition-colors duration-200">
<HelpCircle className="w-5 h-5 text-slate-700" />
</div>
<span className="font-medium">{t("What's my level?")}</span>
<span className="font-medium text-slate-900">{t("What's my level?")}</span>
</Link>
</motion.div>
</>
)}
{/* Language Selector - Available for all users */}
<div className="my-4 border-t border-gray-100"></div>
<div className="my-4 border-t border-slate-100"></div>
<motion.div
custom={isLoggedIn ? 4 : 2}
@ -426,16 +425,16 @@ export default function Navigation({ pageTitle }: NavigationProps) {
{/* Language Dropdown Header */}
<button
onClick={handleLanguageDropdownToggle}
className="w-full flex items-center justify-between p-3 rounded-lg hover:bg-gray-50 transition-colors duration-200"
className="w-full flex items-center justify-between p-3 rounded-lg hover:bg-slate-50 transition-colors duration-200"
>
<div className="flex items-center space-x-3">
<Globe className="w-4 h-4 text-gray-600" />
<span className="font-medium text-gray-700">{t('Language')}</span>
<Globe className="w-4 h-4 text-slate-600" />
<span className="font-medium text-slate-700">{t('Language')}</span>
</div>
<div className="flex items-center space-x-2">
<span className="text-xl">{languages.find(l => l.code === locale)?.flag}</span>
<span className="font-medium text-gray-700">{languages.find(l => l.code === locale)?.label}</span>
<ChevronDown className={`w-4 h-4 text-gray-500 transition-transform duration-200 ${isLanguageDropdownOpen ? 'rotate-180' : ''}`} />
<span className="font-medium text-slate-700">{languages.find(l => l.code === locale)?.label}</span>
<ChevronDown className={`w-4 h-4 text-slate-500 transition-transform duration-200 ${isLanguageDropdownOpen ? 'rotate-180' : ''}`} />
</div>
</button>
@ -458,7 +457,7 @@ export default function Navigation({ pageTitle }: NavigationProps) {
setIsLanguageDropdownOpen(false);
closeMenu();
}}
className="w-full flex items-center space-x-3 px-3 py-2 rounded-lg hover:bg-gray-100 text-gray-700 transition-colors duration-200"
className="w-full flex items-center space-x-3 px-3 py-2 rounded-lg hover:bg-slate-100 text-slate-700 transition-colors duration-200"
>
<span className="text-xl">{lang.flag}</span>
<span className="font-medium">{lang.label}</span>
@ -473,7 +472,7 @@ export default function Navigation({ pageTitle }: NavigationProps) {
</div>
{/* Footer */}
<div className="border-t-2 border-gray-200 p-6 space-y-4 flex-shrink-0">
<div className="border-t-2 border-slate-200 p-6 space-y-4 flex-shrink-0">
{isLoggedIn && (
<div className="flex items-center gap-3">
<motion.div
@ -503,19 +502,19 @@ export default function Navigation({ pageTitle }: NavigationProps) {
<Link
href={localizedLink("/settings")}
onClick={closeMenu}
className="flex items-center justify-center w-12 h-12 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors duration-200"
className="flex items-center justify-center w-12 h-12 rounded-lg bg-slate-100 hover:bg-slate-200 transition-colors duration-200"
title={t('Settings')}
>
<Settings className="w-5 h-5 text-gray-600" />
<Settings className="w-5 h-5 text-slate-600" />
</Link>
</motion.div>
</div>
)}
<div className="flex items-center justify-between text-sm text-gray-500 pt-4 border-t border-gray-100">
<div className="flex items-center justify-between text-sm text-slate-500 pt-4 border-t border-slate-100">
<span>Version {process.env.NEXT_PUBLIC_APP_VERSION}</span>
<div className="flex items-center space-x-1">
<Zap className="w-4 h-4 text-yellow-500" />
<Zap className="w-4 h-4 text-slate-400" />
<span>{t('Powered by passion')}</span>
</div>
</div>

Loading…
Cancel
Save