tank search

This commit is contained in:
tresabhi committed 2026-08-28 16:59:07 -05:00
1 parent 5477616917
commit 4a0fccc526
6 files changed
+54 -73

No files matched your search

+36 -23
View File
@@ -1,6 +1,6 @@
import { BlitzKitAPI } from "@blitzkit/core";
import { BlitzKitAPI } from "@blitzkit/core/src/blitzkit/api/base";
import locales from "@blitzkit/i18n/locales.json";
import { deburr } from "lodash-es";
import { deburr, times } from "lodash-es";
import { I18nString } from "../protos";
export async function fetchTankNames(api: BlitzKitAPI) {
@@ -12,40 +12,53 @@ export async function fetchTankNames(api: BlitzKitAPI) {
return await Promise.all(
tankDefinitionsArray.map(async (tank) => {
const searchableNameDeburr: I18nString = { locales: {} };
const name_deburr: I18nString = I18nString.create();
const camouflages_deburr: I18nString[] = [];
const camouflages = tank.camouflages.map(
(id) => camouflageDefinitions.camouflages[id].name!,
);
Object.entries(tank.name!).forEach(([key, value]) => {
searchableNameDeburr.locales[key] = deburr(value);
name_deburr.locales[key] = deburr(value);
});
camouflages.forEach((camouflage, index) => {
camouflages_deburr[index] = I18nString.create();
Object.entries(camouflage).forEach(([key, value]) => {
camouflages_deburr[index].locales[key] = deburr(value);
});
});
return {
id: tank.id,
name: tank.name,
searchableName: tank.name,
searchableNameDeburr,
camouflages: tank.camouflages
?.map((id) =>
locales.supported.map(
({ locale }) =>
camouflageDefinitions.camouflages[id]?.name!.locales[locale],
),
)
.flat()
.filter(Boolean)
.map(deburr)
.join(" "),
treeType: tank.type,
slug: tank.slug,
dev_name: tank.dev_name,
name: tank.name!,
name_deburr,
camouflages,
camouflages_deburr,
};
}),
);
}
export const SEARCH_KEYS = [
"id",
"slug",
"dev_name",
...locales.supported
.map(({ locale }) => [
`searchableName.locales.${locale}`,
`searchableNameDeburr.locales.${locale}`,
`name.locales.${locale}`,
`name_deburr.locales.${locale}`,
...times(8, (index) => [
`camouflages.${index}.locales.${locale}`,
`camouflages_deburr.${index}.locales.${locale}`,
]),
])
.flat(),
"camouflages",
.flat(2),
];
@@ -1,4 +1,5 @@
.recent {
margin-top: var(--space-4);
padding: var(--space-4);
background-color: var(--gray-a2);
@@ -1,5 +1,8 @@
import { useLocale } from "../../../hooks/useLocale";
import { TankFilters } from "../../../stores/tankFilters";
import { Flex } from "../../Flex";
import { Link } from "../../Link";
import { Text } from "../../Text";
interface NoResultsProps {
type?: "filters" | "search";
@@ -9,8 +12,8 @@ export function NoResults({ type = "filters" }: NoResultsProps) {
const { strings } = useLocale();
return (
<Flex flexGrow="1" align="center" justify="center">
<Text color="gray">
<Flex align="center" justify="center">
<Text lowContrast>
{strings.website.common.tank_search.no_tanks_found.body}{" "}
<Link
href="#"
@@ -73,9 +73,7 @@ export const TankSearch = memo<TankSearchProps>(
} else {
return Promise.resolve(
fuzzysort
.go(tankFilters.search, tankNames, {
keys: SEARCH_KEYS,
})
.go(tankFilters.search, tankNames, { keys: SEARCH_KEYS })
.map((result) => tankDefinitions.tanks[result.obj.id]),
);
}
@@ -437,7 +435,7 @@ export const TankSearch = memo<TankSearchProps>(
onSelect={onSelect}
/>
{!tankFilters.search && !tankFilters.searching && <TankSearchFilters />}
{!tankFilters.search && <TankSearchFilters />}
{!skeleton && !compact && <RecentlyViewedTanks />}
@@ -497,7 +495,7 @@ export const TankSearch = memo<TankSearchProps>(
</div>
)}
{!skeleton && !tankFilters.searching && (
{!skeleton && (
<>
{tanks.length > 0 && (
<TankCardWrapper>
@@ -530,19 +528,6 @@ export const TankSearch = memo<TankSearchProps>(
{tanks.length === 0 && <NoResults type="search" />}
</>
)}
{(skeleton || tankFilters.searching) && (
<TankCardWrapper>
{times(
Math.round(
skeleton ? DEFAULT_LOADED_CARDS : 10 + 10 * Math.random(),
),
(index) => (
<TankCardSkeleton key={index} />
),
)}
</TankCardWrapper>
)}
</Flex>
);
},
@@ -1,12 +1,10 @@
import type { TankDefinition } from "@blitzkit/core";
import { MagnifyingGlassIcon } from "@radix-ui/react-icons";
import { debounce } from "lodash-es";
import { type KeyboardEventHandler, useCallback, useRef } from "react";
import { useLocale } from "../../hooks/useLocale";
import { TankFilters } from "../../stores/tankFilters";
import type { MaybeSkeletonComponentProps } from "../../types/maybeSkeletonComponentProps";
import { Flex } from "../Flex";
import { Spinner } from "../Spinner";
import { Sort } from "../TankSearch/components/Sort";
import { TextField } from "../TextField";
@@ -22,36 +20,19 @@ export function TankSearchBar({
}: SearchBarProps) {
const { strings } = useLocale();
const search = TankFilters.use((state) => state.search);
const searching = TankFilters.use((state) => state.searching);
const input = useRef<HTMLInputElement>(null);
const performSearch = useCallback(
debounce(() => {
TankFilters.mutate((draft) => {
draft.searching = false;
});
if (!input.current) return;
const sanitized = input.current.value.trim();
TankFilters.mutate((draft) => {
draft.search = sanitized.length === 0 ? null : sanitized;
});
}, 500),
[],
);
const handleChange = useCallback(() => {
if (!searching) {
TankFilters.mutate((draft) => {
draft.searching = true;
});
}
if (!input.current) return;
performSearch();
}, [searching]);
const sanitized = input.current.value.trim();
TankFilters.mutate((draft) => {
draft.search = sanitized.length === 0 ? null : sanitized;
});
}, []);
const handleKeyDown = useCallback<KeyboardEventHandler>(
(event) => {
if (event.key !== "Enter" || !topResult || searching) return;
if (event.key !== "Enter" || !topResult) return;
event.preventDefault();
@@ -75,7 +56,7 @@ export function TankSearchBar({
onChange={handleChange}
onKeyDown={handleKeyDown}
>
{searching ? <Spinner /> : <MagnifyingGlassIcon />}
<MagnifyingGlassIcon />
</TextField>
<Sort />
@@ -18,7 +18,6 @@ export interface TankFilters {
classes: TankClass[];
types: TankType[];
search: string | null;
searching: boolean;
gunType: CaseType<GunDefinition>[];
shells: [ShellType | null, ShellType | null, ShellType | null];
consumables: number[];
@@ -38,7 +37,6 @@ export const TankFilters = new Varuna<TankFilters>({
classes: [],
types: [],
search: null,
searching: false,
gunType: [],
shells: [null, null, null],
consumables: [],