diff --git a/app/components/tournament/ActionSection.tsx b/app/components/tournament/ActionSection.tsx deleted file mode 100644 index 6f8724bb8..000000000 --- a/app/components/tournament/ActionSection.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { useLoaderData } from "remix"; -import type { FindTournamentByNameForUrlI } from "~/services/tournament"; -import { useUser } from "~/utils/hooks"; -import { ActionSectionBeforeStartContent } from "./ActionSectionBeforeStartContent"; - -// TODO: warning when not registered but check in is open -// TODO: rename, refactor -export function ActionSection() { - const tournament = useLoaderData(); - const user = useUser(); - - const ownTeam = tournament.teams.find((team) => - team.members.some( - ({ member, captain }) => captain && member.id === user?.id - ) - ); - - const tournamentHasStarted = tournament.brackets.some((b) => b.rounds.length); - if (!ownTeam || tournamentHasStarted) { - return null; - } - - return ; -} diff --git a/app/components/tournament/CheckinActions.tsx b/app/components/tournament/CheckinActions.tsx new file mode 100644 index 000000000..dd4be0309 --- /dev/null +++ b/app/components/tournament/CheckinActions.tsx @@ -0,0 +1,153 @@ +// TODO: Warning: Text content did not match. Server: "57" Client: "56" +import * as React from "react"; +import { Form, useLoaderData, useTransition } from "remix"; +import { + checkInClosesDate, + TOURNAMENT_TEAM_ROSTER_MIN_SIZE, +} from "~/constants"; +import { TournamentAction } from "~/routes/to/$organization.$tournament"; +import type { FindTournamentByNameForUrlI } from "~/services/tournament"; +import { useUser } from "~/utils/hooks"; +import { Button } from "../Button"; +import { AlertIcon } from "../icons/Alert"; +import { CheckInIcon } from "../icons/CheckIn"; +import { ErrorIcon } from "../icons/Error"; +import { SuccessIcon } from "../icons/Success"; +import { ActionSectionWrapper } from "./ActionSectionWrapper"; + +// TODO: warning when not registered but check in is open +export function CheckinActions() { + const tournament = useLoaderData(); + const user = useUser(); + const transition = useTransition(); + + const ownTeam = tournament.teams.find((team) => + team.members.some( + ({ member, captain }) => captain && member.id === user?.id + ) + ); + + const tournamentHasStarted = tournament.brackets.some((b) => b.rounds.length); + if (!ownTeam || tournamentHasStarted) { + return null; + } + + const timeInMinutesBeforeCheckInCloses = () => { + return Math.floor( + (checkInClosesDate(tournament.startTime).getTime() - + new Date().getTime()) / + (1000 * 60) + ); + }; + + const [minutesTillCheckInCloses, setMinutesTillCheckInCloses] = + React.useState(timeInMinutesBeforeCheckInCloses()); + + React.useEffect(() => { + const timeout = setInterval(() => { + setMinutesTillCheckInCloses(timeInMinutesBeforeCheckInCloses()); + }, 1000 * 15); + + return () => clearTimeout(timeout); + }, []); + + if (ownTeam.checkedInTime) { + return ( + + Your team is checked in! + + ); + } + + const checkInHasStarted = new Date(tournament.checkInStartTime) < new Date(); + const teamHasEnoughMembers = + ownTeam.members.length >= TOURNAMENT_TEAM_ROSTER_MIN_SIZE; + + if (!checkInHasStarted && !teamHasEnoughMembers) { + return ( + + You need at least 4 players in your roster to play + + ); + } + + const differenceInMinutesBetweenCheckInAndStart = Math.floor( + (new Date(tournament.startTime).getTime() - + new Date(tournament.checkInStartTime).getTime()) / + (1000 * 60) + ); + + if (!checkInHasStarted && teamHasEnoughMembers) { + return ( + + Check-in starts{" "} + {differenceInMinutesBetweenCheckInAndStart} minutes before the + tournament starts + + ); + } + + if ( + checkInHasStarted && + !teamHasEnoughMembers && + minutesTillCheckInCloses > 0 + ) { + return ( + + You need at least 4 players in your roster to play. + Check-in is open for {minutesTillCheckInCloses} more{" "} + {minutesTillCheckInCloses > 1 ? "minutes" : "minute"} + + ); + } + + if ( + checkInHasStarted && + teamHasEnoughMembers && + minutesTillCheckInCloses > 0 + ) { + return ( + + {minutesTillCheckInCloses > 1 ? ( + <> + Check-in is open for {minutesTillCheckInCloses} more + minutes + + ) : ( + <> + Check-in closes in less than a minute + + )} +
+ + + +
+
+ ); + } + + return ( + + Check-in has closed. Your team is not checked in + + ); +} diff --git a/app/routes/to/$organization.$tournament.tsx b/app/routes/to/$organization.$tournament.tsx index 09d84d884..639547ac4 100644 --- a/app/routes/to/$organization.$tournament.tsx +++ b/app/routes/to/$organization.$tournament.tsx @@ -11,7 +11,7 @@ import { } from "remix"; import invariant from "tiny-invariant"; import { AdminIcon } from "~/components/icons/Admin"; -import { ActionSection } from "~/components/tournament/ActionSection"; +import { CheckinActions } from "~/components/tournament/CheckinActions"; import { InfoBanner } from "~/components/tournament/InfoBanner"; import { isTournamentAdmin } from "~/core/tournament/permissions"; import { tournamentHasStarted } from "~/core/tournament/utils"; @@ -149,7 +149,7 @@ export default function TournamentPage() {
- +
{/* TODO: pass context instead of useMatches */}