diff --git a/app/features/calendar/loaders/calendar.$id.server.ts b/app/features/calendar/loaders/calendar.$id.server.ts index dbde17528..aa7e50aca 100644 --- a/app/features/calendar/loaders/calendar.$id.server.ts +++ b/app/features/calendar/loaders/calendar.$id.server.ts @@ -1,18 +1,18 @@ import type { LoaderFunctionArgs } from "@remix-run/node"; import { redirect } from "@remix-run/node"; -import { z } from "zod"; import * as CalendarRepository from "~/features/calendar/CalendarRepository.server"; -import { notFoundIfFalsy } from "~/utils/remix.server"; +import { notFoundIfFalsy, parseParams } from "~/utils/remix.server"; import { tournamentPage } from "~/utils/urls"; -import { actualNumber, id } from "~/utils/zod"; +import { idObject } from "~/utils/zod"; -export const loader = async ({ params }: LoaderFunctionArgs) => { - const parsedParams = z - .object({ id: z.preprocess(actualNumber, id) }) - .parse(params); +export const loader = async (args: LoaderFunctionArgs) => { + const params = parseParams({ + params: args.params, + schema: idObject, + }); const event = notFoundIfFalsy( await CalendarRepository.findById({ - id: parsedParams.id, + id: params.id, includeBadgePrizes: true, includeMapPool: true, }), @@ -24,6 +24,6 @@ export const loader = async ({ params }: LoaderFunctionArgs) => { return { event, - results: await CalendarRepository.findResultsByEventId(parsedParams.id), + results: await CalendarRepository.findResultsByEventId(params.id), }; }; diff --git a/app/features/top-search/loaders/xsearch.player.$id.server.ts b/app/features/top-search/loaders/xsearch.player.$id.server.ts index 0460792a8..50897bc00 100644 --- a/app/features/top-search/loaders/xsearch.player.$id.server.ts +++ b/app/features/top-search/loaders/xsearch.player.$id.server.ts @@ -1,12 +1,16 @@ import type { LoaderFunctionArgs } from "@remix-run/node"; import { removeDuplicates } from "~/utils/arrays"; -import { notFoundIfFalsy } from "~/utils/remix.server"; +import { notFoundIfFalsy, parseParams } from "~/utils/remix.server"; +import { idObject } from "~/utils/zod"; import { findPlacementsByPlayerId } from "../queries/findPlacements.server"; -export const loader = async ({ params }: LoaderFunctionArgs) => { - const placements = notFoundIfFalsy( - findPlacementsByPlayerId(Number(params.id)), - ); +export const loader = async (args: LoaderFunctionArgs) => { + const params = parseParams({ + params: args.params, + schema: idObject, + }); + + const placements = notFoundIfFalsy(findPlacementsByPlayerId(params.id)); const primaryName = placements[0].name; const aliases = removeDuplicates( diff --git a/app/features/top-search/queries/findPlacements.server.ts b/app/features/top-search/queries/findPlacements.server.ts index 97be32a03..ce5a4a25f 100644 --- a/app/features/top-search/queries/findPlacements.server.ts +++ b/app/features/top-search/queries/findPlacements.server.ts @@ -72,7 +72,7 @@ export function findPlacementsByPlayerId( playerId: Tables["XRankPlacement"]["playerId"], ) { const results = byPlayerStm.all({ playerId }) as Array; - if (!results) return null; + if (results.length === 0) return null; return results; } diff --git a/app/features/tournament-bracket/actions/to.$id.brackets.server.ts b/app/features/tournament-bracket/actions/to.$id.brackets.server.ts index 400699259..c2df28de3 100644 --- a/app/features/tournament-bracket/actions/to.$id.brackets.server.ts +++ b/app/features/tournament-bracket/actions/to.$id.brackets.server.ts @@ -50,7 +50,7 @@ export const action: ActionFunction = async ({ params, request }) => { invariant(bracket, "Bracket not found"); const seeding = bracket.seeding; - invariant(seeding, "Seeding not found"); + errorToastIfFalsy(seeding, "Bracket already started"); errorToastIfFalsy( bracket.canBeStarted, diff --git a/app/features/tournament/actions/to.$id.admin.server.ts b/app/features/tournament/actions/to.$id.admin.server.ts index a8d1da58a..e872282e1 100644 --- a/app/features/tournament/actions/to.$id.admin.server.ts +++ b/app/features/tournament/actions/to.$id.admin.server.ts @@ -208,6 +208,11 @@ export const action: ActionFunction = async ({ request, params }) => { const previousTeam = tournament.teamMemberOfByUser({ id: data.userId }); + errorToastIfFalsy( + !previousTeam?.id || previousTeam.id !== team.id, + "User is already in this team", + ); + errorToastIfFalsy( tournament.hasStarted || !previousTeam, "User is already in a team", diff --git a/app/utils/zod.ts b/app/utils/zod.ts index 458a30246..729c4d37c 100644 --- a/app/utils/zod.ts +++ b/app/utils/zod.ts @@ -8,6 +8,9 @@ import type { Unpacked } from "./types"; import { assertType } from "./types"; export const id = z.coerce.number({ message: "Required" }).int().positive(); +export const idObject = z.object({ + id, +}); export const optionalId = z.coerce.number().int().positive().optional(); export const nonEmptyString = z.string().trim().min(1, {