2024-06-21 19:04:34 -05:00
|
|
|
import { CaretRightIcon, MagnifyingGlassIcon } from '@radix-ui/react-icons';
|
2024-06-22 16:39:31 -05:00
|
|
|
import { Button, Flex, Spinner, TextField } from '@radix-ui/themes';
|
2024-06-21 19:04:34 -05:00
|
|
|
import { debounce } from 'lodash';
|
|
|
|
|
import { useRouter } from 'next/navigation';
|
2024-06-24 14:10:23 -05:00
|
|
|
import { KeyboardEventHandler, useCallback, useRef } from 'react';
|
2024-06-21 19:04:34 -05:00
|
|
|
import { Link } from '../../../../components/Link';
|
|
|
|
|
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
|
|
|
|
|
import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
|
2024-06-22 16:39:31 -05:00
|
|
|
import { Sort } from './Sort';
|
2024-06-21 19:04:34 -05:00
|
|
|
|
|
|
|
|
interface SearchBarProps {
|
|
|
|
|
topResult?: TankDefinition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function SearchBar({ topResult }: SearchBarProps) {
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const input = useRef<HTMLInputElement>(null);
|
2024-06-24 14:10:23 -05:00
|
|
|
const searching = useTankopediaFilters((state) => state.searching);
|
2024-06-21 19:04:34 -05:00
|
|
|
const search = useCallback(
|
|
|
|
|
debounce(() => {
|
2024-06-24 14:10:23 -05:00
|
|
|
useTankopediaFilters.setState({ searching: false });
|
2024-06-21 19:04:34 -05:00
|
|
|
|
|
|
|
|
if (!input.current) return;
|
|
|
|
|
|
|
|
|
|
const sanitized = input.current.value.trim();
|
|
|
|
|
|
|
|
|
|
useTankopediaFilters.setState({
|
|
|
|
|
search: sanitized.length === 0 ? undefined : sanitized,
|
|
|
|
|
});
|
|
|
|
|
}, 500),
|
|
|
|
|
[],
|
|
|
|
|
);
|
|
|
|
|
const handleChange = useCallback(() => {
|
2024-06-24 14:10:23 -05:00
|
|
|
useTankopediaFilters.setState({ searching: true });
|
2024-06-21 19:04:34 -05:00
|
|
|
search();
|
|
|
|
|
}, []);
|
|
|
|
|
const handleKeyDown = useCallback<KeyboardEventHandler>(
|
|
|
|
|
(event) => {
|
|
|
|
|
if (event.key !== 'Enter' || !topResult) return;
|
|
|
|
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
router.push(`/tools/tankopedia/${topResult.id}`);
|
|
|
|
|
},
|
|
|
|
|
[topResult],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return (
|
2024-06-24 13:54:08 -05:00
|
|
|
<Flex justify="center">
|
|
|
|
|
<Flex gap="2" flexGrow="1">
|
|
|
|
|
<TextField.Root
|
|
|
|
|
style={{ flex: 1 }}
|
|
|
|
|
ref={input}
|
|
|
|
|
placeholder="Search tanks..."
|
|
|
|
|
onChange={handleChange}
|
|
|
|
|
onKeyDown={handleKeyDown}
|
|
|
|
|
>
|
2024-06-22 16:39:31 -05:00
|
|
|
<TextField.Slot>
|
2024-06-24 13:54:08 -05:00
|
|
|
{searching ? <Spinner /> : <MagnifyingGlassIcon />}
|
2024-06-22 16:39:31 -05:00
|
|
|
</TextField.Slot>
|
|
|
|
|
|
2024-06-24 13:54:08 -05:00
|
|
|
{topResult && (
|
|
|
|
|
<TextField.Slot>
|
|
|
|
|
<Link href={`/tools/tankopedia/${topResult.id}`}>
|
|
|
|
|
<Button variant="ghost">
|
|
|
|
|
{topResult.name} <CaretRightIcon />
|
|
|
|
|
</Button>
|
|
|
|
|
</Link>
|
|
|
|
|
</TextField.Slot>
|
|
|
|
|
)}
|
|
|
|
|
</TextField.Root>
|
|
|
|
|
|
|
|
|
|
<Sort />
|
|
|
|
|
</Flex>
|
2024-06-22 16:39:31 -05:00
|
|
|
</Flex>
|
2024-06-21 19:04:34 -05:00
|
|
|
);
|
|
|
|
|
}
|