From b965893bfc4279fbd4034e585dfbda072635b326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 6 Jul 2024 20:07:46 -0500 Subject: [PATCH] feat: transition to next safe zustand --- bun.lockb | Bin 385308 -> 385308 bytes .../tank-performance/components/RowLoader.tsx | 3 +- .../tank-performance/components/Tanks.tsx | 2 +- src/app/tools/tank-performance/page.tsx | 13 ++-- .../tankopedia/components/FilterControl.tsx | 14 +++- .../tankopedia/components/TierFilter.tsx | 11 ++- src/app/tools/tankopedia/page.tsx | 11 ++- src/stores/tankFilters.ts | 27 ------- src/stores/tankFilters.tsx | 73 ++++++++++++++++++ 9 files changed, 109 insertions(+), 45 deletions(-) delete mode 100644 src/stores/tankFilters.ts create mode 100644 src/stores/tankFilters.tsx diff --git a/bun.lockb b/bun.lockb index 77df4ca1b8517f3965fdbb35cd343c653b7014c1..509c67288820579c1cd8c9b587b4acb38458ea85 100644 GIT binary patch delta 27 jcmbPpNPNyA@rD-07N#xC!fzQ(+eO|oZx?yX!tn(Fn3D>o delta 27 jcmbPpNPNyA@rD-07N#xC!fzQ3+eO|oZx?yX!tn(Fm}d&2 diff --git a/src/app/tools/tank-performance/components/RowLoader.tsx b/src/app/tools/tank-performance/components/RowLoader.tsx index 41e5299b2..e35b0c295 100644 --- a/src/app/tools/tank-performance/components/RowLoader.tsx +++ b/src/app/tools/tank-performance/components/RowLoader.tsx @@ -1,5 +1,6 @@ import { Skeleton, Table } from '@radix-ui/themes'; import { times } from 'lodash'; +import { tankPerformanceSortTypeNamesArray } from '../../../../stores/tankPerformanceSort'; export function RowLoader() { return ( @@ -8,7 +9,7 @@ export function RowLoader() { - {times(13, (index) => ( + {times(tankPerformanceSortTypeNamesArray.length, (index) => ( diff --git a/src/app/tools/tank-performance/components/Tanks.tsx b/src/app/tools/tank-performance/components/Tanks.tsx index 547a15c41..293874b36 100644 --- a/src/app/tools/tank-performance/components/Tanks.tsx +++ b/src/app/tools/tank-performance/components/Tanks.tsx @@ -108,7 +108,7 @@ export function Tanks() { return tanksSorted.filter((tank) => filterTank(filters, awaitedTankDefinitions[tank.id]), ); - }, [filters, tanksSorted]); + }, [filters, tanksSorted, sort]); return ( diff --git a/src/app/tools/tank-performance/page.tsx b/src/app/tools/tank-performance/page.tsx index 859dfe7b8..108dbb10c 100644 --- a/src/app/tools/tank-performance/page.tsx +++ b/src/app/tools/tank-performance/page.tsx @@ -1,14 +1,17 @@ import PageWrapper from '../../../components/PageWrapper'; +import { TankFiltersProvider } from '../../../stores/tankFilters'; import { FilterControl } from '../tankopedia/components/FilterControl'; import { Info } from './components/Info'; import { TankTable } from './components/Table'; export default function Page() { return ( - - - - - + + + + + + + ); } diff --git a/src/app/tools/tankopedia/components/FilterControl.tsx b/src/app/tools/tankopedia/components/FilterControl.tsx index ba79cbb53..67086750a 100644 --- a/src/app/tools/tankopedia/components/FilterControl.tsx +++ b/src/app/tools/tankopedia/components/FilterControl.tsx @@ -15,8 +15,9 @@ import { gameDefinitions } from '../../../../core/blitzkit/gameDefinitions'; import { Tier } from '../../../../core/blitzkit/tankDefinitions'; import { TIER_ROMAN_NUMERALS } from '../../../../core/blitzkit/tankDefinitions/constants'; import { - mutateTankFilters, useTankFilters, + useTankFiltersContext, + useTankFiltersMutation, } from '../../../../stores/tankFilters'; interface FilterControlProps { @@ -26,6 +27,8 @@ interface FilterControlProps { export function FilterControl({ compact }: FilterControlProps) { const awaitedGameDefinitions = use(gameDefinitions); const filters = useTankFilters(); + const mutateTankFilters = useTankFiltersMutation(); + const tankFiltersContext = useTankFiltersContext(); return ( @@ -321,9 +324,12 @@ export function FilterControl({ compact }: FilterControlProps) { - useTankFilters.setState(useTankFilters.getInitialState(), true) - } + onClick={() => { + tankFiltersContext.setState( + tankFiltersContext.getInitialState(), + true, + ); + }} > diff --git a/src/app/tools/tankopedia/components/TierFilter.tsx b/src/app/tools/tankopedia/components/TierFilter.tsx index f13898604..074826494 100644 --- a/src/app/tools/tankopedia/components/TierFilter.tsx +++ b/src/app/tools/tankopedia/components/TierFilter.tsx @@ -4,8 +4,8 @@ import { memo } from 'react'; import { Tier } from '../../../../core/blitzkit/tankDefinitions'; import { TIER_ROMAN_NUMERALS } from '../../../../core/blitzkit/tankDefinitions/constants'; import { - mutateTankFilters, useTankFilters, + useTankFiltersMutation, } from '../../../../stores/tankFilters'; import { useTankopediaSort } from '../../../../stores/tankopediaSort'; @@ -13,6 +13,7 @@ export const TierFilter = memo(() => { const tierFilter = useTankFilters((state) => state.tiers); const sort = useTankopediaSort(); const search = useTankFilters((state) => state.search); + const mutateTankFilters = useTankFiltersMutation(); if (sort.by !== 'meta.none' || search) return null; @@ -25,7 +26,7 @@ export const TierFilter = memo(() => { > {times(10, (index) => { const tier = (10 - index) as Tier; - const selected = tierFilter === tier; + const selected = tierFilter.includes(tier); return ( { highContrast onClick={() => mutateTankFilters((draft) => { - draft.tiers = tier; + if (draft.tiers?.includes(tier)) { + draft.tiers = draft.tiers?.filter((t) => t !== tier); + } else { + draft.tiers = [...(draft.tiers ?? []), tier]; + } }) } > diff --git a/src/app/tools/tankopedia/page.tsx b/src/app/tools/tankopedia/page.tsx index 65732580d..5647d9edb 100644 --- a/src/app/tools/tankopedia/page.tsx +++ b/src/app/tools/tankopedia/page.tsx @@ -3,15 +3,18 @@ import { AdMidSectionResponsive } from '../../../components/AdMidSectionResponsive'; import PageWrapper from '../../../components/PageWrapper'; import { useAdExempt } from '../../../hooks/useAdExempt'; +import { TankFiltersProvider } from '../../../stores/tankFilters'; import { TankSearch } from './components/TankSearch'; export default function Page() { const exempt = useAdExempt(); return ( - - - {!exempt && } - + + + + {!exempt && } + + ); } diff --git a/src/stores/tankFilters.ts b/src/stores/tankFilters.ts deleted file mode 100644 index 586c2f228..000000000 --- a/src/stores/tankFilters.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { produce } from 'immer'; -import { create } from 'zustand'; -import { TankClass, TreeType } from '../components/Tanks'; -import { Tier } from '../core/blitzkit/tankDefinitions'; - -export interface TankFilters { - tiers: Tier[]; - nations: string[]; - classes: TankClass[]; - types: TreeType[]; - testing: 'include' | 'exclude' | 'only'; - search?: string; - searching: boolean; -} - -export const useTankFilters = create()(() => ({ - testing: 'include', - searching: false, - classes: [], - nations: [], - tiers: [], - types: [], -})); - -export function mutateTankFilters(recipe: (draft: TankFilters) => void) { - useTankFilters.setState(produce(recipe)); -} diff --git a/src/stores/tankFilters.tsx b/src/stores/tankFilters.tsx new file mode 100644 index 000000000..c368391d7 --- /dev/null +++ b/src/stores/tankFilters.tsx @@ -0,0 +1,73 @@ +'use client'; + +import { produce } from 'immer'; +import { createContext, ReactNode, useContext, useRef } from 'react'; +import { createStore, StoreApi, useStore } from 'zustand'; +import { TankClass, TreeType } from '../components/Tanks'; +import { Tier } from '../core/blitzkit/tankDefinitions'; + +export interface TankFilters { + tiers: Tier[]; + nations: string[]; + classes: TankClass[]; + types: TreeType[]; + testing: 'include' | 'exclude' | 'only'; + search?: string; + searching: boolean; +} + +export const tankFiltersInitialState: TankFilters = { + testing: 'include', + searching: false, + classes: [], + nations: [], + tiers: [], + types: [], +}; + +const createTankFiltersStore = ( + initialState: TankFilters = tankFiltersInitialState, +) => createStore()(() => ({ ...initialState })); + +const TankFiltersContext = createContext | undefined>( + undefined, +); + +interface TankFiltersProviderProps { + children: ReactNode; +} + +export function TankFiltersProvider({ children }: TankFiltersProviderProps) { + const storeRef = useRef>(); + if (!storeRef.current) storeRef.current = createTankFiltersStore(); + + return ( + + {children} + + ); +} + +export function useTankFiltersContext() { + const context = useContext(TankFiltersContext); + if (!context) { + throw new Error('useTankFilters must be used within TankFiltersContext'); + } + return context; +} + +export function useTankFilters( + selector: (store: TankFilters) => Type = (store) => store as Type, +): Type { + const counterStoreContext = useTankFiltersContext(); + + return useStore(counterStoreContext, selector); +} + +export function useTankFiltersMutation() { + const counterStoreContext = useTankFiltersContext(); + + return function (recipe: (draft: TankFilters) => void) { + counterStoreContext.setState(produce(recipe)); + }; +}