mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-24 23:19:39 -05:00
Tier list maker: allow filtering down stage+modes by mode
This commit is contained in:
parent
da59b2e79e
commit
d1d0e68b4b
|
|
@ -7,8 +7,12 @@ import { arrayMove } from "@dnd-kit/sortable";
|
|||
import { useSearchParams } from "@remix-run/react";
|
||||
import JSONCrush from "jsoncrush";
|
||||
import * as React from "react";
|
||||
import { useSearchParamState } from "~/hooks/useSearchParamState";
|
||||
import { modesShort } from "~/modules/in-game-lists/modes";
|
||||
import { z } from "zod/v4";
|
||||
import {
|
||||
useSearchParamState,
|
||||
useSearchParamStateEncoder,
|
||||
} from "~/hooks/useSearchParamState";
|
||||
import { modesShort, rankedModesShort } from "~/modules/in-game-lists/modes";
|
||||
import { stageIds } from "~/modules/in-game-lists/stage-ids";
|
||||
import {
|
||||
mainWeaponIds,
|
||||
|
|
@ -17,6 +21,7 @@ import {
|
|||
weaponIdToType,
|
||||
} from "~/modules/in-game-lists/weapon-ids";
|
||||
import { assertUnreachable } from "~/utils/types";
|
||||
import { modeShort, safeJSONParse } from "~/utils/zod";
|
||||
import { DEFAULT_TIERS } from "../tier-list-maker-constants";
|
||||
import {
|
||||
type TierListItem,
|
||||
|
|
@ -71,6 +76,17 @@ export function useTierList() {
|
|||
revive: (value) => value,
|
||||
});
|
||||
|
||||
const [selectedModes, setSelectedModes] = useSearchParamStateEncoder({
|
||||
name: "modes",
|
||||
defaultValue: rankedModesShort,
|
||||
revive: (value) =>
|
||||
z
|
||||
.preprocess(safeJSONParse, z.array(modeShort))
|
||||
.catch(() => rankedModesShort)
|
||||
.parse(value),
|
||||
encode: JSON.stringify,
|
||||
});
|
||||
|
||||
const parseItemFromId = (id: string): TierListItem | null => {
|
||||
const [type, idStr, nth] = String(id).split(":");
|
||||
if (!type || !idStr) return null;
|
||||
|
|
@ -319,7 +335,9 @@ export function useTierList() {
|
|||
const combinations: string[] = [];
|
||||
for (const stageId of stageIds) {
|
||||
for (const mode of modesShort) {
|
||||
combinations.push(`${stageId}-${mode}`);
|
||||
if (selectedModes.includes(mode)) {
|
||||
combinations.push(`${stageId}-${mode}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return combinations;
|
||||
|
|
@ -429,6 +447,8 @@ export function useTierList() {
|
|||
setShowTierHeaders,
|
||||
title,
|
||||
setTitle,
|
||||
selectedModes,
|
||||
setSelectedModes,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
gap: var(--s-4);
|
||||
}
|
||||
|
||||
.modeFilters {
|
||||
column-gap: var(--s-8);
|
||||
row-gap: var(--s-2);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.titleInput {
|
||||
width: 100%;
|
||||
padding: 0 var(--s-2) var(--s-2) var(--s-2);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import {
|
|||
SendouTabPanel,
|
||||
SendouTabs,
|
||||
} from "~/components/elements/Tabs";
|
||||
import { ModeImage } from "~/components/Image";
|
||||
import { DownloadIcon } from "~/components/icons/Download";
|
||||
import { PlusIcon } from "~/components/icons/Plus";
|
||||
import { RefreshIcon } from "~/components/icons/Refresh";
|
||||
|
|
@ -31,6 +32,7 @@ import { Main } from "~/components/Main";
|
|||
import { Placeholder } from "~/components/Placeholder";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import { modesShort } from "~/modules/in-game-lists/modes";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { navIconUrl, TIER_LIST_MAKER_URL } from "~/utils/urls";
|
||||
|
|
@ -106,6 +108,8 @@ function TierListMakerContent() {
|
|||
setTitle,
|
||||
screenshotMode,
|
||||
setScreenshotMode,
|
||||
selectedModes,
|
||||
setSelectedModes,
|
||||
} = useTierListState();
|
||||
|
||||
const sensors = useSensors(
|
||||
|
|
@ -269,7 +273,31 @@ function TierListMakerContent() {
|
|||
</SendouTabPanel>
|
||||
|
||||
<SendouTabPanel id="stage-mode">
|
||||
<ItemPool />
|
||||
<div className="stack md">
|
||||
<ItemPool />
|
||||
<div className={clsx(styles.filters, styles.modeFilters)}>
|
||||
{modesShort.map((mode) => {
|
||||
const isSelected = selectedModes.includes(mode);
|
||||
return (
|
||||
<SendouSwitch
|
||||
key={mode}
|
||||
isSelected={isSelected}
|
||||
onChange={(selected) => {
|
||||
if (selected) {
|
||||
setSelectedModes([...selectedModes, mode]);
|
||||
} else {
|
||||
setSelectedModes(
|
||||
selectedModes.filter((m) => m !== mode),
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ModeImage mode={mode} size={32} />
|
||||
</SendouSwitch>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</SendouTabPanel>
|
||||
</SendouTabs>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user