mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-28 14:18:04 -05:00
Remove rest useFetchers
This commit is contained in:
13
app/components/icons/CheckIn.tsx
Normal file
13
app/components/icons/CheckIn.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
export function CheckInIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M8.707 7.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l2-2a1 1 0 00-1.414-1.414L11 7.586V3a1 1 0 10-2 0v4.586l-.293-.293z" />
|
||||
<path d="M3 5a2 2 0 012-2h1a1 1 0 010 2H5v7h2l1 2h4l1-2h2V5h-1a1 1 0 110-2h1a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V5z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
// TODO: Warning: Text content did not match. Server: "57" Client: "56"
|
||||
|
||||
import * as React from "react";
|
||||
import { useFetcher, useLoaderData } from "remix";
|
||||
import { useTransition, useLoaderData, Form } 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 { Unpacked } from "~/utils";
|
||||
import { Button } from "../Button";
|
||||
import { AlertIcon } from "../icons/Alert";
|
||||
import { CheckmarkIcon } from "../icons/Checkmark";
|
||||
import { CheckInIcon } from "../icons/CheckIn";
|
||||
import { ErrorIcon } from "../icons/Error";
|
||||
import { SuccessIcon } from "../icons/Success";
|
||||
import { ActionSectionWrapper } from "./ActionSectionWrapper";
|
||||
@@ -20,7 +21,7 @@ export function ActionSectionBeforeStartContent({
|
||||
}: {
|
||||
ownTeam: Unpacked<FindTournamentByNameForUrlI["teams"]>;
|
||||
}) {
|
||||
const fetcher = useFetcher();
|
||||
const transition = useTransition();
|
||||
const tournament = useLoaderData<FindTournamentByNameForUrlI>();
|
||||
|
||||
const timeInMinutesBeforeCheckInCloses = () => {
|
||||
@@ -111,21 +112,25 @@ export function ActionSectionBeforeStartContent({
|
||||
<AlertIcon /> Check-in closes in less than a minute
|
||||
</>
|
||||
)}
|
||||
<fetcher.Form
|
||||
<Form
|
||||
method="post"
|
||||
action={`/api/tournamentTeam/${ownTeam.id}/check-in`}
|
||||
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-success"
|
||||
loadingText="Checking in..."
|
||||
variant="outlined"
|
||||
type="submit"
|
||||
loading={fetcher.state !== "idle"}
|
||||
icon={<CheckmarkIcon />}
|
||||
loading={transition.state !== "idle"}
|
||||
icon={<CheckInIcon />}
|
||||
>
|
||||
Check-in
|
||||
</Button>
|
||||
</fetcher.Form>
|
||||
</Form>
|
||||
</ActionSectionWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import {
|
||||
LinksFunction,
|
||||
LoaderFunction,
|
||||
ActionFunction,
|
||||
MetaFunction,
|
||||
NavLink,
|
||||
Outlet,
|
||||
@@ -15,10 +16,11 @@ import { InfoBanner } from "~/components/tournament/InfoBanner";
|
||||
import { isTournamentAdmin } from "~/core/tournament/permissions";
|
||||
import { tournamentHasStarted } from "~/core/tournament/utils";
|
||||
import {
|
||||
checkIn,
|
||||
findTournamentByNameForUrl,
|
||||
FindTournamentByNameForUrlI,
|
||||
} from "~/services/tournament";
|
||||
import { makeTitle } from "~/utils";
|
||||
import { makeTitle, requireUser } from "~/utils";
|
||||
import type { MyCSSProperties } from "~/utils";
|
||||
import { useUser } from "~/utils/hooks";
|
||||
import tournamentStylesUrl from "../../styles/tournament.css";
|
||||
@@ -27,6 +29,28 @@ export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: tournamentStylesUrl }];
|
||||
};
|
||||
|
||||
export enum TournamentAction {
|
||||
CHECK_IN = "CHECK_IN",
|
||||
}
|
||||
|
||||
export const action: ActionFunction = async ({ request, context }) => {
|
||||
const data = Object.fromEntries(await request.formData());
|
||||
const user = requireUser(context);
|
||||
|
||||
switch (data._action) {
|
||||
case TournamentAction.CHECK_IN: {
|
||||
invariant(typeof data.teamId === "string", "Invalid type for teamId");
|
||||
|
||||
await checkIn({ teamId: data.teamId, userId: user.id });
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Response("Bad Request", { status: 400 });
|
||||
}
|
||||
}
|
||||
return new Response(undefined, { status: 200 });
|
||||
};
|
||||
|
||||
export const loader: LoaderFunction = ({ params }) => {
|
||||
invariant(
|
||||
typeof params.organization === "string",
|
||||
|
||||
@@ -85,10 +85,7 @@ export const action: ActionFunction = async ({
|
||||
return new Response("Player deleted from team", { status: 200 });
|
||||
}
|
||||
default: {
|
||||
return new Response(undefined, {
|
||||
status: 405,
|
||||
headers: { Allow: "POST, DELETE" },
|
||||
});
|
||||
throw new Response("Bad Request", { status: 400 });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user