From 3e14bb4320e1cbbe9692b2605d4df1fc3978fdc3 Mon Sep 17 00:00:00 2001 From: "Kalle (Sendou)" <38327916+Sendouc@users.noreply.github.com> Date: Sun, 26 Dec 2021 19:23:35 +0200 Subject: [PATCH] Edit team info: friend code, room pass & canHost --- app/core/tournament/utils.ts | 3 + app/models/Tournament.ts | 3 + app/models/TournamentTeam.ts | 24 ++++ .../manage-roster.tsx | 130 ++++++++++++++++-- .../to/$organization.$tournament/register.tsx | 5 +- app/services/tournament.ts | 42 +++++- app/styles/global.css | 51 ++++++- app/styles/tournament-register.css | 4 - 8 files changed, 237 insertions(+), 25 deletions(-) diff --git a/app/core/tournament/utils.ts b/app/core/tournament/utils.ts index 0330947d2..e55080eea 100644 --- a/app/core/tournament/utils.ts +++ b/app/core/tournament/utils.ts @@ -38,3 +38,6 @@ export function tournamentHasStarted( export const friendCodeRegExpString = "^(SW-)?[0-9]{4}-?[0-9]{4}-?[0-9]{4}$"; export const friendCodeRegExp = new RegExp(friendCodeRegExpString, "i"); + +export const roompassRegExpString = "^[0-9]{4}$"; +export const roompassRegExp = new RegExp(roompassRegExpString, "i"); diff --git a/app/models/Tournament.ts b/app/models/Tournament.ts index 94a4b9708..c33643c89 100644 --- a/app/models/Tournament.ts +++ b/app/models/Tournament.ts @@ -113,6 +113,9 @@ export function findByNameForUrlWithInviteCodes(tournamentNameForUrl: string) { name: true, inviteCode: true, checkedInTime: true, + friendCode: true, + roomPass: true, + canHost: true, members: { select: { captain: true, diff --git a/app/models/TournamentTeam.ts b/app/models/TournamentTeam.ts index 6bc9cb747..5d6bae5aa 100644 --- a/app/models/TournamentTeam.ts +++ b/app/models/TournamentTeam.ts @@ -60,3 +60,27 @@ export function checkOut(id: string) { }, }); } + +export type EditTeam = Prisma.PromiseReturnType; +export function editTeam({ + id, + friendCode, + roomPass, + canHost, +}: { + id: string; + friendCode: string; + roomPass: string | null; + canHost: boolean; +}) { + return db.tournamentTeam.update({ + where: { + id, + }, + data: { + friendCode, + roomPass, + canHost, + }, + }); +} diff --git a/app/routes/to/$organization.$tournament/manage-roster.tsx b/app/routes/to/$organization.$tournament/manage-roster.tsx index be6aa1de9..5347c76f8 100644 --- a/app/routes/to/$organization.$tournament/manage-roster.tsx +++ b/app/routes/to/$organization.$tournament/manage-roster.tsx @@ -8,30 +8,39 @@ import { useActionData, useLoaderData, useLocation, + useTransition, } from "remix"; import invariant from "tiny-invariant"; import { Alert } from "~/components/Alert"; import { Button } from "~/components/Button"; +import { Catcher } from "~/components/Catcher"; import { FormErrorMessage } from "~/components/FormErrorMessage"; +import { FormInfoText } from "~/components/FormInfoText"; import { TeamRoster } from "~/components/tournament/TeamRoster"; import { TOURNAMENT_TEAM_ROSTER_MAX_SIZE } from "~/constants"; import { + friendCodeRegExpString, + roompassRegExp, + roompassRegExpString, +} from "~/core/tournament/utils"; +import type { FindManyByTrustReceiverId } from "~/models/TrustRelationship"; +import { + editTeam, ownTeamWithInviteCode, putPlayerToTeam, removePlayerFromTeam, } from "~/services/tournament"; import { getTrustingUsers } from "~/services/user"; -import type { FindManyByTrustReceiverId } from "~/models/TrustRelationship"; import styles from "~/styles/tournament-manage-roster.css"; import { requireUser } from "~/utils"; import { useBaseURL, useIsSubmitting, useTimeoutState } from "~/utils/hooks"; -import { Catcher } from "~/components/Catcher"; export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; }; export enum ManageRosterAction { + EDIT_TEAM = "EDIT_TEAM", ADD_PLAYER = "ADD_PLAYER", DELETE_PLAYER = "DELETE_PLAYER", } @@ -48,7 +57,6 @@ export const action: ActionFunction = async ({ context, }): Promise => { const data = Object.fromEntries(await request.formData()); - invariant(typeof data.userId === "string", "Invalid type for userId"); invariant(typeof data.teamId === "string", "Invalid type for teamId"); invariant(typeof data._action === "string", "Invalid type for _action"); @@ -56,6 +64,8 @@ export const action: ActionFunction = async ({ switch (data._action) { case ManageRosterAction.ADD_PLAYER: { + invariant(typeof data.userId === "string", "Invalid type for userId"); + try { await putPlayerToTeam({ teamId: data.teamId, @@ -77,13 +87,39 @@ export const action: ActionFunction = async ({ return new Response("Added player to team", { status: 200 }); } case ManageRosterAction.DELETE_PLAYER: { + invariant(typeof data.userId === "string", "Invalid type for userId"); + await removePlayerFromTeam({ - captainId: user.id, + userId: user.id, playerId: data.userId, teamId: data.teamId, }); return new Response("Player deleted from team", { status: 200 }); } + case ManageRosterAction.EDIT_TEAM: { + invariant( + typeof data.friendCode === "string", + "Invalid type for friendCode" + ); + invariant(typeof data.roomPass === "string", "Invalid type for roomPass"); + invariant( + ["yes", "no"].includes(data.canHost as string), + "Invalid type for canHost" + ); + + if (!roompassRegExp.test(data.roomPass)) { + return new Response("Invalid room pass", { status: 400 }); + } + + await editTeam({ + friendCode: data.friendCode, + roomPass: data.roomPass, + teamId: data.teamId, + canHost: data.canHost === "yes" ? true : false, + userId: user.id, + }); + return new Response("Tournament team edited", { status: 200 }); + } default: { throw new Response("Bad Request", { status: 400 }); } @@ -130,6 +166,7 @@ export default function ManageRosterPage() { const { ownTeam, trustingUsers } = useLoaderData(); const baseURL = useBaseURL(); const location = useLocation(); + const transition = useTransition(); const isSubmitting = useIsSubmitting("POST"); const urlWithInviteCode = `${baseURL}${location.pathname.replace( @@ -147,12 +184,85 @@ export default function ManageRosterPage() {
- {ownTeam.members.length < TOURNAMENT_TEAM_ROSTER_MAX_SIZE && ( -
-
-
+ )}
); diff --git a/app/routes/to/$organization.$tournament/register.tsx b/app/routes/to/$organization.$tournament/register.tsx index 41c6b057b..22e44336a 100644 --- a/app/routes/to/$organization.$tournament/register.tsx +++ b/app/routes/to/$organization.$tournament/register.tsx @@ -148,10 +148,7 @@ export default function RegisterPage() { data-cy="team-name-input" /> -