diff --git a/web/src/components/error.tsx b/web/src/components/error.tsx index 5f22826..eb4cf29 100644 --- a/web/src/components/error.tsx +++ b/web/src/components/error.tsx @@ -3,14 +3,21 @@ import { ArrowLeft } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardDescription, CardTitle } from "@/components/ui/card"; +import { cn } from "@/lib/utils"; export function Error(props: { title: string; description: string; showBack?: boolean; + className?: string; }) { return ( - + {props.title} {props.description} {props.showBack && ( diff --git a/web/src/lib/query-keys.ts b/web/src/lib/query-keys.ts index 0234f7b..f69e92f 100644 --- a/web/src/lib/query-keys.ts +++ b/web/src/lib/query-keys.ts @@ -35,6 +35,19 @@ export function gameQueryKey(gameId: string, publisherId: string): QueryKey { return ["games", gameId, publisherId]; } +/** + * Query key used when fetching a game in the distribution routes. + * @param gameId Game ID. + * @param publisherId Publisher ID. + * @returns Game query key. + */ +export function distributeGameQueryKey( + gameId: string, + publisherId: string, +): QueryKey { + return ["games", "distribute", gameId, publisherId]; +} + /** * Query key used when fetching the cart information. */ diff --git a/web/src/routes/_layout/publishers_/$publisherId/games/$gameId.tsx b/web/src/routes/_layout/publishers_/$publisherId/games/$gameId.tsx index 50d472a..3dd10d2 100644 --- a/web/src/routes/_layout/publishers_/$publisherId/games/$gameId.tsx +++ b/web/src/routes/_layout/publishers_/$publisherId/games/$gameId.tsx @@ -11,6 +11,7 @@ import { differenceInYears, format, isAfter } from "date-fns"; import { Heart, Library, ShoppingCart, Star } from "lucide-react"; import { Carousel } from "@/components/carousel"; +import { Error } from "@/components/error"; import { Game } from "@/components/game"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; @@ -33,6 +34,7 @@ import { } from "@/lib/api"; import { decodeTokenPayload, getToken } from "@/lib/auth"; import { TAX, TO_BE_ANNOUNCED, TOAST_MESSAGES } from "@/lib/constants"; +import { BadRequest, NotFound } from "@/lib/errors"; import { withAuthErrors } from "@/lib/middleware"; import { gameQueryKey, userNavbarQueryKey } from "@/lib/query-keys"; import { getBatchPaginatedResponse } from "@/lib/request"; @@ -145,6 +147,22 @@ export const Route = createFileRoute( gameQueryOptions(opts.params.gameId, opts.params.publisherId), ); }, + errorComponent(errorProps) { + // If the game ID is not a valid UUID, a BadRequest is thrown. + // This error is visually identical to a NotFound error. + if ( + errorProps.error instanceof BadRequest || + errorProps.error instanceof NotFound + ) { + return ( + + ); + } + }, }); function Component() { diff --git a/web/src/routes/distribute/_layout/games/$gameId.tsx b/web/src/routes/distribute/_layout/games/$gameId.tsx index 802406d..66d71cd 100644 --- a/web/src/routes/distribute/_layout/games/$gameId.tsx +++ b/web/src/routes/distribute/_layout/games/$gameId.tsx @@ -17,7 +17,7 @@ import { getPublisherGame } from "@/lib/api"; import { decodeTokenPayload, getToken } from "@/lib/auth"; import { MISSING_VALUE_SYMBOL, TAX, TO_BE_ANNOUNCED } from "@/lib/constants"; import { BadRequest, NotFound } from "@/lib/errors"; -import { gameQueryKey } from "@/lib/query-keys"; +import { distributeGameQueryKey } from "@/lib/query-keys"; import { applyTax, formatCurrency, getLanguageName } from "@/lib/utils"; /** @@ -31,7 +31,7 @@ function publisherGameQueryOptions(gameId: string) { const publisherId = payload.sub; return queryOptions({ - queryKey: gameQueryKey(gameId, publisherId), + queryKey: distributeGameQueryKey(gameId, publisherId), async queryFn() { return await getPublisherGame(publisherId, gameId); },