'use client'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { useEffectiveDriverId } from '@/lib/currentDriver'; import { getSendNotificationUseCase } from '@/lib/di-container'; import type { NotificationUrgency } from '@gridpilot/notifications/application'; import { Bell, AlertTriangle, Vote, Shield, ChevronDown, ChevronUp, Wrench, X, MessageSquare, AlertCircle, BellRing, User, Building2, LogOut, LogIn, } from 'lucide-react'; type DemoNotificationType = 'protest_filed' | 'defense_requested' | 'vote_required'; 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', }, ]; 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 (must respond)', icon: AlertCircle, }, ]; type LoginMode = 'none' | 'driver' | 'sponsor'; export default function DevToolbar() { const router = useRouter(); 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 cookie state on mount useEffect(() => { if (typeof document !== 'undefined') { const cookies = document.cookie.split(';'); const demoModeCookie = cookies.find(c => c.trim().startsWith('gridpilot_demo_mode=')); if (demoModeCookie) { const value = demoModeCookie.split('=')[1]?.trim(); if (value === 'sponsor') { setLoginMode('sponsor'); } else if (value === 'driver') { setLoginMode('driver'); } else { setLoginMode('none'); } } else { // Default to driver mode if no cookie (for demo purposes) setLoginMode('driver'); } } }, []); const handleLoginAsDriver = async () => { setLoggingIn(true); try { // Demo: Set cookie to indicate driver mode document.cookie = 'gridpilot_demo_mode=driver; path=/; max-age=86400'; setLoginMode('driver'); // Refresh to update all components that depend on demo mode window.location.reload(); } finally { setLoggingIn(false); } }; const handleLoginAsSponsor = async () => { setLoggingIn(true); try { // Demo: Set cookie to indicate sponsor mode document.cookie = 'gridpilot_demo_mode=sponsor; path=/; max-age=86400'; setLoginMode('sponsor'); // Navigate to sponsor dashboard window.location.href = '/sponsor/dashboard'; } finally { setLoggingIn(false); } }; const handleLogout = async () => { setLoggingIn(true); try { // Demo: Clear demo mode cookie document.cookie = 'gridpilot_demo_mode=; path=/; max-age=0'; setLoginMode('none'); // Refresh to update all components window.location.href = '/'; } finally { setLoggingIn(false); } }; // Only show in development if (process.env.NODE_ENV === 'production') { return null; } const handleSendNotification = async () => { setSending(true); try { const sendNotification = getSendNotificationUseCase(); let title: string; let body: string; let notificationType: 'protest_filed' | 'protest_defense_requested' | 'protest_vote_required'; let actionUrl: string; switch (selectedType) { case 'protest_filed': title = '🚨 Protest Filed Against You'; body = 'Max Verstappen has filed a protest against you for unsafe rejoining at Turn 3, Lap 12 during the Spa-Francorchamps race.'; notificationType = 'protest_filed'; actionUrl = '/races/race-1/stewarding'; break; case 'defense_requested': title = '⚖️ Defense Requested'; body = 'A steward has requested your defense regarding the incident at Turn 1 in the Monza race. Please provide your side of the story within 48 hours.'; notificationType = 'protest_defense_requested'; actionUrl = '/races/race-2/stewarding'; break; case 'vote_required': title = '🗳️ Your Vote Required'; body = 'As a league steward, you are required to vote on the protest: Driver A vs Driver B - Causing a collision at Eau Rouge.'; notificationType = 'protest_vote_required'; actionUrl = '/leagues/league-1/stewarding'; break; } // For modal urgency, add actions const actions = selectedUrgency === 'modal' ? [ { label: 'View Protest', type: 'primary' as const, href: actionUrl, actionId: 'view' }, { label: 'Dismiss', type: 'secondary' as const, actionId: 'dismiss' }, ] : undefined; await sendNotification.execute({ recipientId: currentDriverId, type: notificationType, title, body, actionUrl, urgency: selectedUrgency as NotificationUrgency, requiresResponse: selectedUrgency === 'modal', actions, data: { protestId: `demo-protest-${Date.now()}`, raceId: 'race-1', leagueId: 'league-1', deadline: selectedUrgency === 'modal' ? new Date(Date.now() + 48 * 60 * 60 * 1000) : undefined, }, }); 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 (requires action)

{/* Login Section */}
Demo Login
{loginMode !== 'none' && ( )}

Switch between driver and sponsor views for demo purposes.

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