fix: use role filters

This commit is contained in:
TrèsAbhi committed 2026-01-02 12:39:45 -06:00
1 parent 56a09536cd
commit 8f54bd5971
1 file changed
+151 -87
@@ -26,10 +26,11 @@ import {
type FlexProps, type FlexProps,
} from "@radix-ui/themes"; } from "@radix-ui/themes";
import { times } from "lodash-es"; import { times } from "lodash-es";
import type { ComponentProps, ReactNode } from "react"; import { Fragment, type ComponentProps, type ReactNode } from "react";
import { awaitableConsumableDefinitions } from "../../../core/awaitables/consumableDefinitions"; import { awaitableConsumableDefinitions } from "../../../core/awaitables/consumableDefinitions";
import { awaitableGameDefinitions } from "../../../core/awaitables/gameDefinitions"; import { awaitableGameDefinitions } from "../../../core/awaitables/gameDefinitions";
import { awaitableProvisionDefinitions } from "../../../core/awaitables/provisionDefinitions"; import { awaitableProvisionDefinitions } from "../../../core/awaitables/provisionDefinitions";
import { awaitableTankDefinitions } from "../../../core/awaitables/tankDefinitions";
import { useLocale } from "../../../hooks/useLocale"; import { useLocale } from "../../../hooks/useLocale";
import { App } from "../../../stores/app"; import { App } from "../../../stores/app";
import { TankFilters, type CaseType } from "../../../stores/tankFilters"; import { TankFilters, type CaseType } from "../../../stores/tankFilters";
@@ -45,6 +46,59 @@ import { ScienceOffIcon } from "../../ScienceOffIcon";
const gameDefinitions = await awaitableGameDefinitions; const gameDefinitions = await awaitableGameDefinitions;
const consumableDefinitions = await awaitableConsumableDefinitions; const consumableDefinitions = await awaitableConsumableDefinitions;
const provisionDefinitions = await awaitableProvisionDefinitions; const provisionDefinitions = await awaitableProvisionDefinitions;
const tankDefinitions = await awaitableTankDefinitions;
const gameModeRoleSets: Record<number, Set<number>> = {};
for (const tankIdString in tankDefinitions.tanks) {
const gameMode = tankDefinitions.tanks[tankIdString];
for (const gameModeIdString in gameMode.roles) {
const role = gameMode.roles[gameModeIdString];
const gameModeId = Number(gameModeIdString);
if (gameModeId in gameModeRoleSets) {
gameModeRoleSets[gameModeId].add(role);
} else {
gameModeRoleSets[gameModeId] = new Set([role]);
}
}
}
const gameModeRoles: {
gameModeId: number;
consumables: number[];
provisions: number[];
}[] = [];
const allGameModeConsumables = new Set<number>();
const allGameModeProvisions = new Set<number>();
for (const gameModeIdString in gameModeRoleSets) {
const gameModeId = Number(gameModeIdString);
const roles = gameModeRoleSets[gameModeId];
const consumables = new Set<number>();
const provisions = new Set<number>();
for (const roleId of roles) {
const role = gameDefinitions.roles[roleId];
for (const id of role.consumables) {
consumables.add(id);
allGameModeConsumables.add(id);
}
for (const id of role.provisions) {
provisions.add(id);
allGameModeProvisions.add(id);
}
}
gameModeRoles.push({
gameModeId: gameModeId,
consumables: Array.from(consumables.values()),
provisions: Array.from(provisions.values()),
});
}
const consumablesArray = Object.values(consumableDefinitions.consumables) const consumablesArray = Object.values(consumableDefinitions.consumables)
.filter( .filter(
@@ -53,18 +107,6 @@ const consumablesArray = Object.values(consumableDefinitions.consumables)
consumable.name.locales[locales.default] consumable.name.locales[locales.default]
) )
.map((consumable) => consumable.id); .map((consumable) => consumable.id);
const abilitiesArray = Array.from(
Object.values(consumableDefinitions.consumables)
.filter((ability) => ability.game_mode_exclusive)
.reduce((uniqueMap, consumable) => {
if (!uniqueMap.has(consumable.name.locales[locales.default])) {
uniqueMap.set(consumable.name.locales[locales.default], consumable.id);
}
return uniqueMap;
}, new Map<string, number>())
.values()
);
const provisionsArray = Array.from( const provisionsArray = Array.from(
Object.values(provisionDefinitions.provisions) Object.values(provisionDefinitions.provisions)
.filter( .filter(
@@ -81,22 +123,6 @@ const provisionsArray = Array.from(
}, new Map<string, number>()) }, new Map<string, number>())
.values() .values()
); );
const powersArray = Array.from(
Object.values(provisionDefinitions.provisions)
.filter(
(provision) =>
provision.game_mode_exclusive && provision.name.locales[locales.default]
)
.reduce((uniqueMap, consumable) => {
if (!uniqueMap.has(consumable.name.locales[locales.default])) {
uniqueMap.set(consumable.name.locales[locales.default], consumable.id);
}
return uniqueMap;
}, new Map<string, number>())
.values()
);
const shellTypeIcons: Record<ShellType, string> = { const shellTypeIcons: Record<ShellType, string> = {
[ShellType.AP]: "ap", [ShellType.AP]: "ap",
[ShellType.APCR]: "ap_cr", [ShellType.APCR]: "ap_cr",
@@ -1008,7 +1034,10 @@ function ProvisionsFilter() {
function PowersFilter() { function PowersFilter() {
const { unwrap, strings } = useLocale(); const { unwrap, strings } = useLocale();
const rawPowers = TankFilters.use((state) => state.powers); const rawPowers = TankFilters.use((state) => state.powers);
const powers = rawPowers.length === 0 ? powersArray : rawPowers; const powers =
rawPowers.length === 0
? Array.from(allGameModeProvisions.values())
: rawPowers;
return ( return (
<DropdownMenu.Root modal={false}> <DropdownMenu.Root modal={false}>
@@ -1041,37 +1070,54 @@ function PowersFilter() {
</DropdownMenu.Trigger> </DropdownMenu.Trigger>
<DropdownMenu.Content> <DropdownMenu.Content>
{powersArray.map((power) => { {gameModeRoles.map(({ gameModeId, provisions }) => {
const selected = rawPowers.includes(power); const gameMode = gameDefinitions.gameModes[gameModeId];
const powerDefinition = provisionDefinitions.provisions[power];
if (provisions.length === 0) return null;
return ( return (
<DropdownMenu.CheckboxItem <Fragment key={gameModeId}>
onClick={(event) => { <DropdownMenu.Label>{unwrap(gameMode.name)}</DropdownMenu.Label>
event.preventDefault();
TankFilters.mutate((draft) => { {provisions.map((provision) => {
if (selected) { {
draft.powers = draft.powers.filter((n) => n !== power); const selected = rawPowers.includes(provision);
} else { const powerDefinition =
draft.powers = [...draft.powers, power]; provisionDefinitions.provisions[provision];
}
});
}}
checked={selected}
key={power}
>
<img
style={{
width: "1.25em",
height: "1.25em",
objectFit: "contain",
}}
src={asset(`icons/provisions/${power}.webp`)}
/>
{unwrap(powerDefinition.name)} return (
</DropdownMenu.CheckboxItem> <DropdownMenu.CheckboxItem
onClick={(event) => {
event.preventDefault();
TankFilters.mutate((draft) => {
if (selected) {
draft.powers = draft.powers.filter(
(n) => n !== provision
);
} else {
draft.powers = [...draft.powers, provision];
}
});
}}
checked={selected}
key={provision}
>
<img
style={{
width: "1.25em",
height: "1.25em",
objectFit: "contain",
}}
src={asset(`icons/provisions/${provision}.webp`)}
/>
{unwrap(powerDefinition.name)}
</DropdownMenu.CheckboxItem>
);
}
})}
</Fragment>
); );
})} })}
@@ -1098,7 +1144,10 @@ function PowersFilter() {
function AbilitiesFilter() { function AbilitiesFilter() {
const { unwrap, strings } = useLocale(); const { unwrap, strings } = useLocale();
const rawAbilities = TankFilters.use((state) => state.abilities); const rawAbilities = TankFilters.use((state) => state.abilities);
const abilities = rawAbilities.length === 0 ? abilitiesArray : rawAbilities; const abilities =
rawAbilities.length === 0
? Array.from(allGameModeConsumables.values())
: rawAbilities;
return ( return (
<DropdownMenu.Root modal={false}> <DropdownMenu.Root modal={false}>
@@ -1131,39 +1180,54 @@ function AbilitiesFilter() {
</DropdownMenu.Trigger> </DropdownMenu.Trigger>
<DropdownMenu.Content> <DropdownMenu.Content>
{abilitiesArray.map((ability) => { {gameModeRoles.map(({ gameModeId, consumables }) => {
const selected = rawAbilities.includes(ability); const gameMode = gameDefinitions.gameModes[gameModeId];
const abilityDefinition = consumableDefinitions.consumables[ability];
if (consumables.length === 0) return null;
return ( return (
<DropdownMenu.CheckboxItem <Fragment key={gameModeId}>
onClick={(event) => { <DropdownMenu.Label>{unwrap(gameMode.name)}</DropdownMenu.Label>
event.preventDefault();
TankFilters.mutate((draft) => { {consumables.map((consumable) => {
if (selected) { {
draft.abilities = draft.abilities.filter( const selected = rawAbilities.includes(consumable);
(n) => n !== ability const abilityDefinition =
); consumableDefinitions.consumables[consumable];
} else {
draft.abilities = [...draft.abilities, ability];
}
});
}}
checked={selected}
key={ability}
>
<img
style={{
width: "1.25em",
height: "1.25em",
objectFit: "contain",
}}
src={asset(`icons/consumables/${ability}.webp`)}
/>
{unwrap(abilityDefinition.name)} return (
</DropdownMenu.CheckboxItem> <DropdownMenu.CheckboxItem
onClick={(event) => {
event.preventDefault();
TankFilters.mutate((draft) => {
if (selected) {
draft.abilities = draft.abilities.filter(
(n) => n !== consumable
);
} else {
draft.abilities = [...draft.abilities, consumable];
}
});
}}
checked={selected}
key={consumable}
>
<img
style={{
width: "1.25em",
height: "1.25em",
objectFit: "contain",
}}
src={asset(`icons/consumables/${consumable}.webp`)}
/>
{unwrap(abilityDefinition.name)}
</DropdownMenu.CheckboxItem>
);
}
})}
</Fragment>
); );
})} })}