'use client';
import { useAuth } from '@/lib/auth/AuthContext';
import { AnimatePresence, motion, useReducedMotion } from 'framer-motion';
import { BarChart3, Building2, ChevronDown, CreditCard, Handshake, LogOut, Megaphone, Paintbrush, Settings, TrendingUp, Trophy, Shield } from 'lucide-react';
import Link from 'next/link';
import React, { useEffect, useMemo, useState } from 'react';
import DriverSummaryPill from '@/components/profile/DriverSummaryPill';
import { CapabilityGate } from '@/components/shared/CapabilityGate';
import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId';
import type { DriverViewModel } from '@/lib/view-models/DriverViewModel';
import { DriverViewModel as DriverViewModelClass } from '@/lib/view-models/DriverViewModel';
import { useFindDriverById } from '@/hooks/driver/useFindDriverById';
// Hook to detect demo user mode based on session
function useDemoUserMode(): { isDemo: boolean; demoRole: string | null } {
const { session } = useAuth();
const [demoMode, setDemoMode] = useState({ isDemo: false, demoRole: null as string | null });
// Check if this is a demo user
useEffect(() => {
if (!session?.user) {
setDemoMode({ isDemo: false, demoRole: null });
return;
}
const email = session.user.email?.toLowerCase() || '';
const displayName = session.user.displayName?.toLowerCase() || '';
const primaryDriverId = (session.user as any).primaryDriverId || '';
const role = (session.user as any).role;
// Check if this is a demo user
if (email.includes('demo') ||
displayName.includes('demo') ||
primaryDriverId.startsWith('demo-')) {
// Use role from session if available, otherwise derive from email
let roleToUse = role;
if (!roleToUse) {
if (email.includes('sponsor')) roleToUse = 'sponsor';
else if (email.includes('league-owner') || displayName.includes('owner')) roleToUse = 'league-owner';
else if (email.includes('league-steward') || displayName.includes('steward')) roleToUse = 'league-steward';
else if (email.includes('league-admin') || displayName.includes('admin')) roleToUse = 'league-admin';
else if (email.includes('system-owner') || displayName.includes('system owner')) roleToUse = 'system-owner';
else if (email.includes('super-admin') || displayName.includes('super admin')) roleToUse = 'super-admin';
else roleToUse = 'driver';
}
setDemoMode({ isDemo: true, demoRole: roleToUse });
} else {
setDemoMode({ isDemo: false, demoRole: null });
}
}, [session]);
return demoMode;
}
// Helper to check if user has admin access (Owner or Super Admin)
function useHasAdminAccess(): boolean {
const { session } = useAuth();
const { isDemo, demoRole } = useDemoUserMode();
// Demo users with system-owner or super-admin roles
if (isDemo && (demoRole === 'system-owner' || demoRole === 'super-admin')) {
return true;
}
// Real users - would need role information from session
// For now, we'll check if the user has any admin-related capabilities
// This can be enhanced when the API includes role information
if (!session?.user) return false;
// Check for admin-related email patterns as a temporary measure
const email = session.user.email?.toLowerCase() || '';
const displayName = session.user.displayName?.toLowerCase() || '';
return email.includes('system-owner') ||
email.includes('super-admin') ||
displayName.includes('system owner') ||
displayName.includes('super admin');
}
// Sponsor Pill Component - matches the style of DriverSummaryPill
function SponsorSummaryPill({
onClick,
companyName = 'Acme Racing Co.',
activeSponsors = 7,
impressions = 127,
}: {
onClick: () => void;
companyName?: string;
activeSponsors?: number;
impressions?: number;
}) {
const shouldReduceMotion = useReducedMotion();
return (
{/* Avatar/Logo */}
{/* Info */}
{companyName.split(' ')[0]}
{activeSponsors}
•
{impressions}k
{/* Chevron */}
);
}
export default function UserPill() {
const { session } = useAuth();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const { isDemo, demoRole } = useDemoUserMode();
const shouldReduceMotion = useReducedMotion();
const primaryDriverId = useEffectiveDriverId();
// Use React-Query hook for driver data (only for non-demo users)
const { data: driverDto } = useFindDriverById(primaryDriverId || '', {
enabled: !!primaryDriverId && !isDemo,
});
// Transform DTO to ViewModel
const driver = useMemo(() => {
if (!driverDto) return null;
return new DriverViewModelClass({ ...driverDto, avatarUrl: (driverDto as any).avatarUrl ?? null });
}, [driverDto]);
const data = useMemo(() => {
if (!session?.user) {
return null;
}
// Demo users don't have real driver data
if (isDemo) {
return {
isDemo: true,
demoRole,
displayName: session.user.displayName,
email: session.user.email,
avatarUrl: session.user.avatarUrl,
};
}
if (!primaryDriverId || !driver) {
return null;
}
// Driver rating + rank are not exposed by the current API contract for the lightweight
// driver DTO used in the header. Keep it null until the API provides it.
const rating: number | null = null;
const rank: number | null = null;
const avatarSrc = driver.avatarUrl;
return {
driver,
avatarSrc,
rating,
rank,
isDemo: false,
demoRole: null,
};
}, [session, driver, primaryDriverId, isDemo, demoRole]);
// Close menu when clicking outside
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (isMenuOpen) {
const target = e.target as HTMLElement;
if (!target.closest('[data-user-pill]')) {
setIsMenuOpen(false);
}
}
};
document.addEventListener('click', handleClickOutside);
return () => document.removeEventListener('click', handleClickOutside);
}, [isMenuOpen]);
// Logout handler for demo users
const handleLogout = async () => {
try {
// Call the logout API
await fetch('/api/auth/logout', { method: 'POST' });
// Redirect to home
window.location.href = '/';
} catch (error) {
console.error('Logout failed:', error);
window.location.href = '/';
}
};
// Call hooks unconditionally before any returns
const hasAdminAccess = useHasAdminAccess();
// Handle unauthenticated users
if (!session) {
return (
Sign In
Get Started
);
}
// For all authenticated users (demo or regular), show the user pill
// Determine what to show in the pill
const displayName = driver?.name || session.user.displayName || session.user.email || 'User';
const avatarUrl = session.user.avatarUrl;
const roleLabel = isDemo ? {
'driver': 'Driver',
'sponsor': 'Sponsor',
'league-owner': 'League Owner',
'league-steward': 'League Steward',
'league-admin': 'League Admin',
'system-owner': 'System Owner',
'super-admin': 'Super Admin',
}[demoRole || 'driver'] : null;
const roleColor = isDemo ? {
'driver': 'text-primary-blue',
'sponsor': 'text-performance-green',
'league-owner': 'text-purple-400',
'league-steward': 'text-amber-400',
'league-admin': 'text-red-400',
'system-owner': 'text-indigo-400',
'super-admin': 'text-pink-400',
}[demoRole || 'driver'] : null;
return (
setIsMenuOpen((open) => !open)}
className="group flex items-center gap-3 rounded-full bg-gradient-to-r from-iron-gray to-deep-graphite border border-charcoal-outline px-3 py-1.5 hover:border-primary-blue/50 transition-all duration-200"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
{/* Avatar */}
{avatarUrl ? (
) : (
{displayName[0]?.toUpperCase() || 'U'}
)}
{/* Info */}
{displayName}
{roleLabel && (
{roleLabel}
)}
{/* Chevron */}
{isMenuOpen && (
{/* Header */}
{avatarUrl ? (
) : (
{displayName[0]?.toUpperCase() || 'U'}
)}
{displayName}
{roleLabel && (
{roleLabel}
)}
{isDemo && (
Demo Account
)}
{isDemo && (
Development account - not for production use
)}
{/* Menu Items */}
{/* Admin link for Owner/Super Admin users */}
{hasAdminAccess && (
setIsMenuOpen(false)}
>
Admin Area
)}
{/* Sponsor portal link for demo sponsor users */}
{isDemo && demoRole === 'sponsor' && (
<>
setIsMenuOpen(false)}
>
Dashboard
setIsMenuOpen(false)}
>
My Sponsorships
setIsMenuOpen(false)}
>
Billing
setIsMenuOpen(false)}
>
Settings
>
)}
{/* Regular user profile links */}
setIsMenuOpen(false)}
>
Profile
setIsMenuOpen(false)}
>
Manage leagues
setIsMenuOpen(false)}
>
Liveries
setIsMenuOpen(false)}
>
Sponsorship Requests
setIsMenuOpen(false)}
>
Settings
{/* Demo-specific info */}
{isDemo && (
Demo users have limited profile access
)}
{/* Footer */}
{isDemo ? (
) : (
)}
)}
);
}