mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-25 07:32:19 -05:00
Remove legacy tournament map list generator
This commit is contained in:
parent
890b73f7a1
commit
89a50ca24f
|
|
@ -451,7 +451,8 @@ export interface Tournament {
|
|||
settings: ColumnType<TournamentSettings, string, string>;
|
||||
id: GeneratedAlways<number>;
|
||||
mapPickingStyle: TournamentMapPickingStyle;
|
||||
showMapListGenerator: Generated<number | null>;
|
||||
// TODO: remove in migration
|
||||
// showMapListGenerator: Generated<number | null>;
|
||||
castTwitchAccounts: ColumnType<string[] | null, string | null, string | null>;
|
||||
castedMatchesInfo: ColumnType<
|
||||
CastedMatchesInfo | null,
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@ export interface Tournament {
|
|||
id: number;
|
||||
mapPickingStyle: TournamentMapPickingStyle;
|
||||
format: TournamentFormat;
|
||||
showMapListGenerator: number;
|
||||
}
|
||||
|
||||
export interface TournamentTeam {
|
||||
|
|
|
|||
|
|
@ -2268,7 +2268,6 @@ export const PADDLING_POOL_257 = () =>
|
|||
thirdPlaceMatch: true,
|
||||
isRanked: true,
|
||||
},
|
||||
showMapListGenerator: 0,
|
||||
discordUrl: null,
|
||||
castTwitchAccounts: ["dappleproductions"],
|
||||
castedMatchesInfo: {
|
||||
|
|
@ -8151,7 +8150,6 @@ export const PADDLING_POOL_255 = () =>
|
|||
],
|
||||
teamsPerGroup: 4,
|
||||
},
|
||||
showMapListGenerator: 0,
|
||||
discordUrl: null,
|
||||
castTwitchAccounts: ["dappleproductions"],
|
||||
castedMatchesInfo: {
|
||||
|
|
@ -14358,7 +14356,6 @@ export const IN_THE_ZONE_32 = () =>
|
|||
},
|
||||
],
|
||||
},
|
||||
showMapListGenerator: 0,
|
||||
discordUrl: null,
|
||||
castTwitchAccounts: ["dappleproductions", "kyochandxd"],
|
||||
castedMatchesInfo: null,
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ export const testTournament = (
|
|||
startTime: 1705858842,
|
||||
isFinalized: 0,
|
||||
name: "test",
|
||||
showMapListGenerator: 0,
|
||||
castTwitchAccounts: [],
|
||||
staff: [],
|
||||
tieBreakerMapPool: [],
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ export async function findById(id: number) {
|
|||
"CalendarEvent.id as eventId",
|
||||
"CalendarEvent.discordUrl",
|
||||
"Tournament.settings",
|
||||
"Tournament.showMapListGenerator",
|
||||
"Tournament.castTwitchAccounts",
|
||||
"Tournament.castedMatchesInfo",
|
||||
"Tournament.mapPickingStyle",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ select
|
|||
"Tournament"."id",
|
||||
"Tournament"."mapPickingStyle",
|
||||
"Tournament"."settings",
|
||||
"Tournament"."showMapListGenerator",
|
||||
"CalendarEvent"."id" as "eventId",
|
||||
"CalendarEvent"."name",
|
||||
"CalendarEvent"."description",
|
||||
|
|
@ -33,7 +32,7 @@ type FindByIdentifierRow = (Pick<
|
|||
CalendarEvent,
|
||||
"bracketUrl" | "name" | "description" | "authorId"
|
||||
> &
|
||||
Pick<Tournament, "id" | "mapPickingStyle" | "showMapListGenerator"> &
|
||||
Pick<Tournament, "id" | "mapPickingStyle"> &
|
||||
Pick<User, "discordId" | "username"> &
|
||||
Pick<CalendarEventDate, "startTime">) & {
|
||||
eventId: CalendarEvent["id"];
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
import { sql } from "~/db/sql";
|
||||
|
||||
const stm = sql.prepare(/* sql */ `
|
||||
update
|
||||
"Tournament"
|
||||
set
|
||||
"showMapListGenerator" = @showMapListGenerator
|
||||
where
|
||||
"id" = @tournamentId;
|
||||
`);
|
||||
|
||||
export function updateShowMapListGenerator({
|
||||
tournamentId,
|
||||
showMapListGenerator,
|
||||
}: {
|
||||
tournamentId: number;
|
||||
showMapListGenerator: number;
|
||||
}) {
|
||||
stm.run({ tournamentId, showMapListGenerator });
|
||||
}
|
||||
|
|
@ -1,25 +1,29 @@
|
|||
import type { ActionFunction } from "@remix-run/node";
|
||||
import { useFetcher, useSubmit } from "@remix-run/react";
|
||||
import { useFetcher } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Input } from "~/components/Input";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Redirect } from "~/components/Redirect";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { Toggle } from "~/components/Toggle";
|
||||
import { UserSearch } from "~/components/UserSearch";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import { USER } from "~/constants";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { requireUserId } from "~/features/auth/core/user.server";
|
||||
import { userIsBanned } from "~/features/ban/core/banned.server";
|
||||
import type { TournamentData } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import { isAdmin } from "~/permissions";
|
||||
import { findMapPoolByTeamId } from "~/features/tournament-bracket/queries/findMapPoolByTeamId.server";
|
||||
import * as TournamentTeamRepository from "~/features/tournament/TournamentTeamRepository.server";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { logger } from "~/utils/logger";
|
||||
import {
|
||||
badRequestIfFalsy,
|
||||
parseRequestFormData,
|
||||
|
|
@ -36,17 +40,10 @@ import { changeTeamOwner } from "../queries/changeTeamOwner.server";
|
|||
import { createTeam } from "../queries/createTeam.server";
|
||||
import { deleteTeam } from "../queries/deleteTeam.server";
|
||||
import { joinTeam, leaveTeam } from "../queries/joinLeaveTeam.server";
|
||||
import { updateShowMapListGenerator } from "../queries/updateShowMapListGenerator.server";
|
||||
import { adminActionSchema } from "../tournament-schemas.server";
|
||||
import { tournamentIdFromParams } from "../tournament-utils";
|
||||
import { useTournament } from "./to.$id";
|
||||
import { findMapPoolByTeamId } from "~/features/tournament-bracket/queries/findMapPoolByTeamId.server";
|
||||
import { Input } from "~/components/Input";
|
||||
import { logger } from "~/utils/logger";
|
||||
import { userIsBanned } from "~/features/ban/core/banned.server";
|
||||
import { inGameNameIfNeeded } from "../tournament-utils.server";
|
||||
import * as TournamentTeamRepository from "~/features/tournament/TournamentTeamRepository.server";
|
||||
import { USER } from "~/constants";
|
||||
import { useTournament } from "./to.$id";
|
||||
|
||||
export const action: ActionFunction = async ({ request, params }) => {
|
||||
const user = await requireUserId(request);
|
||||
|
|
@ -90,14 +87,6 @@ export const action: ActionFunction = async ({ request, params }) => {
|
|||
|
||||
break;
|
||||
}
|
||||
case "UPDATE_SHOW_MAP_LIST_GENERATOR": {
|
||||
validateIsTournamentAdmin();
|
||||
updateShowMapListGenerator({
|
||||
tournamentId: tournament.ctx.id,
|
||||
showMapListGenerator: Number(data.show),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "CHANGE_TEAM_OWNER": {
|
||||
validateIsTournamentOrganizer();
|
||||
const team = tournament.teamById(data.teamId);
|
||||
|
|
@ -394,7 +383,6 @@ export default function TournamentAdminPage() {
|
|||
<DownloadParticipants />
|
||||
<Divider smallText>Bracket reset</Divider>
|
||||
<BracketReset />
|
||||
{isAdmin(user) ? <EnableMapList /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -786,30 +774,6 @@ function RemoveStaffButton({
|
|||
);
|
||||
}
|
||||
|
||||
function EnableMapList() {
|
||||
const tournament = useTournament();
|
||||
const submit = useSubmit();
|
||||
const [eventStarted, setEventStarted] = React.useState(
|
||||
Boolean(tournament.ctx.showMapListGenerator),
|
||||
);
|
||||
function handleToggle(toggled: boolean) {
|
||||
setEventStarted(toggled);
|
||||
|
||||
const data = new FormData();
|
||||
data.append("_action", "UPDATE_SHOW_MAP_LIST_GENERATOR");
|
||||
data.append("show", toggled ? "on" : "off");
|
||||
|
||||
submit(data, { method: "post" });
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label>Public map list generator tool</label>
|
||||
<Toggle checked={eventStarted} setChecked={handleToggle} name="show" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DownloadParticipants() {
|
||||
const tournament = useTournament();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,387 +0,0 @@
|
|||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import { useActionData, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import type { MapPoolMap } from "~/db/types";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { getUserId } from "~/features/auth/core/user.server";
|
||||
import { MapPool } from "~/features/map-list-generator/core/map-pool";
|
||||
import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import { useSearchParamState } from "~/hooks/useSearchParamState";
|
||||
import type {
|
||||
BracketType,
|
||||
TournamentMapListMap,
|
||||
TournamentMaplistInput,
|
||||
TournamentMaplistSource,
|
||||
} from "~/modules/tournament-map-list-generator";
|
||||
import { createTournamentMapList } from "~/modules/tournament-map-list-generator";
|
||||
import { type SendouRouteHandle } from "~/utils/remix";
|
||||
import { tournamentPage } from "~/utils/urls";
|
||||
import { findMapPoolsByTournamentId } from "../queries/findMapPoolsByTournamentId.server";
|
||||
import { TOURNAMENT } from "../tournament-constants";
|
||||
import { tournamentIdFromParams } from "../tournament-utils";
|
||||
import { useTournament } from "./to.$id";
|
||||
|
||||
import "~/styles/maps.css";
|
||||
|
||||
export const handle: SendouRouteHandle = {
|
||||
i18n: ["tournament"],
|
||||
};
|
||||
|
||||
type TeamInState = {
|
||||
id: number;
|
||||
mapPool?: Pick<MapPoolMap, "mode" | "stageId">[] | null;
|
||||
};
|
||||
|
||||
export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
||||
const tournamentId = tournamentIdFromParams(params);
|
||||
const user = await getUserId(request);
|
||||
const tournament = await tournamentFromDB({ tournamentId, user });
|
||||
|
||||
const mapListGeneratorAvailable =
|
||||
tournament.isAdmin(user) || tournament.ctx.showMapListGenerator;
|
||||
|
||||
if (!mapListGeneratorAvailable) {
|
||||
throw redirect(tournamentPage(tournamentId));
|
||||
}
|
||||
|
||||
return {
|
||||
mapPools: findMapPoolsByTournamentId(tournamentId),
|
||||
};
|
||||
};
|
||||
|
||||
export default function TournamentMapsPage() {
|
||||
const user = useUser();
|
||||
const { t } = useTranslation(["tournament"]);
|
||||
const actionData = useActionData<{ failed?: boolean }>();
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const tournament = useTournament();
|
||||
|
||||
const [bestOf, setBestOf] = useSearchParamState<
|
||||
(typeof TOURNAMENT)["AVAILABLE_BEST_OF"][number]
|
||||
>({
|
||||
name: "bo",
|
||||
defaultValue: 3,
|
||||
revive: reviveBestOf,
|
||||
});
|
||||
const [teamOneId, setTeamOneId] = useSearchParamState({
|
||||
name: "team-one",
|
||||
defaultValue:
|
||||
tournament.ownedTeamByUser(user)?.id ?? tournament.ctx.teams[0]?.id,
|
||||
revive: reviveTeam(tournament.ctx.teams.map((t) => t.id)),
|
||||
});
|
||||
const [teamTwoId, setTeamTwoId] = useSearchParamState({
|
||||
name: "team-two",
|
||||
defaultValue: tournament.ctx.teams[1]?.id,
|
||||
revive: reviveTeam(
|
||||
tournament.ctx.teams.map((t) => t.id),
|
||||
teamOneId,
|
||||
),
|
||||
});
|
||||
const [roundNumber, setRoundNumber] = useSearchParamState({
|
||||
name: "round",
|
||||
defaultValue: 1,
|
||||
revive: reviveRound,
|
||||
});
|
||||
const [bracketType, setBracketType] = useSearchParamState<BracketType>({
|
||||
name: "bracket",
|
||||
defaultValue: "DE_WINNERS",
|
||||
revive: reviveBracketType,
|
||||
});
|
||||
|
||||
const teamOne = tournament.ctx.teams.find((t) => t.id === teamOneId) ?? {
|
||||
id: -1,
|
||||
mapPool: [],
|
||||
};
|
||||
const teamTwo = tournament.ctx.teams.find((t) => t.id === teamTwoId) ?? {
|
||||
id: -1,
|
||||
mapPool: [],
|
||||
};
|
||||
|
||||
const teamOneMaps =
|
||||
data.mapPools.find((mp) => mp.tournamentTeamId === teamOne.id)?.mapPool ??
|
||||
[];
|
||||
const teamTwoMaps =
|
||||
data.mapPools.find((mp) => mp.tournamentTeamId === teamTwo.id)?.mapPool ??
|
||||
[];
|
||||
|
||||
return (
|
||||
<div className="stack md">
|
||||
{actionData?.failed && (
|
||||
<Alert variation="ERROR" tiny>
|
||||
{t("tournament:generator.error")}
|
||||
</Alert>
|
||||
)}
|
||||
<RoundSelect
|
||||
roundNumber={roundNumber}
|
||||
bracketType={bracketType}
|
||||
handleChange={(roundNumber, bracketType) => {
|
||||
setRoundNumber(roundNumber);
|
||||
setBracketType(bracketType);
|
||||
}}
|
||||
/>
|
||||
<div className="tournament__teams-container">
|
||||
<TeamsSelect
|
||||
number={1}
|
||||
team={teamOne}
|
||||
otherTeam={teamTwo}
|
||||
setTeam={setTeamOneId}
|
||||
/>
|
||||
<TeamsSelect
|
||||
number={2}
|
||||
team={teamTwo}
|
||||
otherTeam={teamOne}
|
||||
setTeam={setTeamTwoId}
|
||||
/>
|
||||
</div>
|
||||
<BestOfRadios bestOf={bestOf} setBestOf={setBestOf} />
|
||||
<MapList
|
||||
teams={[
|
||||
{ ...teamOne, maps: new MapPool(teamOneMaps) },
|
||||
{ ...teamTwo, maps: new MapPool(teamTwoMaps) },
|
||||
]}
|
||||
count={bestOf}
|
||||
seed={`${bracketType}-${roundNumber}`}
|
||||
modesIncluded={tournament.modesIncluded}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const BRACKET_TYPES: Array<BracketType> = ["DE_WINNERS", "DE_LOSERS"];
|
||||
const AMOUNT_OF_ROUNDS = 12;
|
||||
|
||||
function reviveBestOf(value: string) {
|
||||
const parsed = Number(value);
|
||||
|
||||
return TOURNAMENT.AVAILABLE_BEST_OF.find((bo) => bo === parsed);
|
||||
}
|
||||
|
||||
function reviveBracketType(value: string) {
|
||||
return BRACKET_TYPES.find((bracketType) => bracketType === value);
|
||||
}
|
||||
|
||||
function reviveRound(value: string) {
|
||||
const parsed = Number(value);
|
||||
|
||||
return new Array(AMOUNT_OF_ROUNDS)
|
||||
.fill(null)
|
||||
.map((_, i) => i + 1)
|
||||
.find((val) => val === parsed);
|
||||
}
|
||||
|
||||
function reviveTeam(teamIds: number[], excludedTeamId?: number) {
|
||||
return function (value: string) {
|
||||
const parsed = Number(value);
|
||||
|
||||
return teamIds
|
||||
.filter((id) => id !== excludedTeamId)
|
||||
.find((id) => id === parsed);
|
||||
};
|
||||
}
|
||||
|
||||
function RoundSelect({
|
||||
roundNumber,
|
||||
bracketType,
|
||||
handleChange,
|
||||
}: {
|
||||
roundNumber: number;
|
||||
bracketType: string;
|
||||
handleChange: (roundNumber: number, bracketType: BracketType) => void;
|
||||
}) {
|
||||
const { t } = useTranslation(["tournament"]);
|
||||
|
||||
return (
|
||||
<div className="tournament__round-container tournament__select-container">
|
||||
<label htmlFor="round">{t("tournament:round.label")}</label>
|
||||
<select
|
||||
id="round"
|
||||
value={`${bracketType}-${roundNumber}`}
|
||||
onChange={(e) => {
|
||||
const [bracketType, roundNumber] = e.target.value.split("-") as [
|
||||
BracketType,
|
||||
string,
|
||||
];
|
||||
handleChange(Number(roundNumber), bracketType);
|
||||
}}
|
||||
>
|
||||
{BRACKET_TYPES.flatMap((type) =>
|
||||
new Array(AMOUNT_OF_ROUNDS).fill(null).map((_, i) => {
|
||||
return (
|
||||
<option key={`${type}-${i}`} value={`${type}-${i + 1}`}>
|
||||
{t(`tournament:bracket.type.${type}`)} {i + 1}
|
||||
</option>
|
||||
);
|
||||
}),
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function TeamsSelect({
|
||||
number,
|
||||
team,
|
||||
otherTeam,
|
||||
setTeam,
|
||||
}: {
|
||||
number: number;
|
||||
team: { id: number };
|
||||
otherTeam: TeamInState;
|
||||
setTeam: (newTeamId: number) => void;
|
||||
}) {
|
||||
const { t } = useTranslation(["tournament"]);
|
||||
const tournament = useTournament();
|
||||
|
||||
return (
|
||||
<div className="tournament__select-container">
|
||||
<label htmlFor="round">
|
||||
{t("tournament:team.label")} {number}
|
||||
</label>
|
||||
<select
|
||||
id="round"
|
||||
className="tournament__team-select"
|
||||
value={team.id}
|
||||
onChange={(e) => {
|
||||
setTeam(Number(e.target.value));
|
||||
}}
|
||||
>
|
||||
<option value={-1}>({t("tournament:team.unlisted")})</option>
|
||||
{tournament.ctx.teams
|
||||
.filter((t) => t.id !== otherTeam.id)
|
||||
.map((team) => (
|
||||
<option key={team.id} value={team.id}>
|
||||
{team.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function BestOfRadios({
|
||||
bestOf,
|
||||
setBestOf,
|
||||
}: {
|
||||
bestOf: (typeof TOURNAMENT)["AVAILABLE_BEST_OF"][number];
|
||||
setBestOf: (bestOf: (typeof TOURNAMENT)["AVAILABLE_BEST_OF"][number]) => void;
|
||||
}) {
|
||||
const { t } = useTranslation(["tournament"]);
|
||||
|
||||
return (
|
||||
<div className="tournament__bo-radios-container">
|
||||
{TOURNAMENT.AVAILABLE_BEST_OF.map((bestOfOption) => (
|
||||
<div key={bestOfOption}>
|
||||
<label htmlFor={String(bestOfOption)}>
|
||||
{t("tournament:bestOf.label.short")}
|
||||
{bestOfOption}
|
||||
</label>
|
||||
<input
|
||||
id={String(bestOfOption)}
|
||||
name="bestOf"
|
||||
type="radio"
|
||||
checked={bestOfOption === bestOf}
|
||||
onChange={() => setBestOf(bestOfOption)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function MapList(props: Omit<TournamentMaplistInput, "tiebreakerMaps">) {
|
||||
const { t } = useTranslation(["game-misc"]);
|
||||
const tournament = useTournament();
|
||||
|
||||
let mapList: Array<TournamentMapListMap>;
|
||||
|
||||
try {
|
||||
mapList = createTournamentMapList({
|
||||
...props,
|
||||
tiebreakerMaps: new MapPool(tournament.ctx.tieBreakerMapPool),
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(
|
||||
"Failed to create map list. Falling back to default maps.",
|
||||
e,
|
||||
);
|
||||
|
||||
mapList = createTournamentMapList({
|
||||
...props,
|
||||
teams: [
|
||||
{
|
||||
id: -1,
|
||||
maps: new MapPool([]),
|
||||
},
|
||||
{
|
||||
id: -2,
|
||||
maps: new MapPool([]),
|
||||
},
|
||||
],
|
||||
tiebreakerMaps: new MapPool(tournament.ctx.tieBreakerMapPool),
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tournament__map-list">
|
||||
{mapList.map(({ stageId, mode, source }, i) => {
|
||||
return (
|
||||
<React.Fragment key={`${stageId}-${mode}`}>
|
||||
<PickInfoText
|
||||
source={source}
|
||||
teamOneId={props.teams[0].id}
|
||||
teamTwoId={props.teams[1].id}
|
||||
/>
|
||||
<div key={stageId} className="tournament__stage-listed">
|
||||
{i + 1}) {mode} {t(`game-misc:STAGE_${stageId}`)}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PickInfoText({
|
||||
source,
|
||||
teamOneId,
|
||||
teamTwoId,
|
||||
}: {
|
||||
source: TournamentMaplistSource;
|
||||
teamOneId: number;
|
||||
teamTwoId: number;
|
||||
}) {
|
||||
const { t } = useTranslation(["tournament"]);
|
||||
|
||||
const text = () => {
|
||||
if (source === teamOneId) {
|
||||
return t("tournament:pickInfo.team", { number: 1 });
|
||||
}
|
||||
if (source === teamTwoId) {
|
||||
return t("tournament:pickInfo.team", { number: 2 });
|
||||
}
|
||||
if (source === "TIEBREAKER") return t("tournament:pickInfo.tiebreaker");
|
||||
if (source === "BOTH") return t("tournament:pickInfo.both");
|
||||
if (source === "DEFAULT") return t("tournament:pickInfo.default");
|
||||
if (source === "COUNTERPICK") return t("tournament:pickInfo.counterpick");
|
||||
if (source === "TO") return "";
|
||||
|
||||
console.error(`Unknown source: ${String(source)}`);
|
||||
return "";
|
||||
};
|
||||
|
||||
const otherClassName = () => {
|
||||
if (source === teamOneId) return "team-1";
|
||||
if (source === teamTwoId) return "team-2";
|
||||
return typeof source === "string" ? source.toLocaleLowerCase() : source;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx("tournament__pick-info", otherClassName())}>
|
||||
{text()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -211,9 +211,6 @@ export default function TournamentLayout() {
|
|||
<SubNavLink to="brackets" data-testid="brackets-tab" prefetch="render">
|
||||
{t("tournament:tabs.brackets")}
|
||||
</SubNavLink>
|
||||
{tournament.ctx.showMapListGenerator ? (
|
||||
<SubNavLink to="maps">{t("tournament:tabs.maps")}</SubNavLink>
|
||||
) : null}
|
||||
<SubNavLink to="teams" end={false} prefetch="render">
|
||||
{t("tournament:tabs.teams", { count: tournament.ctx.teams.length })}
|
||||
</SubNavLink>
|
||||
|
|
|
|||
|
|
@ -53,10 +53,6 @@ export const seedsActionSchema = z.object({
|
|||
});
|
||||
|
||||
export const adminActionSchema = z.union([
|
||||
z.object({
|
||||
_action: _action("UPDATE_SHOW_MAP_LIST_GENERATOR"),
|
||||
show: z.preprocess(checkboxValueToBoolean, z.boolean()),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("CHANGE_TEAM_OWNER"),
|
||||
teamId: id,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "Hold ({{count}})",
|
||||
"tabs.admin": "Admin",
|
||||
"tabs.register": "Register",
|
||||
"tabs.maps": "Baner",
|
||||
"tabs.brackets": "Grupper",
|
||||
"tabs.seeds": "Seedninger",
|
||||
"tabs.streams": "Streams ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "Teams ({{count}})",
|
||||
"tabs.admin": "Admin",
|
||||
"tabs.register": "Register",
|
||||
"tabs.maps": "Maps",
|
||||
"tabs.brackets": "Brackets",
|
||||
"tabs.seeds": "Seeds",
|
||||
"tabs.streams": "Streams ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "Equipos ({{count}})",
|
||||
"tabs.admin": "Admin",
|
||||
"tabs.register": "Registrar",
|
||||
"tabs.maps": "Mapas",
|
||||
"tabs.brackets": "Cuadros de Torneo",
|
||||
"tabs.seeds": "Listas de Equipos",
|
||||
"tabs.streams": "Streams ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "Equipos ({{count}})",
|
||||
"tabs.admin": "Admin",
|
||||
"tabs.register": "Registrar",
|
||||
"tabs.maps": "Mapas",
|
||||
"tabs.brackets": "Cuadros de Torneo",
|
||||
"tabs.seeds": "Listas de Equipos",
|
||||
"tabs.streams": "Streams ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "Équipes ({{count}})",
|
||||
"tabs.admin": "Admin",
|
||||
"tabs.register": "Registration",
|
||||
"tabs.maps": "Stages",
|
||||
"tabs.brackets": "Brackets",
|
||||
"tabs.seeds": "Seeds",
|
||||
"tabs.streams": "Diffusions ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "צוותים ({{count}})",
|
||||
"tabs.admin": "מנהל",
|
||||
"tabs.register": "הרשמה",
|
||||
"tabs.maps": "מפות",
|
||||
"tabs.brackets": "מערכים",
|
||||
"tabs.seeds": "דירוג",
|
||||
"tabs.streams": "שידורים חיים ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "チーム ({{count}})",
|
||||
"tabs.admin": "管理",
|
||||
"tabs.register": "登録",
|
||||
"tabs.maps": "マップ一覧",
|
||||
"tabs.brackets": "ブラケット",
|
||||
"tabs.seeds": "シード",
|
||||
"tabs.streams": "配信 ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "Times ({{count}})",
|
||||
"tabs.admin": "Administrador",
|
||||
"tabs.register": "Registrar",
|
||||
"tabs.maps": "Mapas",
|
||||
"tabs.brackets": "Brackets",
|
||||
"tabs.seeds": "Sementes",
|
||||
"tabs.streams": "Transmissões ({{count}})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"tabs.teams": "参赛队伍 ({{count}})",
|
||||
"tabs.admin": "管理",
|
||||
"tabs.register": "报名",
|
||||
"tabs.maps": "地图",
|
||||
"tabs.brackets": "对战表",
|
||||
"tabs.seeds": "种子",
|
||||
"tabs.streams": "直播 ({{count}})",
|
||||
|
|
|
|||
|
|
@ -154,10 +154,6 @@ export default defineConfig(() => {
|
|||
"/to/:id/seeds",
|
||||
"features/tournament/routes/to.$id.seeds.tsx",
|
||||
);
|
||||
route(
|
||||
"/to/:id/maps",
|
||||
"features/tournament/routes/to.$id.maps.tsx",
|
||||
);
|
||||
route(
|
||||
"/to/:id/streams",
|
||||
"features/tournament/routes/to.$id.streams.tsx",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user