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)); +}