80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import { Badge, Card, Text, Stack, Group, Box, ThemeIcon } from "@mantine/core";
|
|
import { Tournament } from "@/features/tournaments/types";
|
|
import { useMemo } from "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;
|
|
}
|
|
|
|
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(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 (
|
|
<motion.div
|
|
whileHover={{ y: -4, scale: 1.02 }}
|
|
whileTap={{ scale: 0.98 }}
|
|
transition={{ type: "spring", stiffness: 300 }}
|
|
>
|
|
<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>
|
|
</Group>
|
|
</Stack>
|
|
</Card>
|
|
</motion.div>
|
|
);
|
|
};
|