mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-28 04:59:50 +01:00
feat: new search results
This commit is contained in:
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
+22
-57
@@ -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>
|
||||||
))}
|
))}
|
||||||
Reference in new issue
Block a user