Files
gridpilot.gg/apps/website/components/leagues/PendingProtestsList.tsx
2026-01-18 23:24:30 +01:00

73 lines
2.5 KiB
TypeScript

import { DriverViewModel } from "@/lib/view-models/DriverViewModel";
import { ProtestViewModel } from "@/lib/view-models/ProtestViewModel";
import { RaceViewModel } from "@/lib/view-models/RaceViewModel";
import { Stack } from "@/ui/Stack";
import { Card } from "@/ui/Card";
import { ProtestListItem } from "./ProtestListItem";
import { Text } from "@/ui/Text";
import { Flag } from "lucide-react";
interface PendingProtestsListProps {
protests: ProtestViewModel[];
drivers: Record<string, DriverViewModel>;
races: Record<string, RaceViewModel>;
leagueId: string;
onReviewProtest: (protest: ProtestViewModel) => void;
onProtestReviewed?: () => void;
}
export function PendingProtestsList({
protests,
drivers,
onReviewProtest,
}: PendingProtestsListProps) {
if (protests.length === 0) {
return (
<Card>
<Stack p={12} align="center" gap={4}>
<Stack w="16" h="16" rounded="full" bg="bg-performance-green/10" align="center" justify="center">
<Flag className="h-8 w-8 text-performance-green" />
</Stack>
<Stack align="center">
<Text weight="semibold" size="lg" color="text-white" block mb={2}>All Clear! 🏁</Text>
<Text size="sm" color="text-gray-400">No pending protests to review</Text>
</Stack>
</Stack>
</Card>
);
}
return (
<Stack gap={4}>
{protests.map((protest) => {
const filedAt = protest.filedAt || protest.submittedAt;
const daysSinceFiled = Math.floor((Date.now() - new Date(filedAt).getTime()) / (1000 * 60 * 60 * 24));
const isUrgent = daysSinceFiled > 2;
const protester = drivers[protest.protestingDriverId];
const accused = drivers[protest.accusedDriverId];
return (
<ProtestListItem
key={protest.id}
protesterName={protester?.name || 'Unknown'}
protesterHref={`/drivers/${protest.protestingDriverId}`}
accusedName={accused?.name || 'Unknown'}
accusedHref={`/drivers/${protest.accusedDriverId}`}
status={protest.status}
isUrgent={isUrgent}
daysOld={daysSinceFiled}
lap={protest.incident?.lap ?? 0}
filedAtLabel={new Date(filedAt).toLocaleDateString()}
description={protest.incident?.description || protest.description}
proofVideoUrl={protest.proofVideoUrl || undefined}
isAdmin={true}
onReview={() => onReviewProtest(protest)}
/>
);
})}
</Stack>
);
}