mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-23 07:34:07 -05:00
Enable rest of the Remix future flags
This commit is contained in:
parent
b2b13e6aa7
commit
98edb4896f
|
|
@ -38,7 +38,7 @@ export function NavDialog({
|
|||
to={`/${item.url}`}
|
||||
className="layout__overlay-nav__nav-item"
|
||||
key={item.name}
|
||||
prefetch={item.prefetch ? "render" : undefined}
|
||||
prefetch={item.prefetch ? "intent" : undefined}
|
||||
onClick={close}
|
||||
>
|
||||
<div className="layout__overlay-nav__nav-image-container">
|
||||
|
|
|
|||
|
|
@ -25,5 +25,5 @@ export const action: ActionFunction = async ({ request }) => {
|
|||
|
||||
await seed(variation);
|
||||
|
||||
return null;
|
||||
return Response.json(null);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
import * as CalendarRepository from "~/features/calendar/CalendarRepository.server";
|
||||
|
|
@ -35,7 +35,7 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
: null,
|
||||
}));
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
||||
function fetchEventsOfWeek(args: { week: number; year: number }) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
|
|
@ -73,5 +73,5 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
})),
|
||||
};
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
|
|
@ -155,5 +155,5 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
mapList: await mapList(),
|
||||
};
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
|
|
@ -36,5 +36,5 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
})),
|
||||
};
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
|
|
@ -46,5 +46,5 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
},
|
||||
};
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
|
|
@ -143,5 +143,5 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
};
|
||||
});
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
|
|
@ -88,5 +88,5 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
isFinalized: Boolean(tournament.isFinalized),
|
||||
};
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
||||
import { cors } from "remix-utils/cors";
|
||||
import { z } from "zod";
|
||||
|
|
@ -119,5 +119,5 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
})),
|
||||
};
|
||||
|
||||
return await cors(request, json(result));
|
||||
return await cors(request, Response.json(result));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import type { ShouldRevalidateFunction } from "@remix-run/react";
|
||||
import { useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -16,6 +12,7 @@ import i18next from "~/modules/i18n/i18next.server";
|
|||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { makeTitle } from "~/utils/strings";
|
||||
import { artPage, navIconUrl } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { ArtGrid } from "../components/ArtGrid";
|
||||
import { allArtTags } from "../queries/allArtTags.server";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
import Markdown from "markdown-to-jsx";
|
||||
import * as React from "react";
|
||||
|
|
@ -17,6 +13,7 @@ import {
|
|||
articlePreviewUrl,
|
||||
navIconUrl,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { articleBySlug } from "../core/bySlug.server";
|
||||
|
||||
export const handle: SendouRouteHandle = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { LoaderFunctionArgs, SerializeFrom } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { Outlet, useLoaderData, useMatches, useParams } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -8,6 +8,7 @@ import { Redirect } from "~/components/Redirect";
|
|||
import { useUser } from "~/features/auth/core/user";
|
||||
import { canEditBadgeOwners, isMod } from "~/permissions";
|
||||
import { BADGES_PAGE } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import * as BadgeRepository from "../BadgeRepository.server";
|
||||
import { badgeExplanationText } from "../badges-utils";
|
||||
import type { BadgesLoaderData } from "./badges";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import { NavLink, Outlet, useLoaderData } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -10,6 +9,7 @@ import { SearchIcon } from "~/components/icons/Search";
|
|||
import { useUser } from "~/features/auth/core/user";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { BADGES_DOC_LINK, BADGES_PAGE, navIconUrl } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import * as BadgeRepository from "../BadgeRepository.server";
|
||||
|
||||
import "~/styles/badges.css";
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
import { cachified } from "@epic-web/cachified";
|
||||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -24,6 +20,7 @@ import {
|
|||
outlinedMainWeaponImageUrl,
|
||||
weaponBuildPage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { popularBuilds } from "../build-stats-utils";
|
||||
import { abilitiesByWeaponId } from "../queries/abilitiesByWeaponId.server";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
import { cachified } from "@epic-web/cachified";
|
||||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Ability } from "~/components/Ability";
|
||||
|
|
@ -24,6 +20,7 @@ import {
|
|||
outlinedMainWeaponImageUrl,
|
||||
weaponBuildPage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { abilityPointCountsToAverages } from "../build-stats-utils";
|
||||
import { averageAbilityPoints } from "../queries/averageAbilityPoints.server";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MetaFunction, SerializeFrom } from "@remix-run/node";
|
||||
import type { MetaFunction } from "@remix-run/node";
|
||||
import {
|
||||
type ShouldRevalidateFunction,
|
||||
useLoaderData,
|
||||
|
|
@ -24,7 +24,7 @@ import {
|
|||
PATCHES,
|
||||
} from "~/constants";
|
||||
import { safeJSONParse } from "~/utils/json";
|
||||
import { isRevalidation } from "~/utils/remix";
|
||||
import { type SerializeFrom, isRevalidation } from "~/utils/remix";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
import { redirect } from "@remix-run/node";
|
||||
import type {
|
||||
ActionFunction,
|
||||
LoaderFunctionArgs,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { ActionFunction, LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { Form, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
|
|
@ -28,6 +24,7 @@ import {
|
|||
import type { Unpacked } from "~/utils/types";
|
||||
import { calendarEventPage } from "~/utils/urls";
|
||||
import { actualNumber, id, safeJSONParse, toArray } from "~/utils/zod";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
const playersSchema = z
|
||||
.array(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import type {
|
|||
ActionFunction,
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
|
|
@ -55,6 +54,7 @@ import {
|
|||
userPage,
|
||||
} from "~/utils/urls";
|
||||
import { actualNumber, id } from "~/utils/zod";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { Tags } from "../components/Tags";
|
||||
|
||||
import "~/styles/calendar-event.css";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MetaFunction, SerializeFrom } from "@remix-run/node";
|
||||
import type { MetaFunction } from "@remix-run/node";
|
||||
import { Form, useFetcher, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import Compressor from "compressorjs";
|
||||
|
|
@ -37,6 +37,7 @@ import invariant from "~/utils/invariant";
|
|||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { pathnameFromPotentialURL } from "~/utils/strings";
|
||||
import { CREATING_TOURNAMENT_DOC_LINK, userSubmittedImage } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import {
|
||||
CALENDAR_EVENT,
|
||||
REG_CLOSES_AT_OPTIONS,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { Link, useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import { addDays, addMonths, subDays, subMonths } from "date-fns";
|
||||
|
|
@ -49,6 +45,7 @@ import type {
|
|||
CalendarEventTag,
|
||||
PersistedCalendarEventTag,
|
||||
} from "../../../db/types";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import * as CalendarRepository from "../CalendarRepository.server";
|
||||
import { calendarEventTagSchema } from "../actions/calendar.new.server";
|
||||
import { CALENDAR_EVENT } from "../calendar-constants";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import * as CalendarRepository from "~/features/calendar/CalendarRepository.server";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
export const loader = async () => {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ function DesktopSideNav() {
|
|||
<Link
|
||||
to={`/${item.url}`}
|
||||
key={item.name}
|
||||
prefetch={item.prefetch ? "render" : undefined}
|
||||
prefetch={item.prefetch ? "intent" : undefined}
|
||||
className="front-page__side-nav-item"
|
||||
>
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import type { Unwrapped } from "../../../utils/types";
|
||||
|
||||
export type PatronsListLoaderData = SerializeFrom<typeof loader>;
|
||||
export type PatronsListLoaderData = {
|
||||
patrons: Array<Unwrapped<typeof UserRepository.findAllPatrons>>;
|
||||
};
|
||||
|
||||
export const loader = async () => {
|
||||
return json(
|
||||
return Response.json(
|
||||
{
|
||||
patrons: await UserRepository.findAllPatrons(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export async function cachedFullUserLeaderboard(season: number) {
|
|||
});
|
||||
}
|
||||
|
||||
function addTiers(entries: UserSPLeaderboardItem[], season: number) {
|
||||
function addTiers<T extends { id: number }>(entries: T[], season: number) {
|
||||
const tiers = freshUserSkills(season);
|
||||
|
||||
const encounteredTiers = new Set<string>();
|
||||
|
|
@ -140,7 +140,7 @@ export function ownEntryPeek({
|
|||
userId,
|
||||
season,
|
||||
}: {
|
||||
leaderboard: UserSPLeaderboardItem[];
|
||||
leaderboard: UserLeaderboardWithAdditionsItem[];
|
||||
userId: number;
|
||||
season: number;
|
||||
}) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
import { cachified } from "@epic-web/cachified";
|
||||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { Link, useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -40,6 +36,7 @@ import {
|
|||
userSubmittedImage,
|
||||
} from "~/utils/urls";
|
||||
import { InfoPopover } from "../../../components/InfoPopover";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { TopTenPlayer } from "../components/TopTenPlayer";
|
||||
import {
|
||||
cachedFullUserLeaderboard,
|
||||
|
|
@ -340,7 +337,7 @@ function OwnEntryPeek({
|
|||
entry,
|
||||
nextTier,
|
||||
}: {
|
||||
entry: NonNullable<SerializeFrom<typeof loader>["userLeaderboard"]>[number];
|
||||
entry: NonNullable<SerializeFrom<typeof loader>["ownEntryPeek"]>["entry"];
|
||||
nextTier?: SkillTierInterval;
|
||||
}) {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MetaFunction, SerializeFrom } from "@remix-run/node";
|
||||
import type { MetaFunction } from "@remix-run/node";
|
||||
import { useFetcher, useLoaderData } from "@remix-run/react";
|
||||
import { add, sub } from "date-fns";
|
||||
import React from "react";
|
||||
|
|
@ -13,6 +13,7 @@ import type { SendouRouteHandle } from "~/utils/remix.server";
|
|||
import { makeTitle } from "~/utils/strings";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
import { LFG_PAGE, navIconUrl } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { LFGAddFilterButton } from "../components/LFGAddFilterButton";
|
||||
import { LFGFilters } from "../components/LFGFilters";
|
||||
import { LFGPost } from "../components/LFGPost";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import type { ShouldRevalidateFunction } from "@remix-run/react";
|
||||
import { Link, useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
|
|
@ -28,6 +24,7 @@ import {
|
|||
ipLabsMaps,
|
||||
navIconUrl,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { generateMapList } from "../core/map-list-generator/map-list";
|
||||
import { modesOrder } from "../core/map-list-generator/modes";
|
||||
import { mapPoolToNonEmptyModes } from "../core/map-list-generator/utils";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
ActionFunction,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { ActionFunction, MetaFunction } from "@remix-run/node";
|
||||
import type { ShouldRevalidateFunction } from "@remix-run/react";
|
||||
import { Link, Outlet, useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
|
|
@ -41,6 +37,7 @@ import { makeTitle } from "~/utils/strings";
|
|||
import { assertUnreachable } from "~/utils/types";
|
||||
import { userPage } from "~/utils/urls";
|
||||
import { _action, actualNumber } from "~/utils/zod";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
|
|
@ -341,7 +338,7 @@ function SuggestedUser({
|
|||
size="tiny"
|
||||
variant="outlined"
|
||||
to={`comment/${tier}/${suggestion.suggested.id}?tier=${tier}`}
|
||||
prefetch="render"
|
||||
prefetch="intent"
|
||||
>
|
||||
Comment
|
||||
</LinkButton>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { Link, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import type { UserWithPlusTier } from "~/db/types";
|
||||
|
|
@ -14,6 +10,7 @@ import { roundToNDecimalPlaces } from "~/utils/number";
|
|||
import { makeTitle } from "~/utils/strings";
|
||||
import { PLUS_SERVER_DISCORD_URL, userPage } from "~/utils/urls";
|
||||
import { isAtLeastFiveDollarTierPatreon } from "~/utils/users";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
import "~/styles/plus-history.css";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { SerializeFrom } from "@remix-run/server-runtime";
|
||||
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
||||
import { db } from "~/db/sql";
|
||||
import type { UserMapModePreferences } from "~/db/tables";
|
||||
|
|
@ -11,6 +10,7 @@ import {
|
|||
wrappedLoader,
|
||||
} from "~/utils/Test";
|
||||
import invariant from "~/utils/invariant";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import type { lookingSchema, matchSchema } from "../q-schemas.server";
|
||||
import { loader, action as rawLookingAction } from "./q.looking";
|
||||
import { action as rawMatchAction } from "./q.match.$id";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type {
|
|||
ActionFunctionArgs,
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import type { FetcherWithComponents } from "@remix-run/react";
|
||||
|
|
@ -83,6 +82,7 @@ import {
|
|||
teamPage,
|
||||
userSubmittedImage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { GroupCard } from "../components/GroupCard";
|
||||
import { matchEndedAtIndex } from "../core/match";
|
||||
import { compareMatchToReportedScores } from "../core/match.server";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import type {
|
|||
ActionFunction,
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import { Link, useFetcher, useLoaderData } from "@remix-run/react";
|
||||
|
|
@ -56,6 +55,7 @@ import {
|
|||
userSeasonsPage,
|
||||
} from "~/utils/urls";
|
||||
import { isAtLeastFiveDollarTierPatreon } from "~/utils/users";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { FULL_GROUP_SIZE, JOIN_CODE_SEARCH_PARAM_KEY } from "../q-constants";
|
||||
import { frontPageSchema } from "../q-schemas.server";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { LoaderFunctionArgs, SerializeFrom } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { requireUserId } from "~/features/auth/core/user.server";
|
||||
import * as QRepository from "~/features/sendouq/QRepository.server";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
export type TrustersLoaderData = SerializeFrom<typeof loader>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { LoaderFunctionArgs, SerializeFrom } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { parseSearchParams } from "~/utils/remix.server";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { weaponUsageSearchParamsSchema } from "../q-schemas.server";
|
||||
import { weaponUsageStats } from "../queries/weaponUsageStats.server";
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import type {
|
|||
ActionFunction,
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import { Form, Link, useLoaderData } from "@remix-run/react";
|
||||
|
|
@ -34,6 +33,7 @@ import {
|
|||
teamPage,
|
||||
uploadImagePage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import * as TeamRepository from "../TeamRepository.server";
|
||||
import { TEAM } from "../team-constants";
|
||||
import { editTeamSchema, teamParamsSchema } from "../team-schemas.server";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type {
|
|||
ActionFunction,
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import { Form, useFetcher, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
|
|
@ -32,6 +31,7 @@ import {
|
|||
navIconUrl,
|
||||
teamPage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import * as TeamRepository from "../TeamRepository.server";
|
||||
import { editRole } from "../queries/editRole.server";
|
||||
import { inviteCodeById } from "../queries/inviteCodeById.server";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { REGULAR_USER_TEST_ID } from "~/db/seed/constants";
|
||||
import { db } from "~/db/sql";
|
||||
|
|
@ -8,6 +7,7 @@ import {
|
|||
wrappedAction,
|
||||
wrappedLoader,
|
||||
} from "~/utils/Test";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { loader as userProfileLoader } from "../../user-page/loaders/u.$identifier.index.server";
|
||||
import * as TeamRepository from "../TeamRepository.server";
|
||||
import { action as _teamPageAction } from "../actions/t.$customUrl.server";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MetaFunction, SerializeFrom } from "@remix-run/node";
|
||||
import type { MetaFunction } from "@remix-run/node";
|
||||
import { Link, useFetcher, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
|
|
@ -31,6 +31,7 @@ import {
|
|||
userPage,
|
||||
userSubmittedImage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import type * as TeamRepository from "../TeamRepository.server";
|
||||
import { isTeamMember, isTeamOwner } from "../team-utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
type ActionFunction,
|
||||
type LoaderFunction,
|
||||
json,
|
||||
data,
|
||||
redirect,
|
||||
} from "@remix-run/node";
|
||||
import { isTheme } from "../core/provider";
|
||||
|
|
@ -14,21 +14,21 @@ export const action: ActionFunction = async ({ request }) => {
|
|||
const theme = form.get("theme");
|
||||
|
||||
if (theme === "auto") {
|
||||
return json(
|
||||
return data(
|
||||
{ success: true },
|
||||
{ headers: { "Set-Cookie": await themeSession.destroy() } },
|
||||
);
|
||||
}
|
||||
|
||||
if (!isTheme(theme)) {
|
||||
return json({
|
||||
return data({
|
||||
success: false,
|
||||
message: `theme value of ${theme ?? "null"} is not a valid theme`,
|
||||
});
|
||||
}
|
||||
|
||||
themeSession.setTheme(theme);
|
||||
return json(
|
||||
return data(
|
||||
{ success: true },
|
||||
{ headers: { "Set-Cookie": await themeSession.commit() } },
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { Link, useLoaderData } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Main } from "~/components/Main";
|
||||
|
|
@ -16,6 +12,7 @@ import {
|
|||
topSearchPlayerPage,
|
||||
userPage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { PlacementsTable } from "../components/Placements";
|
||||
import { findPlacementsByPlayerId } from "../queries/findPlacements.server";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import type { TFunction } from "i18next";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -7,6 +6,7 @@ import { Dialog } from "~/components/Dialog";
|
|||
import { MapIcon } from "~/components/icons/Map";
|
||||
import { useTournament } from "~/features/tournament/routes/to.$id";
|
||||
import { nullFilledArray } from "~/utils/arrays";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import type { TournamentMatchLoaderData } from "../routes/to.$id.matches.$mid";
|
||||
import { pickInfoText } from "../tournament-bracket-utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import { Form, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import type { TFunction } from "i18next";
|
||||
|
|
@ -27,6 +26,7 @@ import {
|
|||
specialWeaponImageUrl,
|
||||
stageImageUrl,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import type { Bracket } from "../core/Bracket";
|
||||
import * as PickBan from "../core/PickBan";
|
||||
import type { TournamentDataTeam } from "../core/Tournament.server";
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import clsx from "clsx";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import type { MonthYear } from "~/features/plus-voting/core";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import { databaseTimestampToDate, nullPaddedDatesOfMonth } from "~/utils/dates";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import type { loader } from "../loaders/org.$slug.server";
|
||||
|
||||
interface EventCalendarProps {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { MetaFunction, SerializeFrom } from "@remix-run/node";
|
||||
import type { MetaFunction } from "@remix-run/node";
|
||||
import { Link, useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
|
|
@ -24,6 +24,7 @@ import {
|
|||
userPage,
|
||||
userSubmittedImage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { EventCalendar } from "../components/EventCalendar";
|
||||
import { SocialLinksList } from "../components/SocialLinksList";
|
||||
import { TOURNAMENT_SERIES_EVENTS_PER_PAGE } from "../tournament-organization-constants";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { UserIcon } from "~/components/icons/User";
|
||||
import { twitchThumbnailUrlToSrc } from "~/modules/twitch/utils";
|
||||
import { twitchUrl } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { useTournament } from "../routes/to.$id";
|
||||
import type { TournamentStreamsLoader } from "../routes/to.$id.streams";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import {
|
||||
Outlet,
|
||||
type ShouldRevalidateFunction,
|
||||
|
|
@ -29,6 +25,7 @@ import {
|
|||
tournamentPage,
|
||||
userSubmittedImage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { streamsByTournamentId } from "../core/streams.server";
|
||||
import {
|
||||
HACKY_resolvePicture,
|
||||
|
|
@ -248,10 +245,10 @@ export function TournamentLayout() {
|
|||
<SubNavLink to="register" data-testid="register-tab" prefetch="intent">
|
||||
{tournament.hasStarted ? "Info" : t("tournament:tabs.register")}
|
||||
</SubNavLink>
|
||||
<SubNavLink to="brackets" data-testid="brackets-tab" prefetch="render">
|
||||
<SubNavLink to="brackets" data-testid="brackets-tab" prefetch="intent">
|
||||
{t("tournament:tabs.brackets")}
|
||||
</SubNavLink>
|
||||
<SubNavLink to="teams" end={false} prefetch="render">
|
||||
<SubNavLink to="teams" end={false} prefetch="intent">
|
||||
{t("tournament:tabs.teams", { count: tournament.ctx.teams.length })}
|
||||
</SubNavLink>
|
||||
{!tournament.everyBracketOver && tournament.subsFeatureEnabled && (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { LoaderFunctionArgs, SerializeFrom } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { notFoundIfFalsy } from "~/utils/remix.server";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
export type UserResultsLoaderData = SerializeFrom<typeof loader>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { LoaderFunctionArgs, SerializeFrom } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import {
|
||||
Link,
|
||||
useLoaderData,
|
||||
|
|
@ -55,6 +55,7 @@ import invariant from "~/utils/invariant";
|
|||
import { cutToNDecimalPlaces, roundToNDecimalPlaces } from "~/utils/number";
|
||||
import { type SendouRouteHandle, notFoundIfFalsy } from "~/utils/remix.server";
|
||||
import { TIERS_PAGE, sendouQMatchPage, userSeasonsPage } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import {
|
||||
seasonsSearchParamsSchema,
|
||||
userParamsSchema,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { Outlet, useLoaderData, useLocation } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Main } from "~/components/Main";
|
||||
|
|
@ -23,6 +19,7 @@ import {
|
|||
userSeasonsPage,
|
||||
userVodsPage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
import "~/styles/u.css";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { LoaderFunctionArgs, SerializeFrom } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { Link, useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from "~/utils/remix.server";
|
||||
import { USER_SEARCH_PAGE, navIconUrl, userPage } from "~/utils/urls";
|
||||
import { queryToUserIdentifier } from "~/utils/users";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
|
||||
import "~/styles/u.css";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
|
|
@ -30,6 +26,7 @@ import {
|
|||
stageImageUrl,
|
||||
vodVideoPage,
|
||||
} from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { PovUser } from "../components/VodPov";
|
||||
import { findVodById } from "../queries/findVodById.server";
|
||||
import type { Vod } from "../vods-types";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
|
|
@ -14,6 +10,7 @@ import { mainWeaponIds, modesShort, stageIds } from "~/modules/in-game-lists";
|
|||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { makeTitle } from "~/utils/strings";
|
||||
import { VODS_PAGE, navIconUrl } from "~/utils/urls";
|
||||
import type { SerializeFrom } from "../../../utils/remix";
|
||||
import { VodListing } from "../components/VodListing";
|
||||
import { findVods } from "../queries/findVods.server";
|
||||
import { VODS_PAGE_BATCH_SIZE, videoMatchTypes } from "../vods-constants";
|
||||
|
|
|
|||
16
app/root.tsx
16
app/root.tsx
|
|
@ -1,9 +1,5 @@
|
|||
import type {
|
||||
LoaderFunctionArgs,
|
||||
MetaFunction,
|
||||
SerializeFrom,
|
||||
} from "@remix-run/node";
|
||||
import { json, redirect } from "@remix-run/node";
|
||||
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
||||
import { data, redirect } from "@remix-run/node";
|
||||
import {
|
||||
Links,
|
||||
Meta,
|
||||
|
|
@ -37,9 +33,11 @@ import {
|
|||
} from "./features/theme/core/provider";
|
||||
import { getThemeSession } from "./features/theme/core/session.server";
|
||||
import { useIsMounted } from "./hooks/useIsMounted";
|
||||
import { useVisibilityChange } from "./hooks/useVisibilityChange";
|
||||
import { DEFAULT_LANGUAGE } from "./modules/i18n/config";
|
||||
import i18next, { i18nCookie } from "./modules/i18n/i18next.server";
|
||||
import type { Namespace } from "./modules/i18n/resources.server";
|
||||
import { type SerializeFrom, isRevalidation } from "./utils/remix";
|
||||
import { COMMON_PREVIEW_IMAGE, SUSPENDED_PAGE } from "./utils/urls";
|
||||
|
||||
import "nprogress/nprogress.css";
|
||||
|
|
@ -49,8 +47,6 @@ import "~/styles/layout.css";
|
|||
import "~/styles/reset.css";
|
||||
import "~/styles/utils.css";
|
||||
import "~/styles/vars.css";
|
||||
import { useVisibilityChange } from "./hooks/useVisibilityChange";
|
||||
import { isRevalidation } from "./utils/remix";
|
||||
|
||||
export const shouldRevalidate: ShouldRevalidateFunction = (args) => {
|
||||
if (isRevalidation(args)) return true;
|
||||
|
|
@ -92,7 +88,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|||
return redirect(SUSPENDED_PAGE);
|
||||
}
|
||||
|
||||
return json(
|
||||
return data(
|
||||
{
|
||||
locale,
|
||||
theme: themeSession.getTheme(),
|
||||
|
|
@ -281,7 +277,7 @@ export default function App() {
|
|||
// useLoaderData can't be used in CatchBoundary and layout is rendered in it as well
|
||||
//
|
||||
// Update 14.10.23: not sure if this still applies as the CatchBoundary is gone
|
||||
const data = useLoaderData<RootLoaderData>();
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
|
|
|
|||
|
|
@ -83,10 +83,3 @@ export function isNotVisible(locator: Locator) {
|
|||
export function modalClickConfirmButton(page: Page) {
|
||||
return page.getByTestId("confirm-button").click();
|
||||
}
|
||||
|
||||
export async function fetchSendouInk<T>(url: string) {
|
||||
const res = await fetch(`http://localhost:5173${url}`);
|
||||
if (!res.ok) throw new Error("Response not successful");
|
||||
|
||||
return res.json() as T;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { json } from "@remix-run/node";
|
||||
import { data } from "@remix-run/node";
|
||||
import {
|
||||
unstable_composeUploadHandlers as composeUploadHandlers,
|
||||
unstable_createMemoryUploadHandler as createMemoryUploadHandler,
|
||||
|
|
@ -255,8 +255,8 @@ export type SendouRouteHandle = {
|
|||
* To be used when the response is different for each user. This is especially useful when the response
|
||||
* is prefetched on link hover.
|
||||
*/
|
||||
export function privatelyCachedJson<T>(data: T) {
|
||||
return json(data, {
|
||||
export function privatelyCachedJson<T>(value: T) {
|
||||
return data(value, {
|
||||
headers: { "Cache-Control": "private, max-age=5" },
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
import type { ShouldRevalidateFunctionArgs } from "@remix-run/react";
|
||||
import type {
|
||||
ShouldRevalidateFunctionArgs,
|
||||
useLoaderData,
|
||||
} from "@remix-run/react";
|
||||
|
||||
export function isRevalidation(args: ShouldRevalidateFunctionArgs) {
|
||||
return (
|
||||
args.defaultShouldRevalidate && args.nextUrl.href === args.currentUrl.href
|
||||
);
|
||||
}
|
||||
|
||||
// https://remix.run/docs/en/main/start/future-flags#serializefrom
|
||||
export type SerializeFrom<T> = ReturnType<typeof useLoaderData<T>>;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@ import { expect, test } from "@playwright/test";
|
|||
import { ADMIN_ID } from "~/constants";
|
||||
import { NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { BANNED_MAPS } from "~/features/sendouq-settings/banned-maps";
|
||||
import type { TournamentLoaderData } from "~/features/tournament/routes/to.$id";
|
||||
import type { StageId } from "~/modules/in-game-lists";
|
||||
import { rankedModesShort } from "~/modules/in-game-lists/modes";
|
||||
import invariant from "~/utils/invariant";
|
||||
import {
|
||||
fetchSendouInk,
|
||||
impersonate,
|
||||
isNotVisible,
|
||||
navigate,
|
||||
|
|
@ -16,35 +14,41 @@ import {
|
|||
submit,
|
||||
} from "~/utils/playwright";
|
||||
import { tournamentBracketsPage, tournamentPage } from "~/utils/urls";
|
||||
import { tournamentFromDB } from "../app/features/tournament-bracket/core/Tournament.server";
|
||||
|
||||
const fetchTournamentLoaderData = () =>
|
||||
fetchSendouInk<TournamentLoaderData>(
|
||||
"/to/1/admin?_data=features%2Ftournament%2Froutes%2Fto.%24id",
|
||||
);
|
||||
tournamentFromDB({ tournamentId: 1, user: { id: ADMIN_ID } });
|
||||
|
||||
const getIsOwnerOfUser = ({
|
||||
data,
|
||||
teams,
|
||||
userId,
|
||||
teamId,
|
||||
}: {
|
||||
data: TournamentLoaderData;
|
||||
teams: Array<{
|
||||
id: number;
|
||||
members: Array<{ userId: number; isOwner: number }>;
|
||||
}>;
|
||||
userId: number;
|
||||
teamId: number;
|
||||
}) => {
|
||||
const team = data.tournament.ctx.teams.find((t) => t.id === teamId);
|
||||
const team = teams.find((t) => t.id === teamId);
|
||||
invariant(team, "Team not found");
|
||||
|
||||
return team.members.find((m) => m.userId === userId)?.isOwner;
|
||||
};
|
||||
|
||||
const getTeamCheckedInAt = ({
|
||||
data,
|
||||
teams,
|
||||
teamId,
|
||||
}: {
|
||||
data: TournamentLoaderData;
|
||||
teams: Array<{
|
||||
id: number;
|
||||
checkIns: unknown[];
|
||||
members: Array<{ userId: number }>;
|
||||
}>;
|
||||
teamId: number;
|
||||
}) => {
|
||||
const team = data.tournament.ctx.teams.find((t) => t.id === teamId);
|
||||
const team = teams.find((t) => t.id === teamId);
|
||||
invariant(team, "Team not found");
|
||||
return team.checkIns.length > 0;
|
||||
};
|
||||
|
|
@ -128,43 +132,67 @@ test.describe("Tournament", () => {
|
|||
await page.getByLabel("Team name").fill("NSTC");
|
||||
await submit(page);
|
||||
|
||||
const data = await fetchTournamentLoaderData();
|
||||
const firstTeam = data.tournament.ctx.teams.find((t) => t.id === 1);
|
||||
const tournament = await fetchTournamentLoaderData();
|
||||
const firstTeam = tournament.ctx.teams.find((t) => t.id === 1);
|
||||
invariant(firstTeam, "First team not found");
|
||||
expect(firstTeam.name).toBe("NSTC");
|
||||
}
|
||||
|
||||
// Change team owner
|
||||
let data = await fetchTournamentLoaderData();
|
||||
expect(getIsOwnerOfUser({ data, userId: ADMIN_ID, teamId: 1 })).toBe(1);
|
||||
let tournament = await fetchTournamentLoaderData();
|
||||
expect(
|
||||
getIsOwnerOfUser({
|
||||
teams: tournament.ctx.teams,
|
||||
userId: ADMIN_ID,
|
||||
teamId: 1,
|
||||
}),
|
||||
).toBe(1);
|
||||
|
||||
await actionSelect.selectOption("CHANGE_TEAM_OWNER");
|
||||
await teamSelect.selectOption("1");
|
||||
await memberSelect.selectOption("2");
|
||||
await submit(page);
|
||||
|
||||
data = await fetchTournamentLoaderData();
|
||||
expect(getIsOwnerOfUser({ data, userId: ADMIN_ID, teamId: 1 })).toBe(0);
|
||||
expect(getIsOwnerOfUser({ data, userId: NZAP_TEST_ID, teamId: 1 })).toBe(1);
|
||||
tournament = await fetchTournamentLoaderData();
|
||||
expect(
|
||||
getIsOwnerOfUser({
|
||||
teams: tournament.ctx.teams,
|
||||
userId: ADMIN_ID,
|
||||
teamId: 1,
|
||||
}),
|
||||
).toBe(0);
|
||||
expect(
|
||||
getIsOwnerOfUser({
|
||||
teams: tournament.ctx.teams,
|
||||
userId: NZAP_TEST_ID,
|
||||
teamId: 1,
|
||||
}),
|
||||
).toBe(1);
|
||||
|
||||
// Check in team
|
||||
expect(getTeamCheckedInAt({ data, teamId: 1 })).toBeFalsy();
|
||||
expect(
|
||||
getTeamCheckedInAt({ teams: tournament.ctx.teams, teamId: 1 }),
|
||||
).toBeFalsy();
|
||||
|
||||
await actionSelect.selectOption("CHECK_IN");
|
||||
await submit(page);
|
||||
|
||||
data = await fetchTournamentLoaderData();
|
||||
expect(getTeamCheckedInAt({ data, teamId: 1 })).toBeTruthy();
|
||||
tournament = await fetchTournamentLoaderData();
|
||||
expect(
|
||||
getTeamCheckedInAt({ teams: tournament.ctx.teams, teamId: 1 }),
|
||||
).toBeTruthy();
|
||||
|
||||
// Check out team
|
||||
await actionSelect.selectOption("CHECK_OUT");
|
||||
await submit(page);
|
||||
|
||||
data = await fetchTournamentLoaderData();
|
||||
expect(getTeamCheckedInAt({ data, teamId: 1 })).toBeFalsy();
|
||||
tournament = await fetchTournamentLoaderData();
|
||||
expect(
|
||||
getTeamCheckedInAt({ teams: tournament.ctx.teams, teamId: 1 }),
|
||||
).toBeFalsy();
|
||||
|
||||
// Remove member...
|
||||
const firstTeam = data.tournament.ctx.teams.find((t) => t.id === 1);
|
||||
const firstTeam = tournament.ctx.teams.find((t) => t.id === 1);
|
||||
invariant(firstTeam, "First team not found");
|
||||
const firstNonOwnerMember = firstTeam.members.find(
|
||||
(m) => m.userId !== 1 && !m.isOwner,
|
||||
|
|
@ -175,13 +203,13 @@ test.describe("Tournament", () => {
|
|||
await memberSelect.selectOption(String(firstNonOwnerMember.userId));
|
||||
await submit(page);
|
||||
|
||||
data = await fetchTournamentLoaderData();
|
||||
const firstTeamAgain = data.tournament.ctx.teams.find((t) => t.id === 1);
|
||||
tournament = await fetchTournamentLoaderData();
|
||||
const firstTeamAgain = tournament.ctx.teams.find((t) => t.id === 1);
|
||||
invariant(firstTeamAgain, "First team again not found");
|
||||
expect(firstTeamAgain.members.length).toBe(firstTeam.members.length - 1);
|
||||
|
||||
// ...and add to another team
|
||||
const teamWithSpace = data.tournament.ctx.teams.find(
|
||||
const teamWithSpace = tournament.ctx.teams.find(
|
||||
(t) => t.id !== 1 && t.members.length === 4,
|
||||
);
|
||||
invariant(teamWithSpace, "Team with space not found");
|
||||
|
|
@ -195,8 +223,8 @@ test.describe("Tournament", () => {
|
|||
});
|
||||
await submit(page);
|
||||
|
||||
data = await fetchTournamentLoaderData();
|
||||
const teamWithSpaceAgain = data.tournament.ctx.teams.find(
|
||||
tournament = await fetchTournamentLoaderData();
|
||||
const teamWithSpaceAgain = tournament.ctx.teams.find(
|
||||
(t) => t.id === teamWithSpace.id,
|
||||
);
|
||||
invariant(teamWithSpaceAgain, "Team with space again not found");
|
||||
|
|
@ -210,7 +238,7 @@ test.describe("Tournament", () => {
|
|||
await teamSelect.selectOption("1");
|
||||
await submit(page);
|
||||
|
||||
data = await fetchTournamentLoaderData();
|
||||
expect(data.tournament.ctx.teams.find((t) => t.id === 1)).toBeFalsy();
|
||||
tournament = await fetchTournamentLoaderData();
|
||||
expect(tournament.ctx.teams.find((t) => t.id === 1)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
"biome:fix:unsafe": "npx @biomejs/biome check --write --unsafe .",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test:unit": "cross-env VITE_SITE_DOMAIN=http://localhost:5173 vitest run",
|
||||
"test:e2e": "npx playwright test",
|
||||
"test:e2e": "cross-env DB_PATH=db.sqlite3 npx playwright test",
|
||||
"checks": "npm run biome:fix && npm run test:unit && npm run check-translation-jsons && npm run typecheck"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import { vitePlugin as remix } from "@remix-run/dev";
|
||||
import { installGlobals } from "@remix-run/node";
|
||||
import { defineConfig } from "vite";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
import { configDefaults } from "vitest/config";
|
||||
|
||||
installGlobals();
|
||||
declare module "@remix-run/server-runtime" {
|
||||
interface Future {
|
||||
v3_singleFetch: true;
|
||||
}
|
||||
}
|
||||
|
||||
export default defineConfig(() => {
|
||||
return {
|
||||
|
|
@ -20,6 +23,8 @@ export default defineConfig(() => {
|
|||
v3_relativeSplatPath: true,
|
||||
v3_throwAbortReason: true,
|
||||
v3_routeConfig: true,
|
||||
v3_singleFetch: true,
|
||||
v3_lazyRouteDiscovery: true,
|
||||
},
|
||||
}),
|
||||
tsconfigPaths(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user