'use client'; import { useState } from 'react'; import Breadcrumbs from '@/components/layout/Breadcrumbs'; import RaceStewardingStats from '@/components/races/RaceStewardingStats'; import Button from '@/components/ui/Button'; import Card from '@/components/ui/Card'; import { StewardingTabs } from '@/components/races/StewardingTabs'; import { AlertCircle, AlertTriangle, ArrowLeft, CheckCircle, Clock, Flag, Gavel, Scale, Video } from 'lucide-react'; import Link from 'next/link'; export type StewardingTab = 'pending' | 'resolved' | 'penalties'; export interface Protest { id: string; status: string; protestingDriverId: string; accusedDriverId: string; filedAt: string; incident: { lap: number; description: string; }; proofVideoUrl?: string; decisionNotes?: string; } export interface Penalty { id: string; driverId: string; type: string; value: number; reason: string; notes?: string; } export interface Driver { id: string; name: string; } export interface RaceStewardingData { race?: { id: string; track: string; scheduledAt: string; } | null; league?: { id: string; } | null; pendingProtests: Protest[]; resolvedProtests: Protest[]; penalties: Penalty[]; driverMap: Record; pendingCount: number; resolvedCount: number; penaltiesCount: number; } export interface RaceStewardingTemplateProps { stewardingData?: RaceStewardingData; isLoading: boolean; error?: Error | null; // Actions onBack: () => void; onReviewProtest: (protestId: string) => void; // User state isAdmin: boolean; // UI State activeTab: StewardingTab; setActiveTab: (tab: StewardingTab) => void; } export function RaceStewardingTemplate({ stewardingData, isLoading, error, onBack, onReviewProtest, isAdmin, activeTab, setActiveTab, }: RaceStewardingTemplateProps) { const formatDate = (date: Date | string) => { const d = typeof date === 'string' ? new Date(date) : date; return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', }); }; const getStatusBadge = (status: string) => { switch (status) { case 'pending': case 'under_review': return ( Pending ); case 'upheld': return ( Upheld ); case 'dismissed': return ( Dismissed ); case 'withdrawn': return ( Withdrawn ); default: return null; } }; if (isLoading) { return (
); } if (!stewardingData?.race) { return (

Race not found

The race you're looking for doesn't exist.

); } const breadcrumbItems = [ { label: 'Races', href: '/races' }, { label: stewardingData.race.track, href: `/races/${stewardingData.race.id}` }, { label: 'Stewarding' }, ]; const pendingProtests = stewardingData.pendingProtests ?? []; const resolvedProtests = stewardingData.resolvedProtests ?? []; return (
{/* Navigation */}
{/* Header */}

Stewarding

{stewardingData.race.track} • {stewardingData.race.scheduledAt ? formatDate(stewardingData.race.scheduledAt) : ''}

{/* Stats */}
{/* Tab Navigation */} {/* Content */} {activeTab === 'pending' && (
{pendingProtests.length === 0 ? (

All Clear!

No pending protests to review

) : ( pendingProtests.map((protest) => { const protester = stewardingData.driverMap[protest.protestingDriverId]; const accused = stewardingData.driverMap[protest.accusedDriverId]; const daysSinceFiled = Math.floor( (Date.now() - new Date(protest.filedAt).getTime()) / (1000 * 60 * 60 * 24) ); const isUrgent = daysSinceFiled > 2; return (
{protester?.name || 'Unknown'} vs {accused?.name || 'Unknown'} {getStatusBadge(protest.status)} {isUrgent && ( {daysSinceFiled}d old )}
Lap {protest.incident.lap} Filed {formatDate(protest.filedAt)} {protest.proofVideoUrl && ( <> )}

{protest.incident.description}

{isAdmin && stewardingData?.league && ( )}
); }) )}
)} {activeTab === 'resolved' && (
{resolvedProtests.length === 0 ? (

No Resolved Protests

Resolved protests will appear here

) : ( resolvedProtests.map((protest) => { const protester = stewardingData.driverMap[protest.protestingDriverId]; const accused = stewardingData.driverMap[protest.accusedDriverId]; return (
{protester?.name || 'Unknown'} vs {accused?.name || 'Unknown'} {getStatusBadge(protest.status)}
Lap {protest.incident.lap} Filed {formatDate(protest.filedAt)}

{protest.incident.description}

{protest.decisionNotes && (

Steward Decision

{protest.decisionNotes}

)}
); }) )}
)} {activeTab === 'penalties' && (
{stewardingData?.penalties.length === 0 ? (

No Penalties

Penalties issued for this race will appear here

) : ( stewardingData?.penalties.map((penalty) => { const driver = stewardingData.driverMap[penalty.driverId]; return (
{driver?.name || 'Unknown'} {penalty.type.replace('_', ' ')}

{penalty.reason}

{penalty.notes && (

{penalty.notes}

)}
{penalty.type === 'time_penalty' && `+${penalty.value}s`} {penalty.type === 'grid_penalty' && `+${penalty.value} grid`} {penalty.type === 'points_deduction' && `-${penalty.value} pts`} {penalty.type === 'disqualification' && 'DSQ'} {penalty.type === 'warning' && 'Warning'} {penalty.type === 'license_points' && `${penalty.value} LP`}
); }) )}
)}
); }