'use client';
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 { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId';
import { useRaceStewardingData } from '@/hooks/useRaceStewardingService';
import { useLeagueMembership } from '@/hooks/useLeagueMembershipService';
import { LeagueRoleUtility } from '@/lib/utilities/LeagueRoleUtility';
import {
AlertCircle,
AlertTriangle,
ArrowLeft,
CheckCircle,
Clock,
Flag,
Gavel,
Scale,
Video
} from 'lucide-react';
import Link from 'next/link';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
export default function RaceStewardingPage() {
const params = useParams();
const router = useRouter();
const raceId = params.id as string;
const currentDriverId = useEffectiveDriverId();
const { data: stewardingData, isLoading: loading } = useRaceStewardingData(raceId, currentDriverId);
const { data: membership } = useLeagueMembership(stewardingData?.league?.id || '', currentDriverId);
const [activeTab, setActiveTab] = useState<'pending' | 'resolved' | 'penalties'>('pending');
const isAdmin = membership ? LeagueRoleUtility.isLeagueAdminOrHigherRole(membership.role) : false;
const pendingProtests = stewardingData?.pendingProtests ?? [];
const resolvedProtests = stewardingData?.resolvedProtests ?? [];
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;
}
};
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',
});
};
if (loading) {
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 || 'Race', href: `/races/${raceId}` },
{ label: 'Stewarding' },
];
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 && (
<>
•
Video Evidence
>
)}
{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`}
);
})
)}
)}
);
}