stats reorg, upcoming refinement

This commit is contained in:
yohlo
2025-09-14 23:10:05 -05:00
parent 8efc0a7a4b
commit 9a105b30c6
18 changed files with 703 additions and 373 deletions

View File

@@ -0,0 +1,72 @@
import { Group, Stack, ThemeIcon, Text } from "@mantine/core";
import { Tournament } from "../../types";
import Avatar from "@/components/avatar";
import { CalendarIcon, MapPinIcon, TrophyIcon, UsersIcon } from "@phosphor-icons/react";
import { useMemo } from "react";
const Header = ({ tournament }: { tournament: Tournament}) => {
const tournamentStart = useMemo(() => new Date(tournament.start_time), [tournament.start_time]);
const teamCount = useMemo(() => tournament.teams?.length || 0, [tournament.teams]);
return (
<Group justify="space-around" align="flex-start" w='100%'>
<Group align="center" gap="lg">
<Avatar
name={tournament.name}
src={
tournament.logo
? `/api/files/tournaments/${tournament.id}/${tournament.logo}`
: undefined
}
radius="md"
size={200}
px='md'
withBorder={false}
>
<TrophyIcon size={32} />
</Avatar>
<Stack gap="xs">
{tournament.location && (
<Group gap="xs">
<ThemeIcon size="sm" variant="light" radius="sm">
<MapPinIcon size={14} />
</ThemeIcon>
<Text size="sm" c="dimmed">
{tournament.location}
</Text>
</Group>
)}
<Group gap="xs">
<ThemeIcon size="sm" variant="light" radius="sm">
<CalendarIcon size={14} />
</ThemeIcon>
<Text size="sm" c="dimmed">
{tournamentStart.toLocaleDateString(undefined, {
weekday: "short",
month: "short",
day: "numeric",
})}{" "}
at{" "}
{tournamentStart.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
})}
</Text>
</Group>
<Group gap="xs">
<ThemeIcon size="sm" variant="light" radius="sm">
<UsersIcon size={14} />
</ThemeIcon>
<Text size="sm" c="dimmed">
{teamCount} teams enrolled
</Text>
</Group>
</Stack>
</Group>
</Group>
)
}
export default Header;

View File

@@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from "react";
import { Tournament } from "../types";
import { Tournament } from "../../types";
import { useAuth } from "@/contexts/auth-context";
import {
Box,
@@ -23,8 +23,10 @@ import {
UsersIcon,
ListIcon,
} from "@phosphor-icons/react";
import EnrollTeam from "./enroll-team";
import EnrollFreeAgent from "./enroll-free-agent";
import EnrollTeam from "../enroll-team";
import EnrollFreeAgent from "../enroll-free-agent";
import TeamListButton from "./team-list-button";
import Header from "./header";
const UpcomingTournament: React.FC<{ tournament: Tournament }> = ({
tournament,
@@ -44,70 +46,12 @@ const UpcomingTournament: React.FC<{ tournament: Tournament }> = ({
const enrollmentDeadline = tournament.enroll_time
? new Date(tournament.enroll_time)
: new Date(tournament.start_time);
const tournamentStart = new Date(tournament.start_time);
const isEnrollmentOpen = enrollmentDeadline > new Date();
const enrolledTeamsCount = tournament.teams?.length || 0;
return (
<Stack gap="lg">
<Group justify="space-around" align="flex-start" w='100%'>
<Group align="center" gap="lg">
<Avatar
name={tournament.name}
src={
tournament.logo
? `/api/files/tournaments/${tournament.id}/${tournament.logo}`
: undefined
}
radius="md"
size={120}
px='md'
withBorder={false}
>
<TrophyIcon size={32} />
</Avatar>
<Stack gap="xs">
{tournament.location && (
<Group gap="xs">
<ThemeIcon size="sm" variant="light" radius="sm">
<MapPinIcon size={14} />
</ThemeIcon>
<Text size="sm" c="dimmed">
{tournament.location}
</Text>
</Group>
)}
<Group gap="xs">
<ThemeIcon size="sm" variant="light" radius="sm">
<CalendarIcon size={14} />
</ThemeIcon>
<Text size="sm" c="dimmed">
{tournamentStart.toLocaleDateString(undefined, {
weekday: "short",
month: "short",
day: "numeric",
})}{" "}
at{" "}
{tournamentStart.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
})}
</Text>
</Group>
<Group gap="xs">
<ThemeIcon size="sm" variant="light" radius="sm">
<UsersIcon size={14} />
</ThemeIcon>
<Text size="sm" c="dimmed">
{enrolledTeamsCount} teams enrolled
</Text>
</Group>
</Stack>
</Group>
</Group>
<Header tournament={tournament} />
{tournament.desc && <Text size="sm">{tournament.desc}</Text>}
@@ -149,11 +93,7 @@ const UpcomingTournament: React.FC<{ tournament: Tournament }> = ({
/>
)}
<ListButton label="View Rules" Icon={ListIcon} onClick={() => {}} />
<ListButton
label={`View Teams (${enrolledTeamsCount})`}
Icon={UsersIcon}
onClick={() => {}}
/>
<TeamListButton teams={tournament.teams || []} />
</Box>
</Stack>
);

View File

@@ -0,0 +1,31 @@
import ListButton from "@/components/list-button"
import Sheet from "@/components/sheet/sheet"
import TeamList from "@/features/teams/components/team-list"
import { TeamInfo } from "@/features/teams/types"
import { useSheet } from "@/hooks/use-sheet"
import { UsersIcon } from "@phosphor-icons/react"
import { useMemo } from "react"
interface TeamListButtonProps {
teams: TeamInfo[]
}
const TeamListButton: React.FC<TeamListButtonProps> = ({ teams }) => {
const count = useMemo(() => teams.length, [teams]);
const { open, isOpen, toggle } = useSheet();
return (
<>
<ListButton
label={`View Teams (${count})`}
Icon={UsersIcon}
onClick={open}
/>
<Sheet title="Enrolled Teams" opened={isOpen} onChange={toggle}>
<TeamList teams={teams} />
</Sheet>
</>
)
}
export default TeamListButton;