'use client'; import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId'; import { useNotifications } from '@/components/notifications/NotificationProvider'; import type { NotificationVariant } from '@/components/notifications/notificationTypes'; import { AlertCircle, AlertTriangle, Award, Bell, BellRing, Building2, ChevronDown, ChevronUp, LogIn, LogOut, MessageSquare, Shield, TrendingUp, User, Vote, Wrench, X, } from 'lucide-react'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; type DemoNotificationType = 'protest_filed' | 'defense_requested' | 'vote_required' | 'race_performance_summary' | 'race_final_results'; type DemoUrgency = 'silent' | 'toast' | 'modal'; interface NotificationOption { type: DemoNotificationType; label: string; description: string; icon: typeof Bell; color: string; } interface UrgencyOption { urgency: DemoUrgency; label: string; description: string; icon: typeof Bell; } const notificationOptions: NotificationOption[] = [ { type: 'protest_filed', label: 'Protest Against You', description: 'A protest was filed against you', icon: AlertTriangle, color: 'text-red-400', }, { type: 'defense_requested', label: 'Defense Requested', description: 'A steward requests your defense', icon: Shield, color: 'text-warning-amber', }, { type: 'vote_required', label: 'Vote Required', description: 'You need to vote on a protest', icon: Vote, color: 'text-primary-blue', }, { type: 'race_performance_summary', label: 'Race Performance Summary', description: 'Immediate results after main race', icon: TrendingUp, color: 'text-primary-blue', }, { type: 'race_final_results', label: 'Race Final Results', description: 'Final results after stewarding closes', icon: Award, color: 'text-warning-amber', }, ]; const urgencyOptions: UrgencyOption[] = [ { urgency: 'silent', label: 'Silent', description: 'Only shows in notification center', icon: Bell, }, { urgency: 'toast', label: 'Toast', description: 'Shows a temporary popup', icon: BellRing, }, { urgency: 'modal', label: 'Modal', description: 'Shows blocking modal (may require response)', icon: AlertCircle, }, ]; type LoginMode = 'none' | 'driver' | 'sponsor' | 'league-owner' | 'league-steward' | 'league-admin' | 'system-owner' | 'super-admin'; export default function DevToolbar() { const router = useRouter(); const { addNotification } = useNotifications(); const [isExpanded, setIsExpanded] = useState(false); const [isMinimized, setIsMinimized] = useState(false); const [selectedType, setSelectedType] = useState('protest_filed'); const [selectedUrgency, setSelectedUrgency] = useState('toast'); const [sending, setSending] = useState(false); const [lastSent, setLastSent] = useState(null); const [loginMode, setLoginMode] = useState('none'); const [loggingIn, setLoggingIn] = useState(false); const currentDriverId = useEffectiveDriverId(); // Sync login mode with actual session state on mount useEffect(() => { if (typeof document !== 'undefined') { // Check for actual session cookie first const cookies = document.cookie.split(';'); const sessionCookie = cookies.find(c => c.trim().startsWith('gp_session=')); if (sessionCookie) { // User has a session cookie, check if it's valid by calling the API fetch('/api/auth/session', { method: 'GET', credentials: 'include' }) .then(res => { if (res.ok) { return res.json(); } throw new Error('No valid session'); }) .then(session => { if (session && session.user) { // Determine login mode based on user email patterns const email = session.user.email?.toLowerCase() || ''; const displayName = session.user.displayName?.toLowerCase() || ''; let mode: LoginMode = 'none'; if (email.includes('sponsor') || displayName.includes('sponsor')) { mode = 'sponsor'; } else if (email.includes('league-owner') || displayName.includes('owner')) { mode = 'league-owner'; } else if (email.includes('league-steward') || displayName.includes('steward')) { mode = 'league-steward'; } else if (email.includes('league-admin') || displayName.includes('admin')) { mode = 'league-admin'; } else if (email.includes('system-owner') || displayName.includes('system owner')) { mode = 'system-owner'; } else if (email.includes('super-admin') || displayName.includes('super admin')) { mode = 'super-admin'; } else if (email.includes('driver') || displayName.includes('demo')) { mode = 'driver'; } setLoginMode(mode); } else { setLoginMode('none'); } }) .catch(() => { // Session invalid or expired setLoginMode('none'); }); } else { // No session cookie means not logged in setLoginMode('none'); } } }, []); const handleDemoLogin = async (role: LoginMode) => { if (role === 'none') return; setLoggingIn(true); try { // Use the demo login API const response = await fetch('/api/auth/demo-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ role }), }); if (!response.ok) { throw new Error('Demo login failed'); } setLoginMode(role); // Navigate based on role if (role === 'sponsor') { window.location.href = '/sponsor/dashboard'; } else { // For driver and league roles, go to dashboard window.location.href = '/dashboard'; } } catch (error) { console.error('Demo login failed:', error); alert('Demo login failed. Please check the console for details.'); } finally { setLoggingIn(false); } }; const handleLogout = async () => { setLoggingIn(true); try { // Call logout API await fetch('/api/auth/logout', { method: 'POST' }); setLoginMode('none'); // Refresh to update all components window.location.href = '/'; } catch (error) { console.error('Logout failed:', error); alert('Logout failed. Please check the console for details.'); } finally { setLoggingIn(false); } }; // Only show in development if (process.env.NODE_ENV === 'production') { return null; } const handleSendNotification = async () => { setSending(true); try { const actionUrlByType: Record = { protest_filed: '/races', defense_requested: '/races', vote_required: '/leagues', race_performance_summary: '/races', race_final_results: '/races', }; const titleByType: Record = { protest_filed: 'Protest Filed Against You', defense_requested: 'Defense Requested', vote_required: 'Vote Required', race_performance_summary: 'Race Performance Summary', race_final_results: 'Race Final Results', }; const messageByType: Record = { protest_filed: 'A protest has been filed against you. Please review the incident details.', defense_requested: 'A steward requests your defense. Please respond within the deadline.', vote_required: 'A protest vote is pending. Please review and vote.', race_performance_summary: 'Your race is complete. View your provisional results.', race_final_results: 'Stewarding is closed. Your final results are available.', }; const notificationTypeByDemoType: Record = { protest_filed: 'protest_filed', defense_requested: 'protest_defense_requested', vote_required: 'protest_vote_required', race_performance_summary: 'race_performance_summary', race_final_results: 'race_final_results', }; const variant: NotificationVariant = selectedUrgency === 'modal' ? 'modal' : 'toast'; addNotification({ type: notificationTypeByDemoType[selectedType], title: titleByType[selectedType], message: messageByType[selectedType], variant, actionUrl: actionUrlByType[selectedType], data: { driverId: currentDriverId, demo: true, }, }); setLastSent(`${selectedType}-${selectedUrgency}`); setTimeout(() => setLastSent(null), 3000); } catch (error) { console.error('Failed to send demo notification:', error); } finally { setSending(false); } }; // const handleSendNotification = async () => { // setSending(true); // try { // const sendNotification = getSendNotificationUseCase(); // const raceRepository = getRaceRepository(); // const leagueRepository = getLeagueRepository(); // const [allRaces, allLeagues] = await Promise.all([ // raceRepository.findAll(), // leagueRepository.findAll(), // ]); // const completedRaces = allRaces.filter((race) => race.status === 'completed'); // const scheduledRaces = allRaces.filter((race) => race.status === 'scheduled'); // const primaryRace = completedRaces[0] ?? allRaces[0]; // const secondaryRace = scheduledRaces[0] ?? allRaces[1] ?? primaryRace; // const primaryLeague = allLeagues[0]; // const notificationDeadline = // selectedUrgency === 'modal' // ? new Date(Date.now() + 48 * 60 * 60 * 1000) // : undefined; // let title: string; // let body: string; // let notificationType: 'protest_filed' | 'protest_defense_requested' | 'protest_vote_required' | 'race_performance_summary' | 'race_final_results'; // let actionUrl: string; // switch (selectedType) { // case 'protest_filed': { // const raceId = primaryRace?.id; // title = '🚨 Protest Filed Against You'; // body = // 'A protest has been filed against you for unsafe rejoining during a recent race. Please review the incident details.'; // notificationType = 'protest_filed'; // actionUrl = raceId ? `/races/${raceId}/stewarding` : '/races'; // break; // } // case 'defense_requested': { // const raceId = secondaryRace?.id ?? primaryRace?.id; // title = '⚖️ Defense Requested'; // body = // 'A steward has requested your defense regarding a recent incident. Please provide your side of the story within 48 hours.'; // notificationType = 'protest_defense_requested'; // actionUrl = raceId ? `/races/${raceId}/stewarding` : '/races'; // break; // } // case 'vote_required': { // const leagueId = primaryLeague?.id; // title = '🗳️ Your Vote Required'; // body = // 'As a league steward, you are required to vote on an open protest. Please review the case and cast your vote.'; // notificationType = 'protest_vote_required'; // actionUrl = leagueId ? `/leagues/${leagueId}/stewarding` : '/leagues'; // break; // } // case 'race_performance_summary': { // const raceId = primaryRace?.id; // const leagueId = primaryLeague?.id; // title = '🏁 Race Complete: Performance Summary'; // body = // 'Your Monza Grand Prix race is finished! You finished P1 with 0 incidents. Provisional rating: +25 points. View full results and standings.'; // notificationType = 'race_performance_summary'; // actionUrl = raceId ? `/races/${raceId}` : '/races'; // break; // } // case 'race_final_results': { // const leagueId = primaryLeague?.id; // title = '🏆 Final Results: Monza Grand Prix'; // body = // 'Stewarding is now closed. Your final result: P1 (+25 rating). No penalties were applied. View championship standings.'; // notificationType = 'race_final_results'; // actionUrl = leagueId ? `/leagues/${leagueId}/standings` : '/leagues'; // break; // } // } // const actions = // selectedUrgency === 'modal' // ? selectedType.startsWith('race_') // ? [ // { label: selectedType === 'race_performance_summary' ? '🏁 View Race Results' : '🏆 View Standings', type: 'primary' as const, href: actionUrl, actionId: 'view' }, // { label: '🎉 Share Achievement', type: 'secondary' as const, actionId: 'share' }, // ] // : [ // { label: 'View Protest', type: 'primary' as const, href: actionUrl, actionId: 'view' }, // { label: 'Dismiss', type: 'secondary' as const, actionId: 'dismiss' }, // ] // : []; // await sendNotification.execute({ // recipientId: currentDriverId, // type: notificationType, // title, // body, // actionUrl, // urgency: selectedUrgency as NotificationUrgency, // requiresResponse: selectedUrgency === 'modal' && !selectedType.startsWith('race_'), // actions, // data: { // ...(selectedType.startsWith('protest_') ? { // protestId: `demo-protest-${Date.now()}`, // } : {}), // ...(selectedType.startsWith('race_') ? { // raceEventId: `demo-race-event-${Date.now()}`, // sessionId: `demo-session-${Date.now()}`, // position: 1, // positionChange: 0, // incidents: 0, // provisionalRatingChange: 25, // finalRatingChange: 25, // hadPenaltiesApplied: false, // } : {}), // raceId: primaryRace?.id ?? '', // leagueId: primaryLeague?.id ?? '', // ...(notificationDeadline && selectedType.startsWith('protest_') ? { deadline: notificationDeadline } : {}), // }, // }); // setLastSent(`${selectedType}-${selectedUrgency}`); // setTimeout(() => setLastSent(null), 3000); // } catch (error) { // console.error('Failed to send demo notification:', error); // } finally { // setSending(false); // } // }; if (isMinimized) { return ( ); } return (
{/* Header */}
Dev Toolbar DEMO
{/* Content */} {isExpanded && (
{/* Notification Type Section */}
Notification Type
{notificationOptions.map((option) => { const Icon = option.icon; const isSelected = selectedType === option.type; return ( ); })}
{/* Urgency Section */}
Urgency Level
{urgencyOptions.map((option) => { const Icon = option.icon; const isSelected = selectedUrgency === option.urgency; return ( ); })}

{urgencyOptions.find(o => o.urgency === selectedUrgency)?.description}

{/* Send Button */} {/* Info */}

Silent: Notification center only
Toast: Temporary popup (auto-dismisses)
Modal: Blocking popup (may require action)

{/* Login Section */}
Demo Login
{/* Driver Login */} {/* League Owner Login */} {/* League Steward Login */} {/* League Admin Login */} {/* Sponsor Login */} {/* System Owner Login */} {/* Super Admin Login */} {loginMode !== 'none' && ( )}

Test different user roles for demo purposes. Dashboard works for all roles.

)} {/* Collapsed state hint */} {!isExpanded && (
Click ↑ to expand dev tools
)}
); }