feat: new search results

This commit is contained in:
TrèsAbhi committed 2024-01-16 14:02:50 -06:00
1 parent 1c64305678
commit db0c4a1d71
2 files changed
+75 -57

No files matched your search

@@ -0,0 +1,53 @@
import { Button, Flex, Text } from '@radix-ui/themes';
import { use } from 'react';
import { SmallTankIcon } from '../../../../../../../components/SmallTankIcon';
import {
TIER_ROMAN_NUMERALS,
tankDefinitions,
} from '../../../../../../../core/blitzkrieg/tankDefinitions';
interface SearchResultsProps {
ids: number[];
}
export function SearchResults({ ids }: SearchResultsProps) {
const awaitedTankDefinitions = use(tankDefinitions);
return (
<Flex justify="center">
<Flex direction="column" gap="2" align="start">
{ids.map((id) => {
const tank = awaitedTankDefinitions[id];
return (
<Button key={id} variant="ghost" style={{ width: '100%' }}>
<Flex gap="2" align="start" style={{ width: '100%' }}>
<Text align="right" color="gray" style={{ width: 24 }}>
{TIER_ROMAN_NUMERALS[tank.tier]}
</Text>
<Text color={tank.tree_type === 'collector' ? 'blue' : 'amber'}>
<Flex gap="2" align="center">
<SmallTankIcon id={tank.id} size={16} />
<div
style={{
display: 'block',
color:
tank.tree_type === 'researchable'
? 'white'
: undefined,
}}
>
{tank.name}
</div>
</Flex>
</Text>
</Flex>
</Button>
);
})}
</Flex>
</Flex>
);
}
@@ -19,15 +19,15 @@ import { go } from 'fuzzysort';
import { produce } from 'immer'; import { produce } from 'immer';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { Dispatch, SetStateAction, use, useRef, useState } from 'react'; import { Dispatch, SetStateAction, use, useRef, useState } from 'react';
import { ModuleButton } from '../../../../../components/ModuleButton'; import { ModuleButton } from '../../../../../../components/ModuleButton';
import { SmallTankIcon } from '../../../../../components/SmallTankIcon'; import { SmallTankIcon } from '../../../../../../components/SmallTankIcon';
import { import {
SHELL_NAMES, SHELL_NAMES,
tankDefinitions,
tankNamesDiacritics, tankNamesDiacritics,
} from '../../../../../core/blitzkrieg/tankDefinitions'; } from '../../../../../../core/blitzkrieg/tankDefinitions';
import { useTankopedia } from '../../../../../stores/tankopedia'; import { useTankopedia } from '../../../../../../stores/tankopedia';
import { Duel } from '../page'; import { Duel } from '../../page';
import { SearchResults } from './components/SearchResults';
interface AntagonistBarProps { interface AntagonistBarProps {
duel: Duel; duel: Duel;
@@ -38,12 +38,14 @@ export function AntagonistBar({
duel: { antagonist }, duel: { antagonist },
setDuel, setDuel,
}: AntagonistBarProps) { }: AntagonistBarProps) {
const awaitedTankDefinitions = use(tankDefinitions);
const mode = useTankopedia((state) => state.mode); const mode = useTankopedia((state) => state.mode);
const awaitedTankNamesDiacritics = use(tankNamesDiacritics); const awaitedTankNamesDiacritics = use(tankNamesDiacritics);
const [tab, setTab] = useState('search'); const [tab, setTab] = useState('search');
const searchInput = useRef<HTMLInputElement>(null); const searchInput = useRef<HTMLInputElement>(null);
const [searchResults, setSearchResults] = useState<number[]>([]); const [searchResults, setSearchResults] = useState<number[]>([]);
const chunkSize = window.innerWidth > 512 ? 8 : Infinity;
const firstChunk = searchResults.slice(0, chunkSize);
const secondChunk = searchResults.slice(chunkSize);
if (mode !== 'armor') return null; if (mode !== 'armor') return null;
@@ -127,62 +129,25 @@ export function AntagonistBar({
go( go(
searchInput.current!.value, searchInput.current!.value,
awaitedTankNamesDiacritics, awaitedTankNamesDiacritics,
{ key: 'combined', limit: 8 }, { key: 'combined', limit: 16 },
).map((item) => item.obj.id), ).map((item) => item.obj.id),
); );
}, 500)} }, 500)}
/> />
</TextField.Root> </TextField.Root>
<Flex direction="column" gap="2"> <div
{(searchResults.length > 0 || style={{
searchInput.current?.value) && ( display: 'flex',
<Flex direction="column" gap="2"> width: '100%',
{searchResults justifyContent: 'space-around',
.map((id) => awaitedTankDefinitions[id]) }}
.map((tank) => ( >
<Button <SearchResults ids={firstChunk} />
color={ {secondChunk.length > 0 && (
tank.tree_type === 'researchable' <SearchResults ids={secondChunk} />
? 'gray'
: tank.tree_type === 'premium'
? 'amber'
: 'blue'
}
key={tank.id}
variant="ghost"
onClick={() => {
setDuel(
produce<Duel>((draft) => {
draft.antagonist.tank = tank;
draft.antagonist.turret =
tank.turrets.at(-1)!;
draft.antagonist.gun =
draft.antagonist.turret.guns.at(-1)!;
draft.antagonist.shell =
draft.antagonist.gun.shells[0];
}),
);
setSearchResults([]);
searchInput.current!.value = '';
setTab('configure');
}}
>
{tank.name}
</Button>
))}
{searchResults.length === 0 &&
(searchInput.current
? searchInput.current.value.length > 0
: false) && (
<Button disabled variant="ghost">
No search results
</Button>
)}
</Flex>
)} )}
</Flex> </div>
</Flex> </Flex>
</Tabs.Content> </Tabs.Content>
@@ -265,7 +230,7 @@ export function AntagonistBar({
<ul> <ul>
{antagonist.gun.shells.map((shell) => ( {antagonist.gun.shells.map((shell) => (
<li key={shell.id}> <li key={shell.id}>
{SHELL_NAMES[shell.type]}:{' '} {SHELL_NAMES[shell.type]}:
<b>{shell.damage.armor} HP</b> <b>{shell.damage.armor} HP</b>
</li> </li>
))} ))}