wip tournament list

This commit is contained in:
yohlo
2025-09-13 14:59:02 -05:00
parent a35c688a64
commit 3be2284da9
3 changed files with 183 additions and 76 deletions

View File

@@ -1,8 +1,10 @@
import { Badge, Card, Text, Image, Stack, Flex } from "@mantine/core";
import { Badge, Card, Text, Stack, Group, Box, ThemeIcon } from "@mantine/core";
import { Tournament } from "@/features/tournaments/types";
import { useMemo } from "react";
import { CaretRightIcon } from "@phosphor-icons/react";
import { TrophyIcon, CalendarIcon, MapPinIcon, UsersIcon } from "@phosphor-icons/react";
import { useNavigate } from "@tanstack/react-router";
import Avatar from "@/components/avatar";
import { motion } from "framer-motion";
interface TournamentCardProps {
tournament: Tournament;
@@ -10,64 +12,68 @@ interface TournamentCardProps {
export const TournamentCard = ({ tournament }: TournamentCardProps) => {
const navigate = useNavigate();
const displayDate = useMemo(() => {
if (!tournament.start_time) return null;
const date = new Date(tournament.start_time);
if (isNaN(date.getTime())) return null;
return date.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
return date.toLocaleDateString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric'
});
}, [tournament.start_time]);
const enrollmentDeadline = tournament.enroll_time
? new Date(tournament.enroll_time)
: new Date(tournament.start_time);
const isEnrollmentOpen = enrollmentDeadline > new Date();
const enrolledTeamsCount = tournament.teams?.length || 0;
return (
<Card
shadow="sm"
padding="lg"
radius="md"
withBorder
style={{ cursor: "pointer" }}
onClick={() => navigate({ to: `/tournaments/${tournament.id}` })}
<motion.div
whileHover={{ y: -4, scale: 1.02 }}
whileTap={{ scale: 0.98 }}
transition={{ type: "spring", stiffness: 300 }}
>
<Stack>
<Flex align="center" gap="md">
<Image
maw={100}
mah={100}
fit="contain"
src={
tournament.logo
? `/api/files/tournaments/${tournament.id}/${tournament.logo}`
: undefined
}
alt={tournament.name}
fallbackSrc={"TODO"}
/>
<Stack ta="center" mx="auto" gap="0">
<Text size="lg" fw={800}>
{tournament.name} <CaretRightIcon size={12} weight="bold" />
<Card
withBorder
radius="lg"
p="lg"
style={{
cursor: "pointer",
height: "100%",
transition: "box-shadow 0.2s ease"
}}
onClick={() => navigate({ to: `/tournaments/${tournament.id}` })}
onMouseEnter={(e) => {
e.currentTarget.style.boxShadow = "var(--mantine-shadow-md)";
}}
onMouseLeave={(e) => {
e.currentTarget.style.boxShadow = "none";
}}
>
<Stack gap="md" h="100%">
<Group gap="md" align="flex-start">
<Avatar
size={60}
radius="md"
name={tournament.name}
src={
tournament.logo
? `/api/files/tournaments/${tournament.id}/${tournament.logo}`
: undefined
}
>
<TrophyIcon size={24} />
</Avatar>
<Text fw={700} size="lg" lineClamp={2} my='auto'>
{tournament.name}
</Text>
{displayDate && (
<Text c="dimmed" size="xs" fw={600}>
{displayDate}
</Text>
)}
<Stack gap={4} mt={4}>
{/* TODO: Add medalists when data is available */}
<Badge variant="dot" color="gold">
Longer Team Name Goes Here
</Badge>
<Badge variant="dot" color="silver">
Some Team
</Badge>
<Badge variant="dot" color="orange">
Medium Team Name
</Badge>
</Stack>
</Stack>
</Flex>
</Stack>
</Card>
</Group>
</Stack>
</Card>
</motion.div>
);
};