match h2h

This commit is contained in:
yohlo
2025-10-11 13:40:12 -05:00
parent 14c2eb2c02
commit 43972b6a06
6 changed files with 383 additions and 23 deletions

View File

@@ -0,0 +1,195 @@
import { Stack, Text, Group, Box, Divider, Paper } from "@mantine/core";
import { TeamInfo } from "@/features/teams/types";
import { useTeamHeadToHead } from "../queries";
import { useMemo } from "react";
import { CrownIcon, TrophyIcon } from "@phosphor-icons/react";
import MatchList from "./match-list";
interface TeamHeadToHeadSheetProps {
team1: TeamInfo;
team2: TeamInfo;
}
const TeamHeadToHeadSheet = ({ team1, team2 }: TeamHeadToHeadSheetProps) => {
const { data: matches, isLoading } = useTeamHeadToHead(team1.id, team2.id);
const stats = useMemo(() => {
if (!matches || matches.length === 0) {
return {
team1Wins: 0,
team2Wins: 0,
team1CupsFor: 0,
team2CupsFor: 0,
team1CupsAgainst: 0,
team2CupsAgainst: 0,
team1AvgMargin: 0,
team2AvgMargin: 0,
};
}
let team1Wins = 0;
let team2Wins = 0;
let team1CupsFor = 0;
let team2CupsFor = 0;
let team1CupsAgainst = 0;
let team2CupsAgainst = 0;
matches.forEach((match) => {
const isTeam1Home = match.home?.id === team1.id;
const team1Cups = isTeam1Home ? match.home_cups : match.away_cups;
const team2Cups = isTeam1Home ? match.away_cups : match.home_cups;
if (team1Cups > team2Cups) {
team1Wins++;
} else if (team2Cups > team1Cups) {
team2Wins++;
}
team1CupsFor += team1Cups;
team2CupsFor += team2Cups;
team1CupsAgainst += team2Cups;
team2CupsAgainst += team1Cups;
});
const team1AvgMargin = team1Wins > 0
? (team1CupsFor - team1CupsAgainst) / team1Wins
: 0;
const team2AvgMargin = team2Wins > 0
? (team2CupsFor - team2CupsAgainst) / team2Wins
: 0;
return {
team1Wins,
team2Wins,
team1CupsFor,
team2CupsFor,
team1CupsAgainst,
team2CupsAgainst,
team1AvgMargin,
team2AvgMargin,
};
}, [matches, team1.id]);
if (isLoading) {
return (
<Stack p="md" gap="md">
<Text size="sm" c="dimmed" ta="center">Loading...</Text>
</Stack>
);
}
if (!matches || matches.length === 0) {
return (
<Stack p="md" gap="md">
<Text size="sm" c="dimmed" ta="center">
These teams have not faced each other yet.
</Text>
</Stack>
);
}
const totalGames = stats.team1Wins + stats.team2Wins;
const leader = stats.team1Wins > stats.team2Wins ? team1 : stats.team2Wins > stats.team1Wins ? team2 : null;
return (
<Stack gap="md">
<Paper p="md" withBorder radius="md">
<Stack gap="sm">
<Group justify="center" gap="xs">
<Text size="lg" fw={700}>{team1.name}</Text>
<Text size="sm" c="dimmed">vs</Text>
<Text size="lg" fw={700}>{team2.name}</Text>
</Group>
<Group justify="center" gap="lg">
<Stack gap={0} align="center">
<Text size="xl" fw={700}>{stats.team1Wins}</Text>
<Text size="xs" c="dimmed">{team1.name}</Text>
</Stack>
<Text size="md" c="dimmed">-</Text>
<Stack gap={0} align="center">
<Text size="xl" fw={700}>{stats.team2Wins}</Text>
<Text size="xs" c="dimmed">{team2.name}</Text>
</Stack>
</Group>
{leader && (
<Group justify="center" gap="xs">
<CrownIcon size={16} weight="fill" color="gold" />
<Text size="xs" c="dimmed">
{leader.name} leads the series
</Text>
</Group>
)}
{!leader && totalGames > 0 && (
<Text size="xs" c="dimmed" ta="center">
Series is tied
</Text>
)}
</Stack>
</Paper>
<Stack gap={0}>
<Text size="sm" fw={600} px="md" mb="xs">Stats Comparison</Text>
<Paper withBorder>
<Stack gap={0}>
<Group justify="space-between" px="md" py="sm">
<Group gap="xs">
<Text size="sm" fw={600}>{stats.team1CupsFor}</Text>
<Text size="xs" c="dimmed">cups</Text>
</Group>
<Text size="xs" fw={500}>Total Cups</Text>
<Group gap="xs">
<Text size="xs" c="dimmed">cups</Text>
<Text size="sm" fw={600}>{stats.team2CupsFor}</Text>
</Group>
</Group>
<Divider />
<Group justify="space-between" px="md" py="sm">
<Group gap="xs">
<Text size="sm" fw={600}>
{totalGames > 0 ? (stats.team1CupsFor / totalGames).toFixed(1) : '0.0'}
</Text>
<Text size="xs" c="dimmed">avg</Text>
</Group>
<Text size="xs" fw={500}>Avg Cups/Game</Text>
<Group gap="xs">
<Text size="xs" c="dimmed">avg</Text>
<Text size="sm" fw={600}>
{totalGames > 0 ? (stats.team2CupsFor / totalGames).toFixed(1) : '0.0'}
</Text>
</Group>
</Group>
<Divider />
<Group justify="space-between" px="md" py="sm">
<Group gap="xs">
<Text size="sm" fw={600}>
{!isNaN(stats.team1AvgMargin) ? stats.team1AvgMargin.toFixed(1) : '0.0'}
</Text>
<Text size="xs" c="dimmed">margin</Text>
</Group>
<Text size="xs" fw={500}>Avg Win Margin</Text>
<Group gap="xs">
<Text size="xs" c="dimmed">margin</Text>
<Text size="sm" fw={600}>
{!isNaN(stats.team2AvgMargin) ? stats.team2AvgMargin.toFixed(1) : '0.0'}
</Text>
</Group>
</Group>
</Stack>
</Paper>
</Stack>
<Stack gap="xs">
<Text size="sm" fw={600} px="md">Match History ({totalGames} games)</Text>
<MatchList matches={matches} hideH2H />
</Stack>
</Stack>
);
};
export default TeamHeadToHeadSheet;