import { Link } from "react-router";
import { Card, CardContent } from "~/components/ui/card";
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "~/components/ui/table";
import { Badge } from "~/components/ui/badge";
interface TeamScoreBreakdownProps {
leagueId: string;
seasonId: string;
numTeams: number;
breakdown: {
team: {
id: string;
name: string;
} | null;
picks: Array<{
pickNumber: number;
round: number;
participant: {
id: string;
name: string;
sport: string;
sportsSeasonId: string;
};
finalPosition: number | null;
points: number;
projectedPoints: number | null;
isComplete: boolean;
isPartialScore: boolean;
}>;
actualPoints: number;
projectedPoints: number;
completedCount: number;
totalCount: number;
};
standing: {
currentRank: number;
} | null;
}
/**
* Display detailed team score breakdown with all drafted participants
* Phase 4.3: Team breakdown pages
*/
export function TeamScoreBreakdown({
leagueId,
seasonId,
numTeams,
breakdown,
standing,
}: TeamScoreBreakdownProps) {
if (!breakdown.team) {
return (
Team not found
);
}
const remaining = breakdown.totalCount - breakdown.completedCount;
// Flatten all picks sorted by sport name then pick number
const allPicks = breakdown.picks
.slice()
.toSorted((a, b) => {
const sportCmp = a.participant.sport.localeCompare(b.participant.sport);
return sportCmp !== 0 ? sportCmp : a.pickNumber - b.pickNumber;
});
return (
{/* Header */}
{breakdown.team.name}
Team Score Breakdown
{breakdown.actualPoints.toFixed(2)}
Actual Points
{breakdown.projectedPoints > breakdown.actualPoints && (
{breakdown.projectedPoints.toFixed(2)}
projected
)}
{remaining > 0 && (
{remaining} participant{remaining !== 1 ? "s" : ""} remaining
)}
{standing && (
Rank #{standing.currentRank}
)}
{/* All picks — single flat table */}
Pick #
Sport
Participant
Position
Points
actual / projected
{allPicks.map((pick) => (
{numTeams > 0
? `${pick.round}.${String(pick.pickNumber - (pick.round - 1) * numTeams).padStart(2, "0")}`
: `#${pick.pickNumber}`}
(#{pick.pickNumber})
{pick.participant.sport}
{pick.participant.name}
{pick.isComplete && !pick.isPartialScore ? (
(pick.finalPosition ?? 0) === 0 ? (
Did Not Score
) : (
)
) : (
Pending
)}
{pick.isComplete && !pick.isPartialScore ? (
{pick.points > 0 ? pick.points.toFixed(2) : "0.00"}
) : (
{pick.points.toFixed(2)}
{pick.projectedPoints !== null && (
{pick.projectedPoints.toFixed(2)}
)}
)}
))}
{/* Navigation */}
← Back to Standings
);
}
/**
* Display placement badge with color coding
*/
function PlacementBadge({ position }: { position: number }) {
const badges: Record = {
1: { label: "1st", className: "bg-amber-accent hover:bg-amber-accent/80 text-background" },
2: { label: "2nd", className: "bg-muted hover:bg-muted/80 text-muted-foreground" },
3: { label: "3rd", className: "bg-coral-accent hover:bg-coral-accent/80 text-background" },
4: { label: "4th", className: "bg-electric/20 hover:bg-electric/30 text-electric" },
5: { label: "5th", className: "bg-purple-500/20 hover:bg-purple-500/30 text-purple-400" },
6: { label: "6th", className: "bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-400" },
7: { label: "7th", className: "bg-pink-500/20 hover:bg-pink-500/30 text-pink-400" },
8: { label: "8th", className: "bg-indigo-500/20 hover:bg-indigo-500/30 text-indigo-400" },
};
const badge = badges[position] || { label: `${position}th`, className: "" };
return (
{badge.label}
);
}