mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-25 11:39:51 +01:00
feat: consumables
This commit is contained in:
1 parent
547381286e
commit
98e0f28cd9
1 file changed
+111
-2
@@ -7,6 +7,7 @@ import {
|
|||||||
TankType,
|
TankType,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
} from "@blitzkit/core";
|
} from "@blitzkit/core";
|
||||||
|
import locales from "@blitzkit/i18n/locales.json";
|
||||||
import {
|
import {
|
||||||
LockClosedIcon,
|
LockClosedIcon,
|
||||||
LockOpen2Icon,
|
LockOpen2Icon,
|
||||||
@@ -24,6 +25,7 @@ import {
|
|||||||
} 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 type { ComponentProps, ReactNode } from "react";
|
||||||
|
import { awaitableConsumableDefinitions } from "../../../core/awaitables/consumableDefinitions";
|
||||||
import { awaitableGameDefinitions } from "../../../core/awaitables/gameDefinitions";
|
import { awaitableGameDefinitions } from "../../../core/awaitables/gameDefinitions";
|
||||||
import { useLocale } from "../../../hooks/useLocale";
|
import { useLocale } from "../../../hooks/useLocale";
|
||||||
import { App } from "../../../stores/app";
|
import { App } from "../../../stores/app";
|
||||||
@@ -38,6 +40,18 @@ import { ScienceIcon } from "../../ScienceIcon";
|
|||||||
import { ScienceOffIcon } from "../../ScienceOffIcon";
|
import { ScienceOffIcon } from "../../ScienceOffIcon";
|
||||||
|
|
||||||
const gameDefinitions = await awaitableGameDefinitions;
|
const gameDefinitions = await awaitableGameDefinitions;
|
||||||
|
const consumableDefinitions = await awaitableConsumableDefinitions;
|
||||||
|
|
||||||
|
const consumablesArray = Object.values(consumableDefinitions.consumables)
|
||||||
|
.filter(
|
||||||
|
(consumable) =>
|
||||||
|
!consumable.game_mode_exclusive &&
|
||||||
|
consumable.name.locales[locales.default]
|
||||||
|
)
|
||||||
|
.map((consumable) => consumable.id);
|
||||||
|
const abilitiesArray = Object.values(consumableDefinitions.consumables)
|
||||||
|
.filter((consumable) => consumable.game_mode_exclusive)
|
||||||
|
.map((consumable) => consumable.id);
|
||||||
|
|
||||||
const shellTypeIcons: Record<ShellType, string> = {
|
const shellTypeIcons: Record<ShellType, string> = {
|
||||||
[ShellType.AP]: "ap",
|
[ShellType.AP]: "ap",
|
||||||
@@ -66,6 +80,7 @@ const GUN_TYPES = Object.keys(
|
|||||||
) as (keyof typeof GUN_TYPE_ICONS)[];
|
) as (keyof typeof GUN_TYPE_ICONS)[];
|
||||||
|
|
||||||
const MAX_TIERS = 4;
|
const MAX_TIERS = 4;
|
||||||
|
const MAX_CONSUMABLES = 4;
|
||||||
|
|
||||||
const TIERS = times(10, (i) => 10 - i);
|
const TIERS = times(10, (i) => 10 - i);
|
||||||
|
|
||||||
@@ -76,10 +91,13 @@ export function FilterControl() {
|
|||||||
<NationsFilter />
|
<NationsFilter />
|
||||||
<TypeFilter />
|
<TypeFilter />
|
||||||
<ClassFilter />
|
<ClassFilter />
|
||||||
<GunTypeFilter />
|
|
||||||
<ShellFilter />
|
|
||||||
<OwnershipFilter />
|
<OwnershipFilter />
|
||||||
<TestFilter />
|
<TestFilter />
|
||||||
|
|
||||||
|
<GunTypeFilter />
|
||||||
|
<ShellFilter />
|
||||||
|
<ConsumablesFilter />
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -706,3 +724,94 @@ function TestFilter() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ConsumablesFilter() {
|
||||||
|
const rawConsumables = TankFilters.use((state) => state.consumables);
|
||||||
|
const consumables =
|
||||||
|
rawConsumables.length === 0 ? consumablesArray : rawConsumables;
|
||||||
|
const { unwrap } = useLocale();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<Button color="gray" variant="surface">
|
||||||
|
<Flex>
|
||||||
|
{consumables.slice(0, MAX_CONSUMABLES).map((consumable, index) => (
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
filter: "drop-shadow(0 0 var(--space-1) var(--black-a11))",
|
||||||
|
marginLeft: index > 0 ? "-0.5em" : undefined,
|
||||||
|
width: "1.25em",
|
||||||
|
height: "1.25em",
|
||||||
|
objectFit: "contain",
|
||||||
|
}}
|
||||||
|
src={asset(`icons/consumables/${consumable}.webp`)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{consumables.length > MAX_CONSUMABLES && (
|
||||||
|
<Text size="1" ml="1">
|
||||||
|
+{consumables.length - MAX_CONSUMABLES}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Button>
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
{consumablesArray.map((consumable) => {
|
||||||
|
const selected = rawConsumables.includes(consumable);
|
||||||
|
const consumableDefinition =
|
||||||
|
consumableDefinitions.consumables[consumable];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu.CheckboxItem
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
TankFilters.mutate((draft) => {
|
||||||
|
if (selected) {
|
||||||
|
draft.consumables = draft.consumables.filter(
|
||||||
|
(n) => n !== consumable
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
draft.consumables = [...draft.consumables, consumable];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
checked={selected}
|
||||||
|
key={consumable}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
width: "1em",
|
||||||
|
height: "1em",
|
||||||
|
objectFit: "contain",
|
||||||
|
}}
|
||||||
|
src={asset(`icons/consumables/${consumable}.webp`)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{unwrap(consumableDefinition.name)}
|
||||||
|
</DropdownMenu.CheckboxItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
|
||||||
|
<DropdownMenu.Item
|
||||||
|
color="red"
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
TankFilters.mutate((draft) => {
|
||||||
|
draft.consumables = [];
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TrashIcon />
|
||||||
|
Clear
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user