diff --git a/src/app/tools/tankopedia/components/FilterControl.tsx b/src/app/tools/tankopedia/components/FilterControl.tsx index 4736bd3f6..1b36e3e01 100644 --- a/src/app/tools/tankopedia/components/FilterControl.tsx +++ b/src/app/tools/tankopedia/components/FilterControl.tsx @@ -1,10 +1,9 @@ -import { TrashIcon } from '@radix-ui/react-icons'; -import { Box, Button, Flex, IconButton, Text } from '@radix-ui/themes'; +import { ReloadIcon } from '@radix-ui/react-icons'; +import { Box, Flex, IconButton, Text } from '@radix-ui/themes'; import { times } from 'lodash'; import { use } from 'react'; import { classIcons } from '../../../../components/ClassIcon'; import { ExperimentIcon } from '../../../../components/ExperimentIcon'; -import { NAVBAR_HEIGHT } from '../../../../components/Navbar'; import { ResearchedIcon } from '../../../../components/ResearchedIcon'; import { ScienceIcon } from '../../../../components/ScienceIcon'; import { ScienceOffIcon } from '../../../../components/ScienceOffIcon'; @@ -23,19 +22,11 @@ export function FilterControl() { const filters = useTankopediaFilters(); return ( - + {times(5, (index) => { @@ -51,7 +42,7 @@ export function FilterControl() { highContrast onClick={() => mutateTankopediaFilters((draft) => { - draft.tier = draft.tier === tier ? undefined : tier; + draft.tier = tier; }) } > @@ -74,7 +65,7 @@ export function FilterControl() { highContrast onClick={() => mutateTankopediaFilters((draft) => { - draft.tier = draft.tier === tier ? undefined : tier; + draft.tier = tier; }) } > @@ -88,7 +79,7 @@ export function FilterControl() { {awaitedGameDefinitions.nations @@ -227,7 +218,7 @@ export function FilterControl() { } > @@ -287,10 +278,9 @@ export function FilterControl() { - + useTankopediaFilters.setState( useTankopediaFilters.getInitialState(), @@ -298,23 +288,9 @@ export function FilterControl() { ) } > - + - - - ); } diff --git a/src/app/tools/tankopedia/components/Results.tsx b/src/app/tools/tankopedia/components/Results.tsx index 52affb9af..7285b3bef 100644 --- a/src/app/tools/tankopedia/components/Results.tsx +++ b/src/app/tools/tankopedia/components/Results.tsx @@ -1,8 +1,6 @@ import { Callout, Flex } from '@radix-ui/themes'; import { go } from 'fuzzysort'; -import { range } from 'lodash'; import { memo, use, useMemo } from 'react'; -import { Vector2Tuple } from 'three'; import { ExperimentIcon } from '../../../../components/ExperimentIcon'; import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration'; import { modelDefinitions } from '../../../../core/blitzkit/modelDefinitions'; @@ -11,13 +9,13 @@ import { resolveDpm } from '../../../../core/blitzkit/resolveDpm'; import { resolveReload } from '../../../../core/blitzkit/resolveReload'; import { TankDefinition, - Tier, tankDefinitions, tankNames, tanksDefinitionsArray, } from '../../../../core/blitzkit/tankDefinitions'; import { unionBoundingBox } from '../../../../core/blitzkit/unionBoundingBox'; import { useTankopediaFilters } from '../../../../stores/tankopediaFilters'; +import { FilterControl } from './FilterControl'; import { SearchBar } from './SearchBar'; import { TankCard } from './TankCard'; import { TankCardWrapper } from './TankCardWrapper'; @@ -30,10 +28,14 @@ export const Results = memo(() => { const awaitedTankNames = use(tankNames); const testing = useTankopediaFilters((state) => state.testing); const search = useTankopediaFilters((state) => state.search); + const tier = useTankopediaFilters((state) => state.tier); const sort = useTankopediaFilters((state) => state.sort); const searchedTanks = useMemo(() => { if (search !== undefined) { - const searchedRaw = go(search, awaitedTankNames, { key: 'combined' }); + const searchedRaw = go(search, awaitedTankNames, { + key: 'combined', + limit: 25, + }); const searchedTanks = searchedRaw.map( (result) => awaitedTankDefinitions[result.obj.id], ); @@ -45,10 +47,6 @@ export const Results = memo(() => { let sorted: TankDefinition[]; switch (sort.by) { - case 'meta.name': - sorted = filtered.sort((a, b) => a.name?.localeCompare(b.name)); - break; - case 'survivability.health': { sorted = filtered.sort((a, b) => { const aHealth = a.health + a.turrets.at(-1)!.health; @@ -332,25 +330,23 @@ export const Results = memo(() => { + {!search && } + {testing === 'only' && ( - - - - - - Tanks in testing are subject to change and many not represent the - final product. - - + + + + + + + Tanks in testing are subject to change and many not represent the + final product. + + + )} - {!search && - sort.by === 'meta.tier' && - range( - ...(sort.direction === 'descending' - ? ([10, 0] as Vector2Tuple) - : ([1, 11] as Vector2Tuple)), - ).map((tier) => )} + {!search && sort.by === 'meta.tier' && } {(search || sort.by !== 'meta.tier') && ( diff --git a/src/app/tools/tankopedia/components/SearchBar.tsx b/src/app/tools/tankopedia/components/SearchBar.tsx index d7cf815b3..0deb97b33 100644 --- a/src/app/tools/tankopedia/components/SearchBar.tsx +++ b/src/app/tools/tankopedia/components/SearchBar.tsx @@ -45,31 +45,32 @@ export function SearchBar({ topResult }: SearchBarProps) { ); return ( - - - - {searching ? : } - - - {topResult && ( + + + - - - + {searching ? : } - )} - - + {topResult && ( + + + + + + )} + + + + ); } diff --git a/src/app/tools/tankopedia/components/Sort.tsx b/src/app/tools/tankopedia/components/Sort.tsx index 3041a8929..c7e26f825 100644 --- a/src/app/tools/tankopedia/components/Sort.tsx +++ b/src/app/tools/tankopedia/components/Sort.tsx @@ -12,7 +12,7 @@ export function Sort() { return ( - diff --git a/src/app/tools/tankopedia/components/TankCard.tsx b/src/app/tools/tankopedia/components/TankCard.tsx index ddd9282a5..d16aba86c 100644 --- a/src/app/tools/tankopedia/components/TankCard.tsx +++ b/src/app/tools/tankopedia/components/TankCard.tsx @@ -1,13 +1,10 @@ import { Flex, Text } from '@radix-ui/themes'; import { Icon } from '@radix-ui/themes/dist/cjs/components/callout'; import { assignInlineVars } from '@vanilla-extract/dynamic'; -import { useEffect, useRef } from 'react'; import { Link } from '../../../../components/Link'; import { asset } from '../../../../core/blitzkit/asset'; import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions'; import { tankIcon } from '../../../../core/blitzkit/tankIcon'; -import { tankopediaFilterTank } from '../../../../core/blitzkit/tankopediaFilterTank'; -import { useTankopediaFilters } from '../../../../stores/tankopediaFilters'; import * as styles from './TankCard.css'; interface TankCardProps { @@ -17,7 +14,7 @@ interface TankCardProps { export function TankCard({ tank }: TankCardProps) { // const awaitedModelDefinitions = use(modelDefinitions); // const Icon = classIcons[tank.class]; - const link = useRef(null); + // const link = useRef(null); // const sortBy = useTankopediaFilters((state) => state.sort.by); // const discriminator = useMemo(() => { // if (sortBy.startsWith('meta')) return undefined; @@ -46,20 +43,20 @@ export function TankCard({ tank }: TankCardProps) { // } // }, [sortBy]); - useEffect(() => { - const unsubscribe = useTankopediaFilters.subscribe((filters) => { - if (!link.current) return; + // useEffect(() => { + // const unsubscribe = useTankopediaFilters.subscribe((filters) => { + // if (!link.current) return; - const visible = tankopediaFilterTank(filters, tank); - link.current.style.display = visible ? 'flex' : 'none'; - }); + // const visible = tankopediaFilterTank(filters, tank); + // link.current.style.display = visible ? 'flex' : 'none'; + // }); - return unsubscribe; - }, []); + // return unsubscribe; + // }, []); return ( { const awaitedGameDefinitions = use(gameDefinitions); const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray); - const container = useRef(null); + const filters = useTankopediaFilters(); const tanks = useMemo( () => awaitedTanksDefinitionsArray - .filter((tank) => tank.tier === tier) + .filter((tank) => tankopediaFilterTank(filters, tank)) .sort( (a, b) => treeTypeOrder.indexOf(a.treeType) - @@ -40,41 +40,38 @@ export const TierCard = memo( awaitedGameDefinitions.nations.indexOf(a.nation) - awaitedGameDefinitions.nations.indexOf(b.nation), ), - [tier], + [tier, filters], ); - useEffect(() => { - const unsubscribe = useTankopediaFilters.subscribe((filters) => { - if (!container.current) return; - - const visible = tanks.some((tank) => - tankopediaFilterTank(filters, tank), - ); - container.current.style.display = visible ? 'flex' : 'none'; - }); - - return unsubscribe; - }, []); + if (tanks.length === 0) + return ( + + + No tanks found.{' '} + + useTankopediaFilters.setState( + useTankopediaFilters.getInitialState(), + true, + ) + } + > + Try clearing filters + + . + + + ); return ( - - - Tier {TIER_ROMAN_NUMERALS[tier]} - - - - - {tanks.map((tank) => ( - - ))} - - + + {tanks.map((tank) => ( + + ))} + ); }, (prev, next) => prev.tier === next.tier, diff --git a/src/app/tools/tankopedia/components/TierFilter.tsx b/src/app/tools/tankopedia/components/TierFilter.tsx new file mode 100644 index 000000000..3123a209c --- /dev/null +++ b/src/app/tools/tankopedia/components/TierFilter.tsx @@ -0,0 +1,49 @@ +import { Flex, IconButton, Text } from '@radix-ui/themes'; +import { times } from 'lodash'; +import { memo } from 'react'; +import { Tier } from '../../../../core/blitzkit/tankDefinitions'; +import { TIER_ROMAN_NUMERALS } from '../../../../core/blitzkit/tankDefinitions/constants'; +import { + mutateTankopediaFilters, + useTankopediaFilters, +} from '../../../../stores/tankopediaFilters'; + +export const TierFilter = memo(() => { + const tierFilter = useTankopediaFilters((state) => state.tier); + const sort = useTankopediaFilters((state) => state.sort); + const search = useTankopediaFilters((state) => state.search); + + if (sort.by !== 'meta.tier' || search) return null; + + return ( + + + {times(10, (index) => { + const tier = (10 - index) as Tier; + const selected = tierFilter === tier; + + return ( + + mutateTankopediaFilters((draft) => { + draft.tier = tier; + }) + } + > + {TIER_ROMAN_NUMERALS[tier]} + + ); + })} + + + ); +}); diff --git a/src/app/tools/tankopedia/page.tsx b/src/app/tools/tankopedia/page.tsx index 5d240ef88..76231debb 100644 --- a/src/app/tools/tankopedia/page.tsx +++ b/src/app/tools/tankopedia/page.tsx @@ -2,14 +2,18 @@ import { Flex } from '@radix-ui/themes'; import PageWrapper from '../../../components/PageWrapper'; -import { FilterControl } from './components/FilterControl'; import { Results } from './components/Results'; export default function Page() { return ( - - - + + + {/* */} diff --git a/src/stores/tankopedia.ts b/src/stores/tankopedia.ts index 44a1d4971..fb70c111b 100644 --- a/src/stores/tankopedia.ts +++ b/src/stores/tankopedia.ts @@ -107,7 +107,6 @@ export type ArmorPiercingLayer = export const SORT_NAMES = { 'meta.tier': 'tier', - 'meta.name': 'name', 'survivability.health': 'health', 'survivability.viewRange': 'view range', 'survivability.camouflageStill': 'camouflage still', diff --git a/src/stores/tankopediaFilters.ts b/src/stores/tankopediaFilters.ts index e9c5a91bf..fb1c4a154 100644 --- a/src/stores/tankopediaFilters.ts +++ b/src/stores/tankopediaFilters.ts @@ -5,7 +5,7 @@ import { Tier } from '../core/blitzkit/tankDefinitions'; import { TankopediaSortBy, TankopediaSortDirection } from './tankopedia'; export interface TankopediaFilters { - tier?: Tier; + tier: Tier; nation?: string; class?: TankClass; type?: TreeType; @@ -23,6 +23,7 @@ export const useTankopediaFilters = create()(() => ({ by: 'meta.tier', direction: 'descending', }, + tier: 10, })); export function mutateTankopediaFilters(