From 4c6369b8b4f629efbe8df0f4729b4c647e40a6bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com>
Date: Tue, 2 Jul 2024 19:19:15 -0500
Subject: [PATCH] feat: tank performance filters
---
.../tank-performance/components/Tanks.tsx | 12 +-
src/app/tools/tank-performance/page.tsx | 3 +
.../tankopedia/components/FilterControl.tsx | 2 +
src/app/tools/tankopedia/components/Sort.tsx | 120 +++++++++---------
.../tools/tankopedia/components/TankCard.tsx | 5 +-
.../components/TankSearch/index.tsx | 20 +--
.../tankopedia/components/TierFilter.tsx | 3 +-
src/stores/tankopediaFilters.ts | 9 --
src/stores/tankopediaSort.ts | 17 +++
9 files changed, 106 insertions(+), 85 deletions(-)
create mode 100644 src/stores/tankopediaSort.ts
diff --git a/src/app/tools/tank-performance/components/Tanks.tsx b/src/app/tools/tank-performance/components/Tanks.tsx
index 8b156a9b0..0f1d02ade 100644
--- a/src/app/tools/tank-performance/components/Tanks.tsx
+++ b/src/app/tools/tank-performance/components/Tanks.tsx
@@ -4,6 +4,8 @@ import { Table } from '@radix-ui/themes';
import { Suspense, use, useMemo } from 'react';
import { averageDefinitionsArray } from '../../../../core/blitzkit/averageDefinitions';
import { tankDefinitions } from '../../../../core/blitzkit/tankDefinitions';
+import { tankopediaFilterTank } from '../../../../core/blitzkit/tankopediaFilterTank';
+import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
import { useTankPerformanceSort } from '../../../../stores/tankPerformanceSort';
import { RowLoader } from './RowLoader';
import { TankRow } from './TankRow';
@@ -11,8 +13,9 @@ import { TankRow } from './TankRow';
export function Tanks() {
const awaitedTankDefinitions = use(tankDefinitions);
const awaitedAverageDefinitionsArray = use(averageDefinitionsArray);
+ const filters = useTankopediaFilters();
const sort = useTankPerformanceSort();
- const tankAverages = useMemo(() => {
+ const tanksSorted = useMemo(() => {
switch (sort.type) {
case 'accuracy':
return awaitedAverageDefinitionsArray.sort(
@@ -101,10 +104,15 @@ export function Tanks() {
);
}
}, [sort]);
+ const tanks = useMemo(() => {
+ return tanksSorted.filter((tank) =>
+ tankopediaFilterTank(filters, awaitedTankDefinitions[tank.id]),
+ );
+ }, [filters, tanksSorted]);
return (
- {tankAverages.map((averages) => {
+ {tanks.map((averages) => {
const tank = awaitedTankDefinitions[averages.id];
return (
}>
diff --git a/src/app/tools/tank-performance/page.tsx b/src/app/tools/tank-performance/page.tsx
index 5705d5ce9..1a12405fe 100644
--- a/src/app/tools/tank-performance/page.tsx
+++ b/src/app/tools/tank-performance/page.tsx
@@ -1,6 +1,7 @@
import { Flex, Table } from '@radix-ui/themes';
import { Suspense } from 'react';
import PageWrapper from '../../../components/PageWrapper';
+import { FilterControl } from '../tankopedia/components/FilterControl';
import { BodyLoader } from './components/BodyLoader';
import { Header } from './components/Header';
import { Info } from './components/Info';
@@ -11,6 +12,8 @@ export default function Page() {
+
+
diff --git a/src/app/tools/tankopedia/components/FilterControl.tsx b/src/app/tools/tankopedia/components/FilterControl.tsx
index fbe87c22d..68e498252 100644
--- a/src/app/tools/tankopedia/components/FilterControl.tsx
+++ b/src/app/tools/tankopedia/components/FilterControl.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import { ReloadIcon } from '@radix-ui/react-icons';
import { Box, Flex, IconButton, Text } from '@radix-ui/themes';
import { times } from 'lodash';
diff --git a/src/app/tools/tankopedia/components/Sort.tsx b/src/app/tools/tankopedia/components/Sort.tsx
index 00727a65f..7486beba6 100644
--- a/src/app/tools/tankopedia/components/Sort.tsx
+++ b/src/app/tools/tankopedia/components/Sort.tsx
@@ -2,12 +2,12 @@ import { CaretDownIcon } from '@radix-ui/react-icons';
import { Button, DropdownMenu } from '@radix-ui/themes';
import { TankopediaSortDirection } from '../../../../stores/tankopedia';
import {
- mutateTankopediaFilters,
- useTankopediaFilters,
-} from '../../../../stores/tankopediaFilters';
+ mutateTankopediaSort,
+ useTankopediaSort,
+} from '../../../../stores/tankopediaSort';
export function Sort() {
- const sort = useTankopediaFilters((state) => state.sort);
+ const sort = useTankopediaSort();
return (
@@ -22,8 +22,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'meta.none';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'meta.none';
});
}}
>
@@ -38,8 +38,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.dpm';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.dpm';
});
}}
>
@@ -48,8 +48,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.dpmPremium';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.dpmPremium';
});
}}
>
@@ -58,8 +58,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.reload';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.reload';
});
}}
>
@@ -68,8 +68,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.caliber';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.caliber';
});
}}
>
@@ -78,8 +78,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.standardPenetration';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.standardPenetration';
});
}}
>
@@ -88,8 +88,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.premiumPenetration';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.premiumPenetration';
});
}}
>
@@ -98,8 +98,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.damage';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.damage';
});
}}
>
@@ -108,8 +108,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.shellVelocity';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.shellVelocity';
});
}}
>
@@ -118,8 +118,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.aimTime';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.aimTime';
});
}}
>
@@ -128,8 +128,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.dispersionStill';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.dispersionStill';
});
}}
>
@@ -138,8 +138,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.dispersionMoving';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.dispersionMoving';
});
}}
>
@@ -148,8 +148,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.gunDepression';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.gunDepression';
});
}}
>
@@ -158,8 +158,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'fire.gunElevation';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'fire.gunElevation';
});
}}
>
@@ -174,8 +174,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'maneuverability.forwardsSpeed';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'maneuverability.forwardsSpeed';
});
}}
>
@@ -184,8 +184,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'maneuverability.backwardsSpeed';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'maneuverability.backwardsSpeed';
});
}}
>
@@ -194,8 +194,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'maneuverability.power';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'maneuverability.power';
});
}}
>
@@ -204,8 +204,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'maneuverability.powerToWeight';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'maneuverability.powerToWeight';
});
}}
>
@@ -214,8 +214,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'maneuverability.weight';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'maneuverability.weight';
});
}}
>
@@ -224,8 +224,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'maneuverability.traverseSpeed';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'maneuverability.traverseSpeed';
});
}}
>
@@ -240,8 +240,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'survivability.health';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'survivability.health';
});
}}
>
@@ -250,8 +250,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'survivability.viewRange';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'survivability.viewRange';
});
}}
>
@@ -260,8 +260,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'survivability.camouflageStill';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'survivability.camouflageStill';
});
}}
>
@@ -270,8 +270,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'survivability.camouflageMoving';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'survivability.camouflageMoving';
});
}}
>
@@ -280,8 +280,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'survivability.camouflageShooting';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'survivability.camouflageShooting';
});
}}
>
@@ -290,8 +290,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'survivability.volume';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'survivability.volume';
});
}}
>
@@ -300,8 +300,8 @@ export function Sort() {
{
- mutateTankopediaFilters((draft) => {
- draft.sort.by = 'survivability.length';
+ mutateTankopediaSort((draft) => {
+ draft.by = 'survivability.length';
});
}}
>
@@ -314,8 +314,8 @@ export function Sort() {
- mutateTankopediaFilters((draft) => {
- draft.sort.direction = value as TankopediaSortDirection;
+ mutateTankopediaSort((draft) => {
+ draft.direction = value as TankopediaSortDirection;
})
}
>
diff --git a/src/app/tools/tankopedia/components/TankCard.tsx b/src/app/tools/tankopedia/components/TankCard.tsx
index dd04a6252..9fb1082ad 100644
--- a/src/app/tools/tankopedia/components/TankCard.tsx
+++ b/src/app/tools/tankopedia/components/TankCard.tsx
@@ -12,7 +12,7 @@ import { resolveReload } from '../../../../core/blitzkit/resolveReload';
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
import { tankIcon } from '../../../../core/blitzkit/tankIcon';
import { unionBoundingBox } from '../../../../core/blitzkit/unionBoundingBox';
-import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
+import { useTankopediaSort } from '../../../../stores/tankopediaSort';
import * as styles from './TankCard.css';
interface TankCardProps {
@@ -23,8 +23,7 @@ interface TankCardProps {
export function TankCard({ tank, onSelect }: TankCardProps) {
const awaitedModelDefinitions = use(modelDefinitions);
const Icon = classIcons[tank.class];
- // const link = useRef(null);
- const sortBy = useTankopediaFilters((state) => state.sort.by);
+ const sortBy = useTankopediaSort((state) => state.by);
const discriminator = useMemo(() => {
if (sortBy.startsWith('meta')) return undefined;
diff --git a/src/app/tools/tankopedia/components/TankSearch/index.tsx b/src/app/tools/tankopedia/components/TankSearch/index.tsx
index 22f71b6a0..33f6665e4 100644
--- a/src/app/tools/tankopedia/components/TankSearch/index.tsx
+++ b/src/app/tools/tankopedia/components/TankSearch/index.tsx
@@ -22,6 +22,7 @@ import { unionBoundingBox } from '../../../../../core/blitzkit/unionBoundingBox'
import { useAdExempt } from '../../../../../hooks/useAdExempt';
import { SORT_NAMES, SORT_UNITS } from '../../../../../stores/tankopedia';
import { useTankopediaFilters } from '../../../../../stores/tankopediaFilters';
+import { useTankopediaSort } from '../../../../../stores/tankopediaSort';
import { FilterControl } from '../FilterControl';
import { NoResults } from '../NoResults';
import { SearchBar } from '../SearchBar';
@@ -45,6 +46,7 @@ export const TankSearch = memo(
const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
const awaitedTankNames = use(tankNames);
const filters = useTankopediaFilters();
+ const sort = useTankopediaSort();
const tanks = useMemo(() => {
if (filters.search === undefined) {
const filtered = awaitedTanksDefinitionsArray.filter((tank) =>
@@ -52,7 +54,7 @@ export const TankSearch = memo(
);
let sorted: TankDefinition[];
- switch (filters.sort.by) {
+ switch (sort.by) {
case 'meta.none':
sorted = filtered
.sort((a, b) => b.tier - a.tier)
@@ -362,9 +364,7 @@ export const TankSearch = memo(
break;
}
- return filters.sort.direction === 'ascending'
- ? sorted
- : sorted.reverse();
+ return sort.direction === 'ascending' ? sorted : sorted.reverse();
} else {
const searchedRaw = go(filters.search, awaitedTankNames, {
key: 'combined',
@@ -385,7 +385,7 @@ export const TankSearch = memo(
)}
- {(filters.sort.by !== 'meta.none' || onSelectAll) && (
+ {(sort.by !== 'meta.none' || onSelectAll) && (
(
align="center"
justify="center"
>
- {filters.sort.by !== 'meta.none' && (
+ {sort.by !== 'meta.none' && (
- Sorting by {SORT_NAMES[filters.sort.by]}
- {SORT_UNITS[filters.sort.by] === undefined
+ Sorting by {SORT_NAMES[sort.by]}
+ {SORT_UNITS[sort.by] === undefined
? ''
- : ` (${SORT_UNITS[filters.sort.by]})`}
- , {filters.sort.direction}
+ : ` (${SORT_UNITS[sort.by]})`}
+ , {sort.direction}
)}
diff --git a/src/app/tools/tankopedia/components/TierFilter.tsx b/src/app/tools/tankopedia/components/TierFilter.tsx
index 5398883b7..fcb7cefca 100644
--- a/src/app/tools/tankopedia/components/TierFilter.tsx
+++ b/src/app/tools/tankopedia/components/TierFilter.tsx
@@ -7,10 +7,11 @@ import {
mutateTankopediaFilters,
useTankopediaFilters,
} from '../../../../stores/tankopediaFilters';
+import { useTankopediaSort } from '../../../../stores/tankopediaSort';
export const TierFilter = memo(() => {
const tierFilter = useTankopediaFilters((state) => state.tier);
- const sort = useTankopediaFilters((state) => state.sort);
+ const sort = useTankopediaSort();
const search = useTankopediaFilters((state) => state.search);
if (sort.by !== 'meta.none' || search) return null;
diff --git a/src/stores/tankopediaFilters.ts b/src/stores/tankopediaFilters.ts
index 0959fb6b8..fd1e6e70a 100644
--- a/src/stores/tankopediaFilters.ts
+++ b/src/stores/tankopediaFilters.ts
@@ -2,7 +2,6 @@ import { produce } from 'immer';
import { create } from 'zustand';
import { TankClass, TreeType } from '../components/Tanks';
import { Tier } from '../core/blitzkit/tankDefinitions';
-import { TankopediaSortBy, TankopediaSortDirection } from './tankopedia';
export interface TankopediaFilters {
tier?: Tier;
@@ -11,19 +10,11 @@ export interface TankopediaFilters {
type?: TreeType;
testing: 'include' | 'exclude' | 'only';
search?: string;
- sort: {
- by: TankopediaSortBy;
- direction: TankopediaSortDirection;
- };
searching: boolean;
}
export const useTankopediaFilters = create()(() => ({
testing: 'include',
- sort: {
- by: 'meta.none',
- direction: 'descending',
- },
searching: false,
}));
diff --git a/src/stores/tankopediaSort.ts b/src/stores/tankopediaSort.ts
new file mode 100644
index 000000000..b7005e02b
--- /dev/null
+++ b/src/stores/tankopediaSort.ts
@@ -0,0 +1,17 @@
+import { produce } from 'immer';
+import { create } from 'zustand';
+import { TankopediaSortBy, TankopediaSortDirection } from './tankopedia';
+
+export interface TankopediaSort {
+ by: TankopediaSortBy;
+ direction: TankopediaSortDirection;
+}
+
+export const useTankopediaSort = create()(() => ({
+ by: 'meta.none',
+ direction: 'descending',
+}));
+
+export function mutateTankopediaSort(recipe: (draft: TankopediaSort) => void) {
+ useTankopediaSort.setState(produce(recipe));
+}