mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: gun type filters
This commit is contained in:
1 parent
2d3e45df73
commit
c4fa6cebfa
7 files changed
+206
-11
No files matched your search
Vendored
+2
@@ -13,6 +13,8 @@
|
||||
"artefacts",
|
||||
"astrojs",
|
||||
"atgm",
|
||||
"Autoloader",
|
||||
"Autoreloader",
|
||||
"AYUV",
|
||||
"battleresults",
|
||||
"bbox",
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { ComponentProps } from 'react';
|
||||
|
||||
export function GunAutoloaderIcon(props: ComponentProps<'svg'>) {
|
||||
return (
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M22.2 55H11V29.1692C11 17.4923 11.9314 13.634 16.6 9C21.2686 13.634 22.2 17.4923 22.2 29.1692V55Z"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M37.5999 55H26.3999V29.1692C26.3999 17.4923 27.3313 13.634 31.9999 9C36.6685 13.634 37.5999 17.4923 37.5999 29.1692V55Z"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M53.0003 55H41.8003V29.1692C41.8003 17.4923 42.7317 13.634 47.4003 9C52.0689 13.634 53.0003 17.4923 53.0003 29.1692V55Z"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { ComponentProps } from 'react';
|
||||
|
||||
export function GunAutoreloaderIcon(props: ComponentProps<'svg'>) {
|
||||
return (
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<g clipPath="url(#clip0_630_241)">
|
||||
<path
|
||||
d="M38 49H26V28.7846C26 19.6462 26.9979 16.6266 32 13C37.0021 16.6266 38 19.6462 38 28.7846V49Z"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M56.7296 23.5339L57.0556 11.9915L46.8965 17.4804L56.7296 23.5339ZM57.0909 41.3937C57.2968 40.8813 57.0483 40.2989 56.5358 40.093C56.0234 39.8871 55.441 40.1356 55.2351 40.648L57.0909 41.3937ZM49.8241 48.8241C40.2563 58.392 24.7437 58.392 15.1759 48.8241L13.7617 50.2383C24.1106 60.5872 40.8894 60.5872 51.2383 50.2383L49.8241 48.8241ZM15.1759 48.8241C5.60804 39.2563 5.60804 23.7437 15.1759 14.1759L13.7617 12.7617C3.41278 23.1106 3.41278 39.8894 13.7617 50.2383L15.1759 48.8241ZM15.1759 14.1759C24.7437 4.60805 40.2563 4.60805 49.8241 14.1759L51.2383 12.7617C40.8894 2.41278 24.1106 2.41278 13.7617 12.7617L15.1759 14.1759ZM49.8241 14.1759C50.4853 14.837 51.1005 15.5263 51.6699 16.2397L53.233 14.992C52.6172 14.2205 51.9523 13.4756 51.2383 12.7617L49.8241 14.1759ZM55.2351 40.648C54.0398 43.6229 52.2368 46.4114 49.8241 48.8241L51.2383 50.2383C53.8453 47.6314 55.7968 44.6143 57.0909 41.3937L55.2351 40.648Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_630_241">
|
||||
<rect width="64" height="64" fill="currentColor" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { ComponentProps } from 'react';
|
||||
|
||||
export function GunRegularIcon(props: ComponentProps<'svg'>) {
|
||||
return (
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M38.2 55H25V29.1692C25 17.4923 26.0977 13.634 31.6 9C37.1023 13.634 38.2 17.4923 38.2 29.1692V55Z"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -13,6 +13,9 @@ import { times } from 'lodash-es';
|
||||
import { $tankFilters, initialTankFilters } from '../../../stores/tankFilters';
|
||||
import { classIcons } from '../../ClassIcon';
|
||||
import { ExperimentIcon } from '../../ExperimentIcon';
|
||||
import { GunAutoloaderIcon } from '../../GunAutoloaderIcon';
|
||||
import { GunAutoreloaderIcon } from '../../GunAutoreloaderIcon';
|
||||
import { GunRegularIcon } from '../../GunRegularIcon';
|
||||
import { ResearchedIcon } from '../../ResearchedIcon';
|
||||
import { ScienceIcon } from '../../ScienceIcon';
|
||||
import { ScienceOffIcon } from '../../ScienceOffIcon';
|
||||
@@ -29,11 +32,11 @@ export function FilterControl({ compact }: FilterControlProps) {
|
||||
return (
|
||||
<Flex height="fit-content" gap="2" align="start" justify="center">
|
||||
<Flex
|
||||
direction={compact ? 'row' : { initial: 'row', sm: 'column' }}
|
||||
direction={compact ? 'row' : { initial: 'row', md: 'column' }}
|
||||
overflow="hidden"
|
||||
style={{ borderRadius: 'var(--radius-5)' }}
|
||||
>
|
||||
<Flex direction={compact ? 'column' : { sm: 'row', initial: 'column' }}>
|
||||
<Flex direction={compact ? 'column' : { md: 'row', initial: 'column' }}>
|
||||
{times(5, (index) => {
|
||||
const tier = index as Tier;
|
||||
const selected = tankFilters.tiers?.includes(tier);
|
||||
@@ -61,7 +64,7 @@ export function FilterControl({ compact }: FilterControlProps) {
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
<Flex direction={compact ? 'column' : { sm: 'row', initial: 'column' }}>
|
||||
<Flex direction={compact ? 'column' : { md: 'row', initial: 'column' }}>
|
||||
{times(5, (index) => {
|
||||
const tier = (index + 5) as Tier;
|
||||
const selected = tankFilters.tiers?.includes(tier);
|
||||
@@ -92,11 +95,11 @@ export function FilterControl({ compact }: FilterControlProps) {
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
direction={compact ? 'row' : { initial: 'row', sm: 'column' }}
|
||||
direction={compact ? 'row' : { initial: 'row', md: 'column' }}
|
||||
overflow="hidden"
|
||||
style={{ borderRadius: 'var(--radius-5)' }}
|
||||
>
|
||||
<Flex direction={compact ? 'column' : { sm: 'row', initial: 'column' }}>
|
||||
<Flex direction={compact ? 'column' : { md: 'row', initial: 'column' }}>
|
||||
{gameDefinitions.nations
|
||||
.slice(0, Math.ceil(gameDefinitions.nations.length / 2))
|
||||
.map((nation) => {
|
||||
@@ -131,7 +134,7 @@ export function FilterControl({ compact }: FilterControlProps) {
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
<Flex direction={compact ? 'column' : { sm: 'row', initial: 'column' }}>
|
||||
<Flex direction={compact ? 'column' : { md: 'row', initial: 'column' }}>
|
||||
{gameDefinitions.nations
|
||||
.slice(Math.ceil(gameDefinitions.nations.length / 2))
|
||||
.map((nation) => {
|
||||
@@ -172,7 +175,7 @@ export function FilterControl({ compact }: FilterControlProps) {
|
||||
<Flex
|
||||
overflow="hidden"
|
||||
style={{ borderRadius: 'var(--radius-full)' }}
|
||||
direction={compact ? 'column' : { sm: 'row', initial: 'column' }}
|
||||
direction={compact ? 'column' : { md: 'row', initial: 'column' }}
|
||||
>
|
||||
{TANK_CLASSES.map((tankClass) => {
|
||||
const Icon = classIcons[tankClass];
|
||||
@@ -208,7 +211,85 @@ export function FilterControl({ compact }: FilterControlProps) {
|
||||
<Flex
|
||||
overflow="hidden"
|
||||
style={{ borderRadius: 'var(--radius-full)' }}
|
||||
direction={compact ? 'column' : { sm: 'row', initial: 'column' }}
|
||||
direction={compact ? 'column' : { md: 'row', initial: 'column' }}
|
||||
>
|
||||
<IconButton
|
||||
variant={tankFilters.gunType.includes('regular') ? 'solid' : 'soft'}
|
||||
radius="none"
|
||||
color={tankFilters.gunType.includes('regular') ? undefined : 'gray'}
|
||||
highContrast
|
||||
onClick={() => {
|
||||
if (tankFilters.gunType.includes('regular')) {
|
||||
$tankFilters.setKey(
|
||||
'gunType',
|
||||
tankFilters.gunType.filter((t) => t !== 'regular'),
|
||||
);
|
||||
} else {
|
||||
$tankFilters.setKey('gunType', [
|
||||
...tankFilters.gunType,
|
||||
'regular',
|
||||
]);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<GunRegularIcon style={{ width: '1em', height: '1em' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
variant={
|
||||
tankFilters.gunType.includes('auto_loader') ? 'solid' : 'soft'
|
||||
}
|
||||
radius="none"
|
||||
color={
|
||||
tankFilters.gunType.includes('auto_loader') ? undefined : 'gray'
|
||||
}
|
||||
highContrast
|
||||
onClick={() => {
|
||||
if (tankFilters.gunType.includes('auto_loader')) {
|
||||
$tankFilters.setKey(
|
||||
'gunType',
|
||||
tankFilters.gunType.filter((t) => t !== 'auto_loader'),
|
||||
);
|
||||
} else {
|
||||
$tankFilters.setKey('gunType', [
|
||||
...tankFilters.gunType,
|
||||
'auto_loader',
|
||||
]);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<GunAutoloaderIcon style={{ width: '1em', height: '1em' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
variant={
|
||||
tankFilters.gunType.includes('auto_reloader') ? 'solid' : 'soft'
|
||||
}
|
||||
radius="none"
|
||||
color={
|
||||
tankFilters.gunType.includes('auto_reloader') ? undefined : 'gray'
|
||||
}
|
||||
highContrast
|
||||
onClick={() => {
|
||||
if (tankFilters.gunType.includes('auto_reloader')) {
|
||||
$tankFilters.setKey(
|
||||
'gunType',
|
||||
tankFilters.gunType.filter((t) => t !== 'auto_reloader'),
|
||||
);
|
||||
} else {
|
||||
$tankFilters.setKey('gunType', [
|
||||
...tankFilters.gunType,
|
||||
'auto_reloader',
|
||||
]);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<GunAutoreloaderIcon style={{ width: '1em', height: '1em' }} />
|
||||
</IconButton>
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
overflow="hidden"
|
||||
style={{ borderRadius: 'var(--radius-full)' }}
|
||||
direction={compact ? 'column' : { md: 'row', initial: 'column' }}
|
||||
>
|
||||
<IconButton
|
||||
variant={
|
||||
@@ -312,7 +393,7 @@ export function FilterControl({ compact }: FilterControlProps) {
|
||||
<Flex
|
||||
overflow="hidden"
|
||||
style={{ borderRadius: 'var(--radius-full)' }}
|
||||
direction={compact ? 'column' : { sm: 'row', initial: 'column' }}
|
||||
direction={compact ? 'column' : { md: 'row', initial: 'column' }}
|
||||
>
|
||||
<IconButton
|
||||
variant={tankFilters.testing === 'include' ? 'solid' : 'soft'}
|
||||
|
||||
@@ -9,6 +9,19 @@ export function filterTank(filters: TankFilters, tank: TankDefinition) {
|
||||
(filters.types.length === 0 || filters.types.includes(tank.type)) &&
|
||||
(filters.testing === 'include' ||
|
||||
(filters.testing === 'only' && tank.testing) ||
|
||||
(filters.testing === 'exclude' && !tank.testing))
|
||||
(filters.testing === 'exclude' && !tank.testing)) &&
|
||||
(filters.gunType.length === 0 ||
|
||||
(filters.gunType.includes('regular') &&
|
||||
tank.turrets.some((turret) =>
|
||||
turret.guns.some((gun) => gun.gun_type!.$case === 'regular'),
|
||||
)) ||
|
||||
(filters.gunType.includes('auto_loader') &&
|
||||
tank.turrets.some((turret) =>
|
||||
turret.guns.some((gun) => gun.gun_type!.$case === 'auto_loader'),
|
||||
)) ||
|
||||
(filters.gunType.includes('auto_reloader') &&
|
||||
tank.turrets.some((turret) =>
|
||||
turret.guns.some((gun) => gun.gun_type!.$case === 'auto_reloader'),
|
||||
)))
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
import type { TankClass, TankType, Tier } from '@blitzkit/core';
|
||||
import type { GunDefinition, TankClass, TankType, Tier } from '@blitzkit/core';
|
||||
import { map } from 'nanostores';
|
||||
|
||||
export type CaseType<T> = T extends {
|
||||
gun_type?: { $case: infer U; value: any };
|
||||
}
|
||||
? U
|
||||
: never;
|
||||
|
||||
export interface TankFilters {
|
||||
tiers: Tier[];
|
||||
nations: string[];
|
||||
@@ -9,6 +15,7 @@ export interface TankFilters {
|
||||
testing: 'include' | 'exclude' | 'only';
|
||||
search?: string;
|
||||
searching: boolean;
|
||||
gunType: CaseType<GunDefinition>[];
|
||||
}
|
||||
|
||||
export const initialTankFilters: TankFilters = {
|
||||
@@ -19,6 +26,7 @@ export const initialTankFilters: TankFilters = {
|
||||
testing: 'include',
|
||||
search: undefined,
|
||||
searching: false,
|
||||
gunType: [],
|
||||
};
|
||||
|
||||
export const $tankFilters = map<TankFilters>(initialTankFilters);
|
||||
Reference in new issue
Block a user