Files
flxn-app/src/features/tournaments/components/upcoming-tournament/index.tsx
2026-02-21 23:30:58 -06:00

168 lines
5.5 KiB
TypeScript

import { Suspense, useMemo } from "react";
import { Tournament } from "../../types";
import { useAuth } from "@/contexts/auth-context";
import { Box, Card, Divider, Group, Stack, Text, Title } from "@mantine/core";
import Countdown from "@/components/countdown";
import ListLink from "@/components/list-link";
import { TreeStructureIcon, UsersIcon } from "@phosphor-icons/react";
import EnrollTeam from "./enroll-team";
import EnrollFreeAgent from "./enroll-free-agent";
import TeamListButton from "./team-list-button";
import EnrolledPlayersListButton from "./enrolled-players-list-button";
import Header from "./header";
import TeamCardSkeleton from "@/features/teams/components/team-card-skeleton";
import TeamCard from "@/features/teams/components/team-card";
import RegionalTeamCard from "@/features/teams/components/regional-team-card";
import UpdateTeam from "./update-team";
import UnenrollTeam from "./unenroll-team";
import { useQueryClient } from "@tanstack/react-query";
import { tournamentKeys, useFreeAgents } from "../../queries";
import RulesListButton from "./rules-list-button";
import EnrolledFreeAgent from "./enrolled-free-agent";
const UpcomingTournament: React.FC<{ tournament: Tournament }> = ({
tournament,
}) => {
const { user, roles } = useAuth();
const isAdmin = useMemo(() => roles.includes("Admin"), [roles]);
const userTeam = useMemo(
() =>
tournament.teams?.find((team) =>
team.players?.some((player) => player.id === user?.id)
),
[tournament.teams, user?.id]
);
const isUserEnrolled = !!userTeam;
const enrollmentDeadline = tournament.enroll_time
? new Date(tournament.enroll_time)
: new Date(tournament.start_time);
const isEnrollmentOpen = enrollmentDeadline > new Date();
const queryClient = useQueryClient();
const handleSubmit = () => {
queryClient.invalidateQueries({ queryKey: tournamentKeys.current });
};
const { data: free_agents } = useFreeAgents(tournament.id);
const isFreeAgent = useMemo(() => !isUserEnrolled && free_agents.find(a => a.player?.id === user?.id), [free_agents, isUserEnrolled]);
return (
<Stack gap="lg">
<Header tournament={tournament} />
<Stack px="xs">
{tournament.desc && <Text px="md" size="sm">{tournament.desc}</Text>}
<Card withBorder radius="lg" p="lg">
<Stack gap="xs">
<Group gap="xs" align="center">
<UsersIcon size={16} />
<Title mt={4} order={5}>
Enrollment
</Title>
{isEnrollmentOpen && (
<Box ml="auto">
<Countdown
date={enrollmentDeadline}
label="Time left"
color="yellow"
/>
</Box>
)}
</Group>
{!isUserEnrolled && !isEnrollmentOpen && (
<Text fw={600} c="dimmed" size="sm">
Enrollment has been closed for this tournament.
</Text>
)}
{!isUserEnrolled && isEnrollmentOpen && !isFreeAgent && (
<>
{!tournament.regional && (
<>
<EnrollTeam
tournamentId={tournament.id}
onSubmit={handleSubmit}
/>
<Divider my={0} label="or" />
</>
)}
<EnrollFreeAgent
tournamentId={tournament.id}
isRegional={tournament.regional}
/>
</>
)}
{isUserEnrolled && (
<>
<Suspense fallback={<TeamCardSkeleton />}>
{tournament.regional === true ? (
<RegionalTeamCard teamId={userTeam.id} />
) : (
<TeamCard teamId={userTeam.id} />
)}
</Suspense>
{tournament.regional !== true && (
<>
<UpdateTeam tournamentId={tournament.id} teamId={userTeam.id} />
{isEnrollmentOpen && (
<UnenrollTeam
tournamentId={tournament.id}
teamId={userTeam.id}
onSubmit={handleSubmit}
/>
)}
</>
)}
</>
)}
{
isFreeAgent && isEnrollmentOpen && (
<EnrolledFreeAgent
tournamentId={tournament.id}
isRegional={tournament.regional}
/>
)
}
</Stack>
</Card>
</Stack>
<Box>
<Divider />
{isAdmin && (
<ListLink
label={`Manage ${tournament.name}`}
to={`/admin/tournaments/${tournament.id}`}
Icon={UsersIcon}
/>
)}
<ListLink
label={`View Bracket`}
to={`/tournaments/${tournament.id}/bracket`}
Icon={TreeStructureIcon}
disabled
/>
{tournament.regional === true ? (
(tournament.teams && tournament.teams.length > 0) ? (
<TeamListButton teams={tournament.teams} />
) : (
<EnrolledPlayersListButton tournamentId={tournament.id} />
)
) : (
<TeamListButton teams={tournament.teams || []} />
)}
<RulesListButton tournamentId={tournament.id} />
</Box>
</Stack>
);
};
export default UpcomingTournament;