mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-01 00:24:13 -05:00
Remove MyForm component
This commit is contained in:
parent
e08a0f529b
commit
cdd59b139d
|
|
@ -50,7 +50,7 @@ You can give a variation as a flag to the seeding script changing what exactly i
|
|||
|
||||
- [x] Captain can remove players from roster
|
||||
- [x] Add info about architecture to README
|
||||
- [ ] Move away from MyForm
|
||||
- [x] Move away from MyForm
|
||||
- [x] Make description mandatory + overview tab
|
||||
- [x] Captain can check in
|
||||
- [x] Admin can check teams in / out
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
import { Form, FormProps, useFetcher, useTransition } from "remix";
|
||||
|
||||
interface MyFormProps extends FormProps {
|
||||
hiddenFields?: Record<string, string>;
|
||||
fetcher?: ReturnType<typeof useFetcher>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around Remix's Form that has default method of "post",
|
||||
* creates <input type="hidden"> elements for each key/value pair in hiddenFields,
|
||||
* automatically uses fetcher.Form when action is provided
|
||||
* and disables the form when it's submitting.
|
||||
*/
|
||||
export function MyForm(props: MyFormProps) {
|
||||
const { hiddenFields, children, fetcher, ...rest } = props;
|
||||
|
||||
const FormComponent = fetcher ? fetcher.Form : Form;
|
||||
|
||||
const transition = useTransition();
|
||||
return (
|
||||
<FormComponent method="post" {...rest}>
|
||||
<fieldset disabled={transition.state !== "idle"}>
|
||||
{hiddenFields &&
|
||||
Object.entries(hiddenFields).map(([key, value]) => (
|
||||
<input key={key} type="hidden" name={key} value={value} />
|
||||
))}
|
||||
{children}
|
||||
</fieldset>
|
||||
</FormComponent>
|
||||
);
|
||||
}
|
||||
|
|
@ -10,7 +10,6 @@ import { Button } from "../Button";
|
|||
import { AlertIcon } from "../icons/Alert";
|
||||
import { ErrorIcon } from "../icons/Error";
|
||||
import { SuccessIcon } from "../icons/Success";
|
||||
import { MyForm } from "../MyForm";
|
||||
import { ActionSectionWrapper } from "./ActionSectionWrapper";
|
||||
|
||||
export function ActionSectionBeforeStartContent({
|
||||
|
|
@ -109,10 +108,10 @@ export function ActionSectionBeforeStartContent({
|
|||
<AlertIcon /> Check-in closes in less than a minute
|
||||
</>
|
||||
)}
|
||||
<MyForm
|
||||
<fetcher.Form
|
||||
method="post"
|
||||
action={`/api/tournamentTeam/${ownTeam.id}/check-in`}
|
||||
className="tournament__action-section__button-container"
|
||||
fetcher={fetcher}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
|
|
@ -122,7 +121,7 @@ export function ActionSectionBeforeStartContent({
|
|||
>
|
||||
Check-in
|
||||
</Button>
|
||||
</MyForm>
|
||||
</fetcher.Form>
|
||||
</ActionSectionWrapper>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import * as React from "react";
|
|||
import { useFetcher, useMatches } from "remix";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Button } from "~/components/Button";
|
||||
import { MyForm } from "~/components/MyForm";
|
||||
import { TOURNAMENT_TEAM_ROSTER_MIN_SIZE } from "~/constants";
|
||||
import { checkInHasStarted } from "~/core/tournament/utils";
|
||||
import type { FindTournamentByNameForUrlI } from "~/services/tournament";
|
||||
|
|
@ -27,7 +26,7 @@ import type { Unpacked } from "~/utils";
|
|||
import { useTimeoutState } from "~/utils/hooks";
|
||||
|
||||
// TODO: https://docs.dndkit.com/presets/sortable#drag-overlay
|
||||
// TODO: what if returns error? check other APIs too
|
||||
// TODO: what if returns error? check other APIs too -> add Cypress test
|
||||
export function AdminTeamControls() {
|
||||
const seedsFetcher = useFetcher();
|
||||
const [, parentRoute] = useMatches();
|
||||
|
|
@ -224,10 +223,10 @@ function SortableRow({
|
|||
function CheckOutButton({ teamId }: { teamId: string }) {
|
||||
const fetcher = useFetcher();
|
||||
return (
|
||||
<MyForm
|
||||
<fetcher.Form
|
||||
method="post"
|
||||
action={`/api/tournamentTeam/${teamId}/check-out`}
|
||||
className="tournament__action-section__button-container"
|
||||
fetcher={fetcher}
|
||||
>
|
||||
<Button
|
||||
tiny
|
||||
|
|
@ -238,17 +237,17 @@ function CheckOutButton({ teamId }: { teamId: string }) {
|
|||
>
|
||||
Check-out
|
||||
</Button>
|
||||
</MyForm>
|
||||
</fetcher.Form>
|
||||
);
|
||||
}
|
||||
|
||||
function CheckInButton({ teamId }: { teamId: string }) {
|
||||
const fetcher = useFetcher();
|
||||
return (
|
||||
<MyForm
|
||||
<fetcher.Form
|
||||
method="post"
|
||||
action={`/api/tournamentTeam/${teamId}/check-in`}
|
||||
className="tournament__action-section__button-container"
|
||||
fetcher={fetcher}
|
||||
>
|
||||
<Button
|
||||
tiny
|
||||
|
|
@ -259,6 +258,6 @@ function CheckInButton({ teamId }: { teamId: string }) {
|
|||
>
|
||||
Check-in
|
||||
</Button>
|
||||
</MyForm>
|
||||
</fetcher.Form>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { useFetcher } from "remix";
|
||||
import { useUser } from "~/utils/hooks";
|
||||
import { Button } from "../Button";
|
||||
import { MyForm } from "../MyForm";
|
||||
|
||||
export function TeamRoster({
|
||||
team,
|
||||
|
|
@ -79,10 +78,9 @@ function DeleteFromRosterButton({
|
|||
}) {
|
||||
const fetcher = useFetcher();
|
||||
return (
|
||||
<MyForm
|
||||
action={`/api/tournamentTeam/${teamId}/remove-player/${playerId}`}
|
||||
<fetcher.Form
|
||||
method="delete"
|
||||
fetcher={fetcher}
|
||||
action={`/api/tournamentTeam/${teamId}/remove-player/${playerId}`}
|
||||
>
|
||||
<Button
|
||||
variant="destructive"
|
||||
|
|
@ -92,6 +90,6 @@ function DeleteFromRosterButton({
|
|||
>
|
||||
Remove
|
||||
</Button>
|
||||
</MyForm>
|
||||
</fetcher.Form>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { ActionFunction, LinksFunction, LoaderFunction } from "remix";
|
||||
import { ActionFunction, Form, LinksFunction, LoaderFunction } from "remix";
|
||||
import {
|
||||
json,
|
||||
redirect,
|
||||
|
|
@ -9,7 +9,6 @@ import {
|
|||
} from "remix";
|
||||
import invariant from "tiny-invariant";
|
||||
import { Button } from "~/components/Button";
|
||||
import { MyForm } from "~/components/MyForm";
|
||||
import {
|
||||
FindTournamentByNameForUrlI,
|
||||
findTournamentWithInviteCodes,
|
||||
|
|
@ -169,12 +168,13 @@ function Contents({ data }: { data: Data }) {
|
|||
<div>
|
||||
{data.inviterName} invited you to join {data.teamName} for this
|
||||
tournament. Accept invite?
|
||||
<MyForm
|
||||
hiddenFields={{
|
||||
tournamentId: parentRouteData.id,
|
||||
inviteCode: data.inviteCode,
|
||||
}}
|
||||
>
|
||||
<Form method="post">
|
||||
<input
|
||||
type="hidden"
|
||||
name="tournamentId"
|
||||
value={parentRouteData.id}
|
||||
/>
|
||||
<input type="hidden" name="inviteCode" value={data.inviteCode} />
|
||||
<div className="tournament__join-team__buttons">
|
||||
<Button
|
||||
type="submit"
|
||||
|
|
@ -193,7 +193,7 @@ function Contents({ data }: { data: Data }) {
|
|||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</MyForm>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Prisma } from ".prisma/client";
|
||||
import * as React from "react";
|
||||
import {
|
||||
ActionFunction,
|
||||
Form,
|
||||
json,
|
||||
LinksFunction,
|
||||
LoaderFunction,
|
||||
|
|
@ -13,7 +13,6 @@ import invariant from "tiny-invariant";
|
|||
import { Alert } from "~/components/Alert";
|
||||
import { Button } from "~/components/Button";
|
||||
import ErrorMessage from "~/components/ErrorMessage";
|
||||
import { MyForm } from "~/components/MyForm";
|
||||
import { TeamRoster } from "~/components/tournament/TeamRoster";
|
||||
import { TOURNAMENT_TEAM_ROSTER_MAX_SIZE } from "~/constants";
|
||||
import {
|
||||
|
|
@ -157,7 +156,8 @@ export default function ManageRosterPage() {
|
|||
</div>
|
||||
{trustingUsers.length > 0 && (
|
||||
<div className="tournament__manage-roster__actions__section">
|
||||
<MyForm hiddenFields={{ teamId: ownTeam.id }}>
|
||||
<Form method="post">
|
||||
<input type="hidden" name="teamId" value={ownTeam.id} />
|
||||
<label htmlFor="userId">
|
||||
Add players you previously played with
|
||||
</label>
|
||||
|
|
@ -182,7 +182,7 @@ export default function ManageRosterPage() {
|
|||
>
|
||||
Add to roster
|
||||
</Button>
|
||||
</MyForm>
|
||||
</Form>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Prisma } from ".prisma/client";
|
||||
import {
|
||||
ActionFunction,
|
||||
Form,
|
||||
LinksFunction,
|
||||
redirect,
|
||||
useActionData,
|
||||
|
|
@ -12,7 +13,6 @@ import {
|
|||
import invariant from "tiny-invariant";
|
||||
import { Button } from "~/components/Button";
|
||||
import ErrorMessage from "~/components/ErrorMessage";
|
||||
import { MyForm } from "~/components/MyForm";
|
||||
import {
|
||||
createTournamentTeam,
|
||||
FindTournamentByNameForUrlI,
|
||||
|
|
@ -120,7 +120,8 @@ export default function RegisterPage() {
|
|||
<div className="tournament__register__container">
|
||||
<h2 className="tournament__register__header">Register now</h2>
|
||||
<div className="tournament__register__content">
|
||||
<MyForm hiddenFields={{ tournamentId: tournamentData.id }}>
|
||||
<Form method="post">
|
||||
<input type="hidden" name="tournamentId" value={tournamentData.id} />
|
||||
<label htmlFor="teamName">Team name</label>
|
||||
<input
|
||||
name="teamName"
|
||||
|
|
@ -153,7 +154,7 @@ export default function RegisterPage() {
|
|||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</MyForm>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user