Rename <ActionSection />

This commit is contained in:
Kalle (Sendou)
2021-12-27 16:51:27 +02:00
parent 34075dec1a
commit 7b27c74d4d
3 changed files with 155 additions and 26 deletions

View File

@@ -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<FindTournamentByNameForUrlI>();
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 <ActionSectionBeforeStartContent ownTeam={ownTeam} />;
}

View File

@@ -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<FindTournamentByNameForUrlI>();
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 (
<ActionSectionWrapper icon="success" data-cy="checked-in-alert">
<SuccessIcon /> Your team is checked in!
</ActionSectionWrapper>
);
}
const checkInHasStarted = new Date(tournament.checkInStartTime) < new Date();
const teamHasEnoughMembers =
ownTeam.members.length >= TOURNAMENT_TEAM_ROSTER_MIN_SIZE;
if (!checkInHasStarted && !teamHasEnoughMembers) {
return (
<ActionSectionWrapper icon="warning" data-cy="team-size-alert">
<AlertIcon /> You need at least 4 players in your roster to play
</ActionSectionWrapper>
);
}
const differenceInMinutesBetweenCheckInAndStart = Math.floor(
(new Date(tournament.startTime).getTime() -
new Date(tournament.checkInStartTime).getTime()) /
(1000 * 60)
);
if (!checkInHasStarted && teamHasEnoughMembers) {
return (
<ActionSectionWrapper icon="info">
<AlertIcon /> Check-in starts{" "}
{differenceInMinutesBetweenCheckInAndStart} minutes before the
tournament starts
</ActionSectionWrapper>
);
}
if (
checkInHasStarted &&
!teamHasEnoughMembers &&
minutesTillCheckInCloses > 0
) {
return (
<ActionSectionWrapper icon="warning" data-cy="not-enough-players-warning">
<AlertIcon /> You need at least 4 players in your roster to play.
Check-in is open for {minutesTillCheckInCloses} more{" "}
{minutesTillCheckInCloses > 1 ? "minutes" : "minute"}
</ActionSectionWrapper>
);
}
if (
checkInHasStarted &&
teamHasEnoughMembers &&
minutesTillCheckInCloses > 0
) {
return (
<ActionSectionWrapper
icon={minutesTillCheckInCloses <= 1 ? "warning" : "info"}
data-cy="check-in-alert"
>
{minutesTillCheckInCloses > 1 ? (
<>
<AlertIcon /> Check-in is open for {minutesTillCheckInCloses} more
minutes
</>
) : (
<>
<AlertIcon /> Check-in closes in less than a minute
</>
)}
<Form
method="post"
className="tournament__action-section__button-container"
>
<input
type="hidden"
name="_action"
value={TournamentAction.CHECK_IN}
/>
<input type="hidden" name="teamId" value={ownTeam.id} />
<Button
variant="outlined"
type="submit"
loading={transition.state !== "idle"}
icon={<CheckInIcon />}
data-cy="check-in-button"
>
Check-in
</Button>
</Form>
</ActionSectionWrapper>
);
}
return (
<ActionSectionWrapper icon="error">
<ErrorIcon /> Check-in has closed. Your team is not checked in
</ActionSectionWrapper>
);
}

View File

@@ -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() {
</div>
</div>
<div className="tournament__container__spacer" />
<ActionSection />
<CheckinActions />
<div className="tournament__outlet-spacer" />
{/* TODO: pass context instead of useMatches */}
<Outlet />