mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
Refactor app/constants away
This commit is contained in:
parent
cc4b1037ba
commit
84cdd58fe8
|
|
@ -2,7 +2,7 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useDebounce } from "react-use";
|
||||
import { CUSTOM_CSS_VAR_COLORS } from "~/constants";
|
||||
import { CUSTOM_CSS_VAR_COLORS } from "~/features/user-page/user-page-constants";
|
||||
import { Button } from "./Button";
|
||||
import { InfoPopover } from "./InfoPopover";
|
||||
import { Label } from "./Label";
|
||||
|
|
|
|||
146
app/constants.ts
146
app/constants.ts
|
|
@ -1,146 +0,0 @@
|
|||
import type { BuildAbilitiesTupleWithUnknown } from "./modules/in-game-lists/types";
|
||||
|
||||
export const TWEET_LENGTH_MAX_LENGTH = 280;
|
||||
export const DISCORD_MESSAGE_MAX_LENGTH = 2000;
|
||||
|
||||
export const USER = {
|
||||
BIO_MAX_LENGTH: DISCORD_MESSAGE_MAX_LENGTH,
|
||||
CUSTOM_URL_MAX_LENGTH: 32,
|
||||
CUSTOM_NAME_MAX_LENGTH: 32,
|
||||
BATTLEFY_MAX_LENGTH: 32,
|
||||
IN_GAME_NAME_TEXT_MAX_LENGTH: 20,
|
||||
IN_GAME_NAME_DISCRIMINATOR_MAX_LENGTH: 5,
|
||||
WEAPON_POOL_MAX_SIZE: 5,
|
||||
COMMISSION_TEXT_MAX_LENGTH: 1000,
|
||||
};
|
||||
|
||||
export const PlUS_SUGGESTION_FIRST_COMMENT_MAX_LENGTH = 500;
|
||||
export const PlUS_SUGGESTION_COMMENT_MAX_LENGTH = TWEET_LENGTH_MAX_LENGTH;
|
||||
|
||||
export const CALENDAR_EVENT_RESULT = {
|
||||
MAX_PARTICIPANTS_COUNT: 1000,
|
||||
MAX_PLAYERS_LENGTH: 8,
|
||||
MAX_TEAM_NAME_LENGTH: 100,
|
||||
MAX_TEAM_PLACEMENT: 256,
|
||||
MAX_PLAYER_NAME_LENGTH: 100,
|
||||
} as const;
|
||||
|
||||
export const BUILD = {
|
||||
TITLE_MIN_LENGTH: 1,
|
||||
TITLE_MAX_LENGTH: 50,
|
||||
DESCRIPTION_MAX_LENGTH: TWEET_LENGTH_MAX_LENGTH,
|
||||
MAX_WEAPONS_COUNT: 5,
|
||||
MAX_COUNT: 250,
|
||||
} as const;
|
||||
|
||||
export const MAPS = {
|
||||
CODE_MIN_LENGTH: 2,
|
||||
CODE_MAX_LENGTH: 32,
|
||||
};
|
||||
|
||||
export const BUILDS_PAGE_BATCH_SIZE = 24;
|
||||
export const BUILDS_PAGE_MAX_BUILDS = 240;
|
||||
|
||||
export const INVITE_CODE_LENGTH = 10;
|
||||
|
||||
export const EMPTY_BUILD: BuildAbilitiesTupleWithUnknown = [
|
||||
["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"],
|
||||
["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"],
|
||||
["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"],
|
||||
];
|
||||
|
||||
export const PLUS_TIERS = [1, 2, 3];
|
||||
|
||||
export const PLUS_UPVOTE = 1;
|
||||
export const PLUS_DOWNVOTE = -1;
|
||||
|
||||
export const ADMIN_DISCORD_ID = "79237403620945920";
|
||||
export const ADMIN_ID = process.env.NODE_ENV === "test" ? 1 : 274;
|
||||
|
||||
// Panda Scep
|
||||
export const STAFF_IDS = [11329, 9719];
|
||||
export const STAFF_DISCORD_IDS = ["138757634500067328", "184478601171828737"];
|
||||
|
||||
export const LOHI_TOKEN_HEADER_NAME = "Lohi-Token";
|
||||
export const SKALOP_TOKEN_HEADER_NAME = "Skalop-Token";
|
||||
|
||||
export const CUSTOMIZED_CSS_VARS_NAME = "css";
|
||||
|
||||
export const MAX_AP = 57;
|
||||
|
||||
export const TEN_MINUTES_IN_MS = 10 * 60 * 1000;
|
||||
export const HALF_HOUR_IN_MS = 30 * 60 * 1000;
|
||||
export const ONE_HOUR_IN_MS = 60 * 60 * 1000;
|
||||
export const TWO_HOURS_IN_MS = 2 * 60 * 60 * 1000;
|
||||
|
||||
export const SPLATOON_3_XP_BADGE_VALUES = [
|
||||
5000, 4500, 4000, 3500, 3400, 3300, 3200, 3100, 3000, 2900, 2800, 2700, 2600,
|
||||
] as const;
|
||||
export const findSplatoon3XpBadgeValue = (xPower: number) => {
|
||||
for (const value of SPLATOON_3_XP_BADGE_VALUES) {
|
||||
if (xPower >= value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const PATCHES = [
|
||||
{
|
||||
patch: "9.3.0",
|
||||
date: "2025-03-13",
|
||||
},
|
||||
{
|
||||
patch: "9.2.0",
|
||||
date: "2024-11-20",
|
||||
},
|
||||
{
|
||||
patch: "9.0.0",
|
||||
date: "2024-08-29",
|
||||
},
|
||||
// {
|
||||
// patch: "8.1.0",
|
||||
// date: "2024-07-17",
|
||||
// },
|
||||
// {
|
||||
// patch: "8.0.0",
|
||||
// date: "2024-05-31",
|
||||
// },
|
||||
// {
|
||||
// patch: "7.2.0",
|
||||
// date: "2024-04-17",
|
||||
// },
|
||||
// {
|
||||
// patch: "7.0.0",
|
||||
// date: "2024-02-21",
|
||||
// },
|
||||
// {
|
||||
// patch: "6.1.0",
|
||||
// date: "2024-01-24",
|
||||
// },
|
||||
// {
|
||||
// patch: "6.0.0",
|
||||
// date: "2023-11-29",
|
||||
// },
|
||||
// {
|
||||
// patch: "5.1.0",
|
||||
// date: "2023-10-17",
|
||||
// },
|
||||
// {
|
||||
// patch: "5.0.0",
|
||||
// date: "2023-08-30",
|
||||
// },
|
||||
];
|
||||
|
||||
export const CUSTOM_CSS_VAR_COLORS = [
|
||||
"bg",
|
||||
"bg-darker",
|
||||
"bg-lighter",
|
||||
"bg-lightest",
|
||||
"text",
|
||||
"text-lighter",
|
||||
"theme",
|
||||
"theme-secondary",
|
||||
"chat",
|
||||
] as const;
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
import { faker } from "@faker-js/faker";
|
||||
import { add, sub } from "date-fns";
|
||||
import { nanoid } from "nanoid";
|
||||
import * as R from "remeda";
|
||||
import { ADMIN_DISCORD_ID, ADMIN_ID, INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { db, sql } from "~/db/sql";
|
||||
import { ADMIN_DISCORD_ID, ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import type { SeedVariation } from "~/features/api-private/routes/seed";
|
||||
import * as AssociationRepository from "~/features/associations/AssociationRepository.server";
|
||||
import * as BuildRepository from "~/features/builds/BuildRepository.server";
|
||||
|
|
@ -69,6 +68,7 @@ import type { TournamentMapListMap } from "~/modules/tournament-map-list-generat
|
|||
import { SENDOUQ_DEFAULT_MAPS } from "~/modules/tournament-map-list-generator/constants";
|
||||
import { nullFilledArray } from "~/utils/arrays";
|
||||
import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { mySlugify } from "~/utils/urls";
|
||||
import type { Tables, UserMapModePreferences } from "../tables";
|
||||
|
|
@ -1269,7 +1269,7 @@ function calendarEventWithToToolsTeams(
|
|||
name,
|
||||
createdAt: dateToDatabaseTimestamp(new Date()),
|
||||
tournamentId,
|
||||
inviteCode: nanoid(INVITE_CODE_LENGTH),
|
||||
inviteCode: shortNanoid(),
|
||||
});
|
||||
|
||||
// in PICNIC & PP Chimera is not checked in + in LUTI no check-ins at all
|
||||
|
|
@ -1605,7 +1605,7 @@ const detailedTeam = (seedVariation?: SeedVariation | null) => () => {
|
|||
values (
|
||||
'Alliance Rogue',
|
||||
'alliance-rogue',
|
||||
'${nanoid(INVITE_CODE_LENGTH)}',
|
||||
'${shortNanoid()}',
|
||||
'${faker.lorem.paragraph()}',
|
||||
1,
|
||||
2
|
||||
|
|
@ -1682,7 +1682,7 @@ function otherTeams() {
|
|||
id: i,
|
||||
name: teamName,
|
||||
customUrl: teamCustomUrl,
|
||||
inviteCode: nanoid(INVITE_CODE_LENGTH),
|
||||
inviteCode: shortNanoid(),
|
||||
bio: faker.lorem.paragraph(),
|
||||
});
|
||||
|
||||
|
|
|
|||
6
app/features/admin/admin-constants.ts
Normal file
6
app/features/admin/admin-constants.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export const ADMIN_DISCORD_ID = "79237403620945920";
|
||||
export const ADMIN_ID = process.env.NODE_ENV === "test" ? 1 : 274;
|
||||
|
||||
// Panda Scep
|
||||
export const STAFF_IDS = [11329, 9719];
|
||||
export const STAFF_DISCORD_IDS = ["138757634500067328", "184478601171828737"];
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
import { TWEET_LENGTH_MAX_LENGTH } from "~/constants";
|
||||
|
||||
export const ART_PER_PAGE = 14;
|
||||
|
||||
export const ART = {
|
||||
DESCRIPTION_MAX_LENGTH: TWEET_LENGTH_MAX_LENGTH / 2,
|
||||
DESCRIPTION_MAX_LENGTH: 140,
|
||||
LINKED_USERS_MAX_LENGTH: 10,
|
||||
THUMBNAIL_WIDTH: 640,
|
||||
TAG_MAX_LENGTH: 100,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
||||
import { nanoid } from "nanoid";
|
||||
import { INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { db } from "~/db/sql";
|
||||
import type { TablesInsertable, TablesUpdatable } from "~/db/tables";
|
||||
import type { AssociationVirtualIdentifier } from "~/features/associations/associations-constants";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { logger } from "~/utils/logger";
|
||||
|
||||
|
|
@ -130,7 +129,7 @@ export function insert({ userId, ...associationArgs }: InsertArgs) {
|
|||
return db.transaction().execute(async (trx) => {
|
||||
const association = await trx
|
||||
.insertInto("Association")
|
||||
.values({ ...associationArgs, inviteCode: nanoid(INVITE_CODE_LENGTH) })
|
||||
.values({ ...associationArgs, inviteCode: shortNanoid() })
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
|
||||
|
|
@ -155,7 +154,7 @@ export function update(
|
|||
export function refreshInviteCode(associationId: number) {
|
||||
return db
|
||||
.updateTable("Association")
|
||||
.set({ inviteCode: nanoid(INVITE_CODE_LENGTH) })
|
||||
.set({ inviteCode: shortNanoid() })
|
||||
.where("id", "=", associationId)
|
||||
.execute();
|
||||
}
|
||||
|
|
|
|||
7
app/features/badges/badges-constants.ts
Normal file
7
app/features/badges/badges-constants.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export const BADGE = {
|
||||
SMALL_BADGES_PER_DISPLAY_PAGE: 9,
|
||||
};
|
||||
|
||||
export const SPLATOON_3_XP_BADGE_VALUES = [
|
||||
5000, 4500, 4000, 3500, 3400, 3300, 3200, 3100, 3000, 2900, 2800, 2700, 2600,
|
||||
] as const;
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
export const BADGE = {
|
||||
SMALL_BADGES_PER_DISPLAY_PAGE: 9,
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type { TFunction } from "i18next";
|
||||
import { SPLATOON_3_XP_BADGE_VALUES } from "~/constants";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { SPLATOON_3_XP_BADGE_VALUES } from "./badges-constants";
|
||||
|
||||
export function badgeExplanationText(
|
||||
t: TFunction<"badges", undefined>,
|
||||
|
|
@ -22,3 +22,13 @@ export function badgeExplanationText(
|
|||
tournament: badge.displayName,
|
||||
}).replace("'", "'");
|
||||
}
|
||||
|
||||
export const findSplatoon3XpBadgeValue = (xPower: number) => {
|
||||
for (const value of SPLATOON_3_XP_BADGE_VALUES) {
|
||||
if (xPower >= value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Button } from "~/components/Button";
|
|||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { BADGE } from "~/features/badges/badges-contants";
|
||||
import { BADGE } from "~/features/badges/badges-constants";
|
||||
import { usePagination } from "~/hooks/usePagination";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
import { badgeExplanationText } from "../badges-utils";
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import {
|
||||
SPLATOON_3_XP_BADGE_VALUES,
|
||||
findSplatoon3XpBadgeValue,
|
||||
} from "~/constants";
|
||||
import { sql } from "~/db/sql";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { SPLATOON_3_XP_BADGE_VALUES } from "../badges-constants";
|
||||
import { findSplatoon3XpBadgeValue } from "../badges-utils";
|
||||
|
||||
const badgeCodeToIdStm = sql.prepare(/* sql */ `
|
||||
select "id"
|
||||
|
|
|
|||
|
|
@ -124,3 +124,5 @@ export const multiShot = Object.fromEntries(
|
|||
export const RAINMAKER_SPEED_PENALTY_MODIFIER = 0.8;
|
||||
|
||||
export const UNKNOWN_SHORT = "U";
|
||||
|
||||
export const MAX_AP = 57;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Ability } from "~/components/Ability";
|
||||
import { MAX_AP } from "~/constants";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
||||
import { SendouButton } from "../../../components/elements/Button";
|
||||
import { SendouPopover } from "../../../components/elements/Popover";
|
||||
import { MAX_AP } from "../analyzer-constants";
|
||||
import type { FullInkTankOption } from "../analyzer-types";
|
||||
import { fullInkTankOptions } from "../core/stats";
|
||||
import { weaponParams } from "../core/utils";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { MAX_AP } from "~/constants";
|
||||
import { MAX_AP } from "../analyzer-constants";
|
||||
import type { AbilityPoints } from "../analyzer-types";
|
||||
|
||||
export const SPECIAL_EFFECTS = [
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EMPTY_BUILD } from "~/constants";
|
||||
import { EMPTY_BUILD } from "~/features/builds/builds-constants";
|
||||
import { abilities } from "~/modules/in-game-lists/abilities";
|
||||
import type {
|
||||
Ability,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import { Main } from "~/components/Main";
|
|||
import { Table } from "~/components/Table";
|
||||
import { Tab, Tabs } from "~/components/Tabs";
|
||||
import { BeakerIcon } from "~/components/icons/Beaker";
|
||||
import { MAX_AP } from "~/constants";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import { abilitiesShort } from "~/modules/in-game-lists/abilities";
|
||||
|
|
@ -50,6 +49,7 @@ import { SendouButton } from "../../../components/elements/Button";
|
|||
import { SendouPopover } from "../../../components/elements/Popover";
|
||||
import { metaTags } from "../../../utils/remix";
|
||||
import {
|
||||
MAX_AP,
|
||||
MAX_LDE_INTENSITY,
|
||||
damageTypeToWeaponType,
|
||||
} from "../analyzer-constants";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { MAX_AP } from "~/constants";
|
||||
import { abilities } from "~/modules/in-game-lists/abilities";
|
||||
import type { Ability } from "~/modules/in-game-lists/types";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { roundToNDecimalPlaces } from "~/utils/number";
|
||||
import { MAX_AP } from "../build-analyzer/analyzer-constants";
|
||||
import { isStackableAbility } from "../build-analyzer/core/utils";
|
||||
import type { AbilitiesByWeapon } from "./queries/abilitiesByWeaponId.server";
|
||||
import type { AverageAbilityPointsResult } from "./queries/averageAbilityPoints.server";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { cachified } from "@epic-web/cachified";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { ONE_HOUR_IN_MS } from "~/constants";
|
||||
import { i18next } from "~/modules/i18n/i18next.server";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { IN_MILLISECONDS, cache, ttl } from "~/utils/cache.server";
|
||||
import { notFoundIfNullLike } from "~/utils/remix.server";
|
||||
import { weaponNameSlugToId } from "~/utils/unslugify.server";
|
||||
import { popularBuilds } from "../build-stats-utils";
|
||||
|
|
@ -18,7 +17,7 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
const cachedPopularBuilds = await cachified({
|
||||
key: `popular-builds-${weaponId}`,
|
||||
cache,
|
||||
ttl: ttl(ONE_HOUR_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.ONE_HOUR),
|
||||
async getFreshValue() {
|
||||
return popularBuilds(abilitiesByWeaponId(weaponId));
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { cachified } from "@epic-web/cachified";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { ONE_HOUR_IN_MS } from "~/constants";
|
||||
import { i18next } from "~/modules/i18n/i18next.server";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { IN_MILLISECONDS, cache, ttl } from "~/utils/cache.server";
|
||||
import { notFoundIfNullLike } from "~/utils/remix.server";
|
||||
import { weaponNameSlugToId } from "~/utils/unslugify.server";
|
||||
import { abilityPointCountsToAverages } from "../build-stats-utils";
|
||||
|
|
@ -17,7 +16,7 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
const cachedStats = await cachified({
|
||||
key: `build-stats-${weaponId}`,
|
||||
cache,
|
||||
ttl: ttl(ONE_HOUR_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.ONE_HOUR),
|
||||
async getFreshValue() {
|
||||
return abilityPointCountsToAverages({
|
||||
allAbilities: averageAbilityPoints(),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { useTranslation } from "react-i18next";
|
|||
import { Ability } from "~/components/Ability";
|
||||
import { WeaponImage } from "~/components/Image";
|
||||
import { Main } from "~/components/Main";
|
||||
import { MAX_AP } from "~/constants";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import {
|
||||
BUILDS_PAGE,
|
||||
|
|
@ -18,6 +17,7 @@ import { loader } from "../loaders/builds.$slug.stats.server";
|
|||
export { loader };
|
||||
|
||||
import "../build-stats.css";
|
||||
import { MAX_AP } from "~/features/build-analyzer/analyzer-constants";
|
||||
|
||||
export const meta: MetaFunction<typeof loader> = (args) => {
|
||||
if (!args.data) return [];
|
||||
|
|
|
|||
|
|
@ -1,3 +1,69 @@
|
|||
import type { BuildAbilitiesTupleWithUnknown } from "~/modules/in-game-lists/types";
|
||||
|
||||
export const MAX_BUILD_FILTERS = 6;
|
||||
|
||||
export const FILTER_SEARCH_PARAM_KEY = "f";
|
||||
|
||||
export const PATCHES = [
|
||||
{
|
||||
patch: "9.3.0",
|
||||
date: "2025-03-13",
|
||||
},
|
||||
{
|
||||
patch: "9.2.0",
|
||||
date: "2024-11-20",
|
||||
},
|
||||
{
|
||||
patch: "9.0.0",
|
||||
date: "2024-08-29",
|
||||
},
|
||||
// {
|
||||
// patch: "8.1.0",
|
||||
// date: "2024-07-17",
|
||||
// },
|
||||
// {
|
||||
// patch: "8.0.0",
|
||||
// date: "2024-05-31",
|
||||
// },
|
||||
// {
|
||||
// patch: "7.2.0",
|
||||
// date: "2024-04-17",
|
||||
// },
|
||||
// {
|
||||
// patch: "7.0.0",
|
||||
// date: "2024-02-21",
|
||||
// },
|
||||
// {
|
||||
// patch: "6.1.0",
|
||||
// date: "2024-01-24",
|
||||
// },
|
||||
// {
|
||||
// patch: "6.0.0",
|
||||
// date: "2023-11-29",
|
||||
// },
|
||||
// {
|
||||
// patch: "5.1.0",
|
||||
// date: "2023-10-17",
|
||||
// },
|
||||
// {
|
||||
// patch: "5.0.0",
|
||||
// date: "2023-08-30",
|
||||
// },
|
||||
];
|
||||
|
||||
export const BUILD = {
|
||||
TITLE_MIN_LENGTH: 1,
|
||||
TITLE_MAX_LENGTH: 50,
|
||||
DESCRIPTION_MAX_LENGTH: 280,
|
||||
MAX_WEAPONS_COUNT: 5,
|
||||
MAX_COUNT: 250,
|
||||
} as const;
|
||||
|
||||
export const BUILDS_PAGE_BATCH_SIZE = 24;
|
||||
export const BUILDS_PAGE_MAX_BUILDS = 240;
|
||||
|
||||
export const EMPTY_BUILD: BuildAbilitiesTupleWithUnknown = [
|
||||
["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"],
|
||||
["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"],
|
||||
["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import { Ability } from "~/components/Ability";
|
|||
import { Button } from "~/components/Button";
|
||||
import { ModeImage } from "~/components/Image";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { PATCHES } from "~/constants";
|
||||
import { possibleApValues } from "~/features/build-analyzer";
|
||||
import { abilities } from "~/modules/in-game-lists/abilities";
|
||||
import { modesShort } from "~/modules/in-game-lists/modes";
|
||||
import type { ModeShort } from "~/modules/in-game-lists/types";
|
||||
import type { Ability as AbilityType } from "~/modules/in-game-lists/types";
|
||||
import { dateToYYYYMMDD } from "~/utils/dates";
|
||||
import { PATCHES } from "../builds-constants";
|
||||
import type {
|
||||
AbilityBuildFilter,
|
||||
BuildFilter,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { BUILDS_PAGE_MAX_BUILDS } from "~/constants";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
||||
import { cache, syncCached } from "~/utils/cache.server";
|
||||
import { BUILDS_PAGE_MAX_BUILDS } from "../builds-constants";
|
||||
import { buildsByWeaponId } from "../queries/buildsBy.server";
|
||||
|
||||
const buildsCacheKey = (weaponSplId: MainWeaponId) => `builds-${weaponSplId}`;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { BUILDS_PAGE_BATCH_SIZE, BUILDS_PAGE_MAX_BUILDS } from "~/constants";
|
||||
import { i18next } from "~/modules/i18n/i18next.server";
|
||||
import { weaponIdIsNotAlt } from "~/modules/in-game-lists/weapon-ids";
|
||||
import { weaponNameSlugToId } from "~/utils/unslugify.server";
|
||||
import { mySlugify } from "~/utils/urls";
|
||||
import { FILTER_SEARCH_PARAM_KEY } from "../builds-constants";
|
||||
import {
|
||||
BUILDS_PAGE_BATCH_SIZE,
|
||||
BUILDS_PAGE_MAX_BUILDS,
|
||||
FILTER_SEARCH_PARAM_KEY,
|
||||
} from "../builds-constants";
|
||||
import { buildFiltersSearchParams } from "../builds-schemas.server";
|
||||
import { cachedBuildsByWeaponId } from "../core/cached-builds.server";
|
||||
import { filterBuilds } from "../core/filter.server";
|
||||
|
|
|
|||
|
|
@ -18,11 +18,6 @@ import { ChartBarIcon } from "~/components/icons/ChartBar";
|
|||
import { FilterIcon } from "~/components/icons/Filter";
|
||||
import { FireIcon } from "~/components/icons/Fire";
|
||||
import { MapIcon } from "~/components/icons/Map";
|
||||
import {
|
||||
BUILDS_PAGE_BATCH_SIZE,
|
||||
BUILDS_PAGE_MAX_BUILDS,
|
||||
PATCHES,
|
||||
} from "~/constants";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { safeJSONParse } from "~/utils/json";
|
||||
import { isRevalidation, metaTags } from "~/utils/remix";
|
||||
|
|
@ -37,8 +32,11 @@ import {
|
|||
weaponBuildStatsPage,
|
||||
} from "~/utils/urls";
|
||||
import {
|
||||
BUILDS_PAGE_BATCH_SIZE,
|
||||
BUILDS_PAGE_MAX_BUILDS,
|
||||
FILTER_SEARCH_PARAM_KEY,
|
||||
MAX_BUILD_FILTERS,
|
||||
PATCHES,
|
||||
} from "../builds-constants";
|
||||
import type { BuildFiltersFromSearchParams } from "../builds-schemas.server";
|
||||
import type { AbilityBuildFilter, BuildFilter } from "../builds-types";
|
||||
|
|
|
|||
|
|
@ -103,3 +103,11 @@ export const EXCLUDED_TAGS: Array<CalendarEventTag> = [
|
|||
"SZ",
|
||||
"TW",
|
||||
];
|
||||
|
||||
export const CALENDAR_EVENT_RESULT = {
|
||||
MAX_PARTICIPANTS_COUNT: 1000,
|
||||
MAX_PLAYERS_LENGTH: 8,
|
||||
MAX_TEAM_NAME_LENGTH: 100,
|
||||
MAX_TEAM_PLACEMENT: 256,
|
||||
MAX_PLAYER_NAME_LENGTH: 100,
|
||||
} as const;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { z } from "zod";
|
||||
import { CALENDAR_EVENT_RESULT } from "~/constants";
|
||||
import { type CalendarEventTag, TOURNAMENT_STAGE_TYPES } from "~/db/tables";
|
||||
import * as Progression from "~/features/tournament-bracket/core/Progression";
|
||||
import { TOURNAMENT } from "~/features/tournament/tournament-constants";
|
||||
|
|
@ -14,7 +13,7 @@ import {
|
|||
safeJSONParse,
|
||||
toArray,
|
||||
} from "~/utils/zod";
|
||||
import { CALENDAR_EVENT } from "./calendar-constants";
|
||||
import { CALENDAR_EVENT, CALENDAR_EVENT_RESULT } from "./calendar-constants";
|
||||
import * as CalendarEvent from "./core/CalendarEvent";
|
||||
|
||||
export const calendarEventTagSchema = z
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import { FormMessage } from "~/components/FormMessage";
|
|||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import { CALENDAR_EVENT_RESULT } from "~/constants";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
import { CALENDAR_EVENT_RESULT } from "../calendar-constants";
|
||||
|
||||
import { action } from "../actions/calendar.$id.report-winners.server";
|
||||
import { loader } from "../loaders/calendar.$id.report-winners.server";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { nanoid } from "nanoid";
|
||||
import { SKALOP_TOKEN_HEADER_NAME } from "~/constants";
|
||||
import invariant from "~/utils/invariant";
|
||||
import type { ChatMessage } from "./chat-types";
|
||||
|
||||
const SKALOP_TOKEN_HEADER_NAME = "Skalop-Token";
|
||||
|
||||
type PartialChatMessage = Pick<
|
||||
ChatMessage,
|
||||
"type" | "context" | "room" | "revalidateOnly"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import cachified from "@epic-web/cachified";
|
||||
import { TWO_HOURS_IN_MS } from "~/constants";
|
||||
import type { ShowcaseCalendarEvent } from "~/features/calendar/calendar-types";
|
||||
import * as TournamentRepository from "~/features/tournament/TournamentRepository.server";
|
||||
import { tournamentIsRanked } from "~/features/tournament/tournament-utils";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { IN_MILLISECONDS, cache, ttl } from "~/utils/cache.server";
|
||||
import {
|
||||
databaseTimestampToDate,
|
||||
dateToDatabaseTimestamp,
|
||||
|
|
@ -161,7 +160,7 @@ async function cachedTournaments() {
|
|||
return cachified({
|
||||
key: SHOWCASE_TOURNAMENTS_CACHE_KEY,
|
||||
cache,
|
||||
ttl: ttl(TWO_HOURS_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.TWO_HOURS),
|
||||
async getFreshValue() {
|
||||
const tournaments = await TournamentRepository.forShowcase();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import cachified from "@epic-web/cachified";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { ONE_HOUR_IN_MS, TWO_HOURS_IN_MS } from "~/constants";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { getUserId } from "~/features/auth/core/user.server";
|
||||
import * as Changelog from "~/features/front-page/core/Changelog.server";
|
||||
import * as LeaderboardRepository from "~/features/leaderboards/LeaderboardRepository.server";
|
||||
import { cachedFullUserLeaderboard } from "~/features/leaderboards/core/leaderboards.server";
|
||||
import * as Seasons from "~/features/mmr/core/Seasons";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { IN_MILLISECONDS, cache, ttl } from "~/utils/cache.server";
|
||||
import {
|
||||
discordAvatarUrl,
|
||||
teamPage,
|
||||
|
|
@ -24,8 +23,8 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|||
cachified({
|
||||
key: "front-changelog",
|
||||
cache,
|
||||
ttl: ttl(ONE_HOUR_IN_MS),
|
||||
staleWhileRevalidate: ttl(TWO_HOURS_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.ONE_HOUR),
|
||||
staleWhileRevalidate: ttl(IN_MILLISECONDS.TWO_HOURS),
|
||||
async getFreshValue() {
|
||||
return Changelog.get();
|
||||
},
|
||||
|
|
@ -56,8 +55,8 @@ function cachedLeaderboards(): Promise<{
|
|||
return cachified({
|
||||
key: "front-leaderboard",
|
||||
cache,
|
||||
ttl: ttl(ONE_HOUR_IN_MS),
|
||||
staleWhileRevalidate: ttl(TWO_HOURS_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.ONE_HOUR),
|
||||
staleWhileRevalidate: ttl(IN_MILLISECONDS.TWO_HOURS),
|
||||
async getFreshValue() {
|
||||
const season = Seasons.currentOrPrevious()?.nth ?? 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { cachified } from "@epic-web/cachified";
|
||||
import { HALF_HOUR_IN_MS } from "~/constants";
|
||||
import * as Seasons from "~/features/mmr/core/Seasons";
|
||||
import { USER_LEADERBOARD_MIN_ENTRIES_FOR_LEVIATHAN } from "~/features/mmr/mmr-constants";
|
||||
import { spToOrdinal } from "~/features/mmr/mmr-utils";
|
||||
|
|
@ -7,7 +6,7 @@ import { freshUserSkills, userSkills } from "~/features/mmr/tiered.server";
|
|||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
||||
import { weaponCategories } from "~/modules/in-game-lists/weapon-ids";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { IN_MILLISECONDS, cache, ttl } from "~/utils/cache.server";
|
||||
import type { Unwrapped } from "~/utils/types";
|
||||
import { DEFAULT_LEADERBOARD_MAX_SIZE } from "../leaderboards-constants";
|
||||
import { seasonHasTopTen } from "../leaderboards-utils";
|
||||
|
|
@ -23,7 +22,7 @@ export async function cachedFullUserLeaderboard(season: number) {
|
|||
return cachified({
|
||||
key: `user-leaderboard-season-${season}`,
|
||||
cache,
|
||||
ttl: ttl(HALF_HOUR_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.HALF_HOUR),
|
||||
async getFreshValue() {
|
||||
const leaderboard = userSPLeaderboard(season);
|
||||
const withTiers = addTiers(leaderboard, season);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { cachified } from "@epic-web/cachified";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { HALF_HOUR_IN_MS } from "~/constants";
|
||||
import { getUser } from "~/features/auth/core/user.server";
|
||||
import * as LeaderboardRepository from "~/features/leaderboards/LeaderboardRepository.server";
|
||||
import * as Seasons from "~/features/mmr/core/Seasons";
|
||||
|
|
@ -9,7 +8,7 @@ import type {
|
|||
RankedModeShort,
|
||||
} from "~/modules/in-game-lists/types";
|
||||
import type { weaponCategories } from "~/modules/in-game-lists/weapon-ids";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { IN_MILLISECONDS, cache, ttl } from "~/utils/cache.server";
|
||||
import {
|
||||
cachedFullUserLeaderboard,
|
||||
filterByWeaponCategory,
|
||||
|
|
@ -59,7 +58,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|||
? await cachified({
|
||||
key: `team-leaderboard-season-${season}-${type}`,
|
||||
cache,
|
||||
ttl: ttl(HALF_HOUR_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.HALF_HOUR),
|
||||
async getFreshValue() {
|
||||
return LeaderboardRepository.teamLeaderboardBySeason({
|
||||
season,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
export const PLUS_SUGGESTION = {
|
||||
FIRST_COMMENT_MAX_LENGTH: 500,
|
||||
COMMENT_MAX_LENGTH: 280,
|
||||
};
|
||||
|
||||
export const PLUS_TIERS = [1, 2, 3];
|
||||
|
|
@ -1,15 +1,11 @@
|
|||
import { z } from "zod";
|
||||
import {
|
||||
PLUS_TIERS,
|
||||
PlUS_SUGGESTION_COMMENT_MAX_LENGTH,
|
||||
PlUS_SUGGESTION_FIRST_COMMENT_MAX_LENGTH,
|
||||
} from "~/constants";
|
||||
import { _action, actualNumber, trimmedString } from "~/utils/zod";
|
||||
import { PLUS_SUGGESTION, PLUS_TIERS } from "./plus-suggestions-constants";
|
||||
|
||||
export const followUpCommentActionSchema = z.object({
|
||||
comment: z.preprocess(
|
||||
trimmedString,
|
||||
z.string().min(1).max(PlUS_SUGGESTION_COMMENT_MAX_LENGTH),
|
||||
z.string().min(1).max(PLUS_SUGGESTION.COMMENT_MAX_LENGTH),
|
||||
),
|
||||
tier: z.preprocess(
|
||||
actualNumber,
|
||||
|
|
@ -31,7 +27,7 @@ export const firstCommentActionSchema = z.object({
|
|||
),
|
||||
comment: z.preprocess(
|
||||
trimmedString,
|
||||
z.string().min(1).max(PlUS_SUGGESTION_FIRST_COMMENT_MAX_LENGTH),
|
||||
z.string().min(1).max(PLUS_SUGGESTION.FIRST_COMMENT_MAX_LENGTH),
|
||||
),
|
||||
userId: z.preprocess(actualNumber, z.number().positive()),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { Form, useMatches, useParams } from "@remix-run/react";
|
|||
import { Button } from "~/components/Button";
|
||||
import { Redirect } from "~/components/Redirect";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { PlUS_SUGGESTION_COMMENT_MAX_LENGTH } from "~/constants";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { atOrError } from "~/utils/arrays";
|
||||
import { plusSuggestionPage } from "~/utils/urls";
|
||||
import { PLUS_SUGGESTION } from "../plus-suggestions-constants";
|
||||
import { canAddCommentToSuggestionFE } from "../plus-suggestions-utils";
|
||||
import type { PlusSuggestionsLoaderData } from "./plus.suggestions";
|
||||
import { CommentTextarea } from "./plus.suggestions.new";
|
||||
|
|
@ -49,7 +49,7 @@ export default function PlusCommentModalPage() {
|
|||
<Form method="post" className="stack md">
|
||||
<input type="hidden" name="tier" value={tierSuggestedTo} />
|
||||
<input type="hidden" name="suggestedId" value={targetUserId} />
|
||||
<CommentTextarea maxLength={PlUS_SUGGESTION_COMMENT_MAX_LENGTH} />
|
||||
<CommentTextarea maxLength={PLUS_SUGGESTION.COMMENT_MAX_LENGTH} />
|
||||
<div>
|
||||
<Button type="submit">Submit</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,13 +5,10 @@ import { Redirect } from "~/components/Redirect";
|
|||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import {
|
||||
PLUS_TIERS,
|
||||
PlUS_SUGGESTION_FIRST_COMMENT_MAX_LENGTH,
|
||||
} from "~/constants";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { atOrError } from "~/utils/arrays";
|
||||
import { plusSuggestionPage } from "~/utils/urls";
|
||||
import { PLUS_SUGGESTION, PLUS_TIERS } from "../plus-suggestions-constants";
|
||||
import { canSuggestNewUser } from "../plus-suggestions-utils";
|
||||
import type { PlusSuggestionsLoaderData } from "./plus.suggestions";
|
||||
|
||||
|
|
@ -67,7 +64,7 @@ export default function PlusNewSuggestionModalPage() {
|
|||
</select>
|
||||
</div>
|
||||
<UserSearch name="userId" label="Suggested user" isRequired />
|
||||
<CommentTextarea maxLength={PlUS_SUGGESTION_FIRST_COMMENT_MAX_LENGTH} />
|
||||
<CommentTextarea maxLength={PLUS_SUGGESTION.FIRST_COMMENT_MAX_LENGTH} />
|
||||
<div>
|
||||
<SubmitButton>Submit</SubmitButton>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type { ActionFunction } from "@remix-run/node";
|
||||
import { PLUS_UPVOTE } from "~/constants";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server";
|
||||
import type { PlusVoteFromFE } from "~/features/plus-voting/core";
|
||||
|
|
@ -11,6 +10,7 @@ import { isVotingActive } from "~/features/plus-voting/core/voting-time";
|
|||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { badRequestIfFalsy, parseRequestPayload } from "~/utils/remix.server";
|
||||
import { PLUS_UPVOTE } from "../plus-voting-constants";
|
||||
import { votingActionSchema } from "../plus-voting-schemas";
|
||||
|
||||
export const action: ActionFunction = async ({ request }) => {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as React from "react";
|
||||
import { PLUS_DOWNVOTE, PLUS_UPVOTE } from "~/constants";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { PLUS_DOWNVOTE, PLUS_UPVOTE } from "../plus-voting-constants";
|
||||
import type { PlusVoteFromFE } from "./types";
|
||||
import { nextNonCompletedVoting, rangeToMonthYear } from "./voting-time";
|
||||
|
||||
|
|
|
|||
2
app/features/plus-voting/plus-voting-constants.ts
Normal file
2
app/features/plus-voting/plus-voting-constants.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export const PLUS_UPVOTE = 1;
|
||||
export const PLUS_DOWNVOTE = -1;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { z } from "zod";
|
||||
import { PLUS_DOWNVOTE, PLUS_UPVOTE } from "~/constants";
|
||||
import type { PlusVoteFromFE } from "~/features/plus-voting/core";
|
||||
import { assertType } from "~/utils/types";
|
||||
import { safeJSONParse } from "~/utils/zod";
|
||||
import { PLUS_DOWNVOTE, PLUS_UPVOTE } from "./plus-voting-constants";
|
||||
|
||||
export const voteSchema = z.object({
|
||||
votedId: z.number(),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import { sub } from "date-fns";
|
||||
import type { Insertable } from "kysely";
|
||||
import { jsonArrayFrom, jsonBuildObject } from "kysely/helpers/sqlite";
|
||||
import { nanoid } from "nanoid";
|
||||
import type { Tables, TablesInsertable } from "~/db/tables";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { INVITE_CODE_LENGTH } from "../../constants";
|
||||
import { db } from "../../db/sql";
|
||||
import invariant from "../../utils/invariant";
|
||||
import type { Unwrapped } from "../../utils/types";
|
||||
|
|
@ -38,7 +37,7 @@ export function insert(args: InsertArgs) {
|
|||
teamId: args.teamId,
|
||||
text: args.text,
|
||||
visibility: args.visibility ? JSON.stringify(args.visibility) : null,
|
||||
chatCode: nanoid(INVITE_CODE_LENGTH),
|
||||
chatCode: shortNanoid(),
|
||||
})
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import cachified from "@epic-web/cachified";
|
||||
import { HALF_HOUR_IN_MS } from "~/constants";
|
||||
import {
|
||||
type UserLeaderboardWithAdditionsItem,
|
||||
cachedFullUserLeaderboard,
|
||||
|
|
@ -9,7 +8,7 @@ import { TIERS } from "~/features/mmr/mmr-constants";
|
|||
import * as QStreamsRepository from "~/features/sendouq-streams/QStreamsRepository.server";
|
||||
import { getStreams } from "~/modules/twitch";
|
||||
import type { MappedStream } from "~/modules/twitch/streams";
|
||||
import { cache, ttl } from "~/utils/cache.server";
|
||||
import { IN_MILLISECONDS, cache, ttl } from "~/utils/cache.server";
|
||||
import { SENDOUQ_STREAMS_KEY } from "../q-streams-constants";
|
||||
|
||||
export function cachedStreams() {
|
||||
|
|
@ -18,7 +17,7 @@ export function cachedStreams() {
|
|||
return cachified({
|
||||
key: SENDOUQ_STREAMS_KEY,
|
||||
cache: cache,
|
||||
ttl: ttl(HALF_HOUR_IN_MS),
|
||||
ttl: ttl(IN_MILLISECONDS.HALF_HOUR),
|
||||
async getFreshValue() {
|
||||
return streamedMatches({
|
||||
matchPlayers: await QStreamsRepository.activeMatchPlayers(),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { sub } from "date-fns";
|
||||
import { sql } from "kysely";
|
||||
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
||||
import { nanoid } from "nanoid";
|
||||
import { INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { db } from "~/db/sql";
|
||||
import type {
|
||||
Tables,
|
||||
|
|
@ -10,6 +8,7 @@ import type {
|
|||
UserMapModePreferences,
|
||||
} from "~/db/tables";
|
||||
import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { userIsBanned } from "../ban/core/banned.server";
|
||||
import type { LookingGroupWithInviteCode } from "./q-types";
|
||||
|
|
@ -165,8 +164,8 @@ export function createGroup(args: CreateGroupArgs) {
|
|||
const createdGroup = await trx
|
||||
.insertInto("Group")
|
||||
.values({
|
||||
inviteCode: nanoid(INVITE_CODE_LENGTH),
|
||||
chatCode: nanoid(INVITE_CODE_LENGTH),
|
||||
inviteCode: shortNanoid(),
|
||||
chatCode: shortNanoid(),
|
||||
status: args.status,
|
||||
})
|
||||
.returning("id")
|
||||
|
|
@ -205,7 +204,7 @@ export async function createGroupFromPrevious(
|
|||
.select((eb) => [
|
||||
"Group.teamId",
|
||||
"Group.chatCode",
|
||||
eb.val(nanoid(INVITE_CODE_LENGTH)).as("inviteCode"),
|
||||
eb.val(shortNanoid()).as("inviteCode"),
|
||||
eb.val("PREPARING").as("status"),
|
||||
])
|
||||
.where("Group.id", "=", args.previousGroupId),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { TWEET_LENGTH_MAX_LENGTH } from "~/constants";
|
||||
|
||||
export const SENDOUQ = {
|
||||
SZ_MAP_COUNT: 6,
|
||||
OTHER_MODE_MAP_COUNT: 3,
|
||||
MAX_STAGE_REPEAT_COUNT: 2,
|
||||
OWN_PUBLIC_NOTE_MAX_LENGTH: TWEET_LENGTH_MAX_LENGTH / 2,
|
||||
PRIVATE_USER_NOTE_MAX_LENGTH: TWEET_LENGTH_MAX_LENGTH,
|
||||
OWN_PUBLIC_NOTE_MAX_LENGTH: 160,
|
||||
PRIVATE_USER_NOTE_MAX_LENGTH: 280,
|
||||
} as const;
|
||||
|
||||
export const FRIEND_CODE_REGEXP_PATTERN =
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import type { Insertable, Transaction } from "kysely";
|
||||
import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
||||
import { nanoid } from "nanoid";
|
||||
import { INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { db } from "~/db/sql";
|
||||
import type { DB, Tables } from "~/db/tables";
|
||||
import * as LFGRepository from "~/features/lfg/LFGRepository.server";
|
||||
import { databaseTimestampNow } from "~/utils/dates";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
|
||||
|
|
@ -139,7 +138,7 @@ export async function create(
|
|||
.values({
|
||||
name: args.name,
|
||||
customUrl: args.customUrl,
|
||||
inviteCode: nanoid(INVITE_CODE_LENGTH),
|
||||
inviteCode: shortNanoid(),
|
||||
})
|
||||
.returning("id")
|
||||
.executeTakeFirstOrThrow();
|
||||
|
|
@ -294,7 +293,7 @@ export function resetInviteCode(teamId: number) {
|
|||
return db
|
||||
.updateTable("AllTeam")
|
||||
.set({
|
||||
inviteCode: nanoid(INVITE_CODE_LENGTH),
|
||||
inviteCode: shortNanoid(),
|
||||
})
|
||||
.where("id", "=", teamId)
|
||||
.execute();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import { INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import { SHORT_NANOID_LENGTH } from "~/utils/id";
|
||||
import { notFoundIfFalsy } from "~/utils/remix.server";
|
||||
import { teamPage } from "~/utils/urls";
|
||||
import * as TeamRepository from "../TeamRepository.server";
|
||||
|
|
@ -58,7 +58,7 @@ export function validateInviteCode({
|
|||
user?: { id: number; team?: { name: string } };
|
||||
reachedTeamCountLimit: boolean;
|
||||
}) {
|
||||
if (inviteCode.length !== INVITE_CODE_LENGTH) {
|
||||
if (inviteCode.length !== SHORT_NANOID_LENGTH) {
|
||||
return "SHORT_CODE";
|
||||
}
|
||||
if (inviteCode !== realInviteCode) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { TWEET_LENGTH_MAX_LENGTH } from "~/constants";
|
||||
|
||||
export const TOURNAMENT_SUB = {
|
||||
WEAPON_POOL_MAX_SIZE: 5,
|
||||
MESSAGE_MAX_LENGTH: TWEET_LENGTH_MAX_LENGTH,
|
||||
MESSAGE_MAX_LENGTH: 280,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
import type { Transaction } from "kysely";
|
||||
import { sql } from "kysely";
|
||||
import { nanoid } from "nanoid";
|
||||
import { INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { db } from "~/db/sql";
|
||||
import type { DB, Tables } from "~/db/tables";
|
||||
import { databaseTimestampNow } from "~/utils/dates";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import invariant from "~/utils/invariant";
|
||||
|
||||
export function setActiveRoster({
|
||||
|
|
@ -133,7 +132,7 @@ export function create({
|
|||
.values({
|
||||
tournamentId,
|
||||
name: team.name,
|
||||
inviteCode: nanoid(INVITE_CODE_LENGTH),
|
||||
inviteCode: shortNanoid(),
|
||||
prefersNotToHost: team.prefersNotToHost,
|
||||
noScreen: team.noScreen,
|
||||
teamId: team.teamId,
|
||||
|
|
@ -215,7 +214,7 @@ export function copyFromAnotherTournament({
|
|||
.values({
|
||||
...oldTeam,
|
||||
tournamentId: destinationTournamentId,
|
||||
inviteCode: nanoid(INVITE_CODE_LENGTH),
|
||||
inviteCode: shortNanoid(),
|
||||
seed,
|
||||
})
|
||||
.returning("id")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
tournamentFromDB,
|
||||
} from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import * as TournamentTeamRepository from "~/features/tournament/TournamentTeamRepository.server";
|
||||
import { USER } from "~/features/user-page/user-page-constants";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { logger } from "~/utils/logger";
|
||||
import {
|
||||
|
|
@ -21,7 +22,6 @@ import {
|
|||
successToast,
|
||||
} from "~/utils/remix.server";
|
||||
import { assertUnreachable } from "~/utils/types";
|
||||
import { USER } from "../../../constants";
|
||||
import { _action, id, idObject } from "../../../utils/zod";
|
||||
import { bracketIdx } from "../../tournament-bracket/tournament-bracket-schemas.server";
|
||||
import * as TournamentRepository from "../TournamentRepository.server";
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ import { SubmitButton } from "~/components/SubmitButton";
|
|||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import { USER } from "~/constants";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import * as Progression from "~/features/tournament-bracket/core/Progression";
|
||||
import type { TournamentData } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import { USER } from "~/features/user-page/user-page-constants";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { assertUnreachable } from "~/utils/types";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as R from "remeda";
|
||||
import { INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { modesShort, rankedModesShort } from "~/modules/in-game-lists/modes";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists/types";
|
||||
import { weekNumberToDate } from "~/utils/dates";
|
||||
import { SHORT_NANOID_LENGTH } from "~/utils/id";
|
||||
import { tournamentLogoUrl } from "~/utils/urls";
|
||||
import type { Tables, TournamentStageSettings } from "../../db/tables";
|
||||
import { assertUnreachable } from "../../utils/types";
|
||||
|
|
@ -369,7 +369,7 @@ export function validateCanJoinTeam({
|
|||
if (typeof userId !== "number") {
|
||||
return "NOT_LOGGED_IN";
|
||||
}
|
||||
if (!teamToJoin && inviteCode.length !== INVITE_CODE_LENGTH) {
|
||||
if (!teamToJoin && inviteCode.length !== SHORT_NANOID_LENGTH) {
|
||||
return "SHORT_CODE";
|
||||
}
|
||||
if (!teamToJoin) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { type ActionFunction, redirect } from "@remix-run/node";
|
||||
import * as R from "remeda";
|
||||
import { z } from "zod";
|
||||
import { BUILD } from "~/constants";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import * as BuildRepository from "~/features/builds/BuildRepository.server";
|
||||
import { BUILD } from "~/features/builds/builds-constants";
|
||||
import { refreshBuildsCacheByWeaponSplIds } from "~/features/builds/core/cached-builds.server";
|
||||
import type { BuildWeaponWithTop500Info } from "~/features/builds/queries/buildsBy.server";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import { RequiredHiddenInput } from "~/components/RequiredHiddenInput";
|
|||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { PlusIcon } from "~/components/icons/Plus";
|
||||
import { BUILD } from "~/constants";
|
||||
import type { GearType } from "~/db/tables";
|
||||
import {
|
||||
validatedBuildFromSearchParams,
|
||||
|
|
@ -35,6 +34,7 @@ import type { SendouRouteHandle } from "~/utils/remix.server";
|
|||
import { modeImageUrl } from "~/utils/urls";
|
||||
import type { UserPageLoaderData } from "../loaders/u.$identifier.server";
|
||||
|
||||
import { BUILD } from "~/features/builds/builds-constants";
|
||||
import { action } from "../actions/u.$identifier.builds.new.server";
|
||||
import { loader } from "../loaders/u.$identifier.builds.new.server";
|
||||
export { loader, action };
|
||||
|
|
|
|||
|
|
@ -15,9 +15,8 @@ import { SendouSwitch } from "~/components/elements/Switch";
|
|||
import { StarIcon } from "~/components/icons/Star";
|
||||
import { StarFilledIcon } from "~/components/icons/StarFilled";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import { USER } from "~/constants";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import { BADGE } from "~/features/badges/badges-contants";
|
||||
import { BADGE } from "~/features/badges/badges-constants";
|
||||
import { BadgesSelector } from "~/features/badges/components/BadgesSelector";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
||||
|
|
@ -26,7 +25,7 @@ import invariant from "~/utils/invariant";
|
|||
import { rawSensToString } from "~/utils/strings";
|
||||
import { FAQ_PAGE } from "~/utils/urls";
|
||||
import type { UserPageLoaderData } from "../loaders/u.$identifier.server";
|
||||
import { COUNTRY_CODES } from "../user-page-constants";
|
||||
import { COUNTRY_CODES, USER } from "../user-page-constants";
|
||||
|
||||
import { action } from "../actions/u.$identifier.edit.server";
|
||||
import { loader } from "../loaders/u.$identifier.edit.server";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,29 @@
|
|||
export const USER = {
|
||||
BIO_MAX_LENGTH: 2000,
|
||||
CUSTOM_URL_MAX_LENGTH: 32,
|
||||
CUSTOM_NAME_MAX_LENGTH: 32,
|
||||
BATTLEFY_MAX_LENGTH: 32,
|
||||
IN_GAME_NAME_TEXT_MAX_LENGTH: 20,
|
||||
IN_GAME_NAME_DISCRIMINATOR_MAX_LENGTH: 5,
|
||||
WEAPON_POOL_MAX_SIZE: 5,
|
||||
COMMISSION_TEXT_MAX_LENGTH: 1000,
|
||||
};
|
||||
|
||||
export const MATCHES_PER_SEASONS_PAGE = 8;
|
||||
export const DEFAULT_BUILD_SORT = ["WEAPON_POOL", "UPDATED_AT"] as const;
|
||||
|
||||
export const CUSTOM_CSS_VAR_COLORS = [
|
||||
"bg",
|
||||
"bg-darker",
|
||||
"bg-lighter",
|
||||
"bg-lightest",
|
||||
"text",
|
||||
"text-lighter",
|
||||
"theme",
|
||||
"theme-secondary",
|
||||
"chat",
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* An array of ISO 3166-1 alpha-2 country codes.
|
||||
* Each entry is a two-letter uppercase string representing a country or territory. Sorted alphabetically.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { z } from "zod";
|
||||
import { USER } from "~/constants";
|
||||
import "~/styles/u-edit.css";
|
||||
import { BADGE } from "~/features/badges/badges-contants";
|
||||
import { BADGE } from "~/features/badges/badges-constants";
|
||||
import { isCustomUrl } from "~/utils/urls";
|
||||
import {
|
||||
actualNumber,
|
||||
|
|
@ -22,7 +21,7 @@ import {
|
|||
HIGHLIGHT_CHECKBOX_NAME,
|
||||
HIGHLIGHT_TOURNAMENT_CHECKBOX_NAME,
|
||||
} from "./components/UserResultsTable";
|
||||
import { COUNTRY_CODES } from "./user-page-constants";
|
||||
import { COUNTRY_CODES, USER } from "./user-page-constants";
|
||||
|
||||
export const userParamsSchema = z.object({ identifier: z.string() });
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { z } from "zod";
|
||||
import { STAFF_DISCORD_IDS } from "~/constants";
|
||||
import { STAFF_DISCORD_IDS } from "~/features/admin/admin-constants";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { fetchWithTimeout } from "~/utils/fetch";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ADMIN_ID, STAFF_IDS } from "~/constants";
|
||||
import { ADMIN_ID, STAFF_IDS } from "~/features/admin/admin-constants";
|
||||
|
||||
export function isAdmin(user?: { id: number }) {
|
||||
return user?.id === ADMIN_ID;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ import { Catcher } from "./components/Catcher";
|
|||
import { SendouToastRegion, toastQueue } from "./components/elements/Toast";
|
||||
import { Layout } from "./components/layout";
|
||||
import { Ramp } from "./components/ramp/Ramp";
|
||||
import { CUSTOMIZED_CSS_VARS_NAME } from "./constants";
|
||||
import { getUser } from "./features/auth/core/user.server";
|
||||
import { userIsBanned } from "./features/ban/core/banned.server";
|
||||
import {
|
||||
|
|
@ -280,6 +279,8 @@ function usePreloadTranslation() {
|
|||
}, []);
|
||||
}
|
||||
|
||||
const CUSTOMIZED_CSS_VARS_NAME = "css";
|
||||
|
||||
function useCustomizedCSSVars() {
|
||||
const matches = useMatches();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
|
|||
import type { Params } from "@remix-run/react";
|
||||
import { expect } from "vitest";
|
||||
import type { z } from "zod";
|
||||
import { ADMIN_ID } from "~/constants";
|
||||
import { REGULAR_USER_TEST_ID } from "~/db/seed/constants";
|
||||
import { db, sql } from "~/db/sql";
|
||||
import { ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import { SESSION_KEY } from "~/features/auth/core/authenticator.server";
|
||||
import { authSessionStorage } from "~/features/auth/core/session.server";
|
||||
|
||||
|
|
|
|||
|
|
@ -24,3 +24,9 @@ export function syncCached<T>(key: string, getFreshValue: () => T) {
|
|||
|
||||
return value;
|
||||
}
|
||||
|
||||
export const IN_MILLISECONDS = {
|
||||
HALF_HOUR: 30 * 60 * 1000,
|
||||
ONE_HOUR: 60 * 60 * 1000,
|
||||
TWO_HOURS: 2 * 60 * 60 * 1000,
|
||||
};
|
||||
|
|
|
|||
10
app/utils/id.ts
Normal file
10
app/utils/id.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { nanoid } from "nanoid";
|
||||
|
||||
export const SHORT_NANOID_LENGTH = 10;
|
||||
|
||||
/**
|
||||
* Generates a short, unique identifier string (wraps nanoid using a smaller length than the default).
|
||||
*/
|
||||
export function shortNanoid() {
|
||||
return nanoid(SHORT_NANOID_LENGTH);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { type Locator, type Page, expect } from "@playwright/test";
|
||||
import { ADMIN_ID } from "~/constants";
|
||||
import { ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import type { SeedVariation } from "~/features/api-private/routes/seed";
|
||||
import { tournamentBracketsPage } from "./urls";
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import type { Namespace, TFunction } from "i18next";
|
|||
import { nanoid } from "nanoid";
|
||||
import type { z } from "zod";
|
||||
import type { navItems } from "~/components/layout/nav-items";
|
||||
import { LOHI_TOKEN_HEADER_NAME } from "~/constants";
|
||||
import { s3UploadHandler } from "~/features/img-upload";
|
||||
import invariant from "./invariant";
|
||||
import { logger } from "./logger";
|
||||
|
|
@ -182,6 +181,8 @@ function formDataToObject(formData: FormData) {
|
|||
return result;
|
||||
}
|
||||
|
||||
const LOHI_TOKEN_HEADER_NAME = "Lohi-Token";
|
||||
|
||||
/** Some endpoints can only be accessed with an auth token. Used by Lohi bot and cron jobs. */
|
||||
export function canAccessLohiEndpoint(request: Request) {
|
||||
invariant(process.env.LOHI_TOKEN, "LOHI_TOKEN is required");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ZodType } from "zod";
|
||||
import { z } from "zod";
|
||||
import { CUSTOM_CSS_VAR_COLORS, INVITE_CODE_LENGTH } from "~/constants";
|
||||
import { CUSTOM_CSS_VAR_COLORS } from "~/features/user-page/user-page-constants";
|
||||
import {
|
||||
abilities,
|
||||
type abilitiesShort,
|
||||
|
|
@ -8,6 +8,7 @@ import {
|
|||
import { stageIds } from "~/modules/in-game-lists/stage-ids";
|
||||
import { mainWeaponIds } from "~/modules/in-game-lists/weapon-ids";
|
||||
import { FRIEND_CODE_REGEXP } from "../features/sendouq/q-constants";
|
||||
import { SHORT_NANOID_LENGTH } from "./id";
|
||||
import type { Unpacked } from "./types";
|
||||
import { assertType } from "./types";
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ export const idObject = z.object({
|
|||
});
|
||||
export const optionalId = z.coerce.number().int().positive().optional();
|
||||
|
||||
export const inviteCode = z.string().length(INVITE_CODE_LENGTH);
|
||||
export const inviteCode = z.string().length(SHORT_NANOID_LENGTH);
|
||||
export const inviteCodeObject = z.object({
|
||||
inviteCode,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import test, { expect } from "@playwright/test";
|
||||
import { ADMIN_ID } from "~/constants";
|
||||
import { NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import {
|
||||
impersonate,
|
||||
isNotVisible,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { ADMIN_DISCORD_ID } from "~/constants";
|
||||
import { NZAP_TEST_DISCORD_ID, NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { ADMIN_DISCORD_ID } from "~/features/admin/admin-constants";
|
||||
import {
|
||||
impersonate,
|
||||
navigate,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import test, { expect } from "@playwright/test";
|
||||
import { ADMIN_ID } from "~/constants";
|
||||
import { ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import {
|
||||
impersonate,
|
||||
navigate,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { ADMIN_DISCORD_ID, ADMIN_ID } from "~/constants";
|
||||
import { NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { ADMIN_DISCORD_ID, ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import {
|
||||
impersonate,
|
||||
isNotVisible,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { type Page, expect, test } from "@playwright/test";
|
||||
import { ADMIN_DISCORD_ID } from "~/constants";
|
||||
import { NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { ADMIN_DISCORD_ID } from "~/features/admin/admin-constants";
|
||||
import {
|
||||
impersonate,
|
||||
isNotVisible,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import test, { expect } from "@playwright/test";
|
||||
import { ADMIN_ID } from "~/constants";
|
||||
import { NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import {
|
||||
impersonate,
|
||||
isNotVisible,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { ADMIN_ID } from "~/constants";
|
||||
import { NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import { BANNED_MAPS } from "~/features/sendouq-settings/banned-maps";
|
||||
import type { TournamentLoaderData } from "~/features/tournament/loaders/to.$id.server";
|
||||
import { rankedModesShort } from "~/modules/in-game-lists/modes";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { type Page, expect, test } from "@playwright/test";
|
||||
import { ADMIN_DISCORD_ID } from "~/constants";
|
||||
import { NZAP_TEST_DISCORD_ID, NZAP_TEST_ID } from "~/db/seed/constants";
|
||||
import { ADMIN_DISCORD_ID } from "~/features/admin/admin-constants";
|
||||
import {
|
||||
impersonate,
|
||||
isNotVisible,
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import "dotenv/config";
|
||||
import { z } from "zod";
|
||||
import { ADMIN_ID } from "~/constants";
|
||||
import { db } from "~/db/sql";
|
||||
import { ADMIN_ID } from "~/features/admin/admin-constants";
|
||||
import * as CalendarRepository from "~/features/calendar/CalendarRepository.server";
|
||||
import type { Tournament } from "~/features/tournament-bracket/core/Tournament";
|
||||
import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user