2026-10-31 17:43:57 -05:00
|
|
|
import {
|
|
|
|
|
CaretDownIcon,
|
|
|
|
|
CaretRightIcon,
|
|
|
|
|
DotFilledIcon,
|
|
|
|
|
} from "@radix-ui/react-icons";
|
|
|
|
|
import { characteristicsGroups } from "../config/characteristicsGroups";
|
|
|
|
|
import { useStrings } from "../hooks/useStrings";
|
|
|
|
|
import { TankopediaSortDirection } from "../stores/tankopediaPersistent";
|
|
|
|
|
import { TankSort } from "../stores/tankopediaSort";
|
|
|
|
|
import { sortableCharacteristics } from "../tankopedia/sortableCharacteristics";
|
|
|
|
|
import type { CharacteristicName } from "../types/characteristics";
|
|
|
|
|
import { Button } from "./Button";
|
|
|
|
|
import { DropdownMenu } from "./DropdownMenu";
|
2024-05-23 13:29:39 -05:00
|
|
|
|
2025-01-07 13:50:06 -06:00
|
|
|
interface ItemProps {
|
2026-10-15 00:38:01 -05:00
|
|
|
by: CharacteristicName;
|
2025-01-07 13:50:06 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Item({ by }: ItemProps) {
|
2026-09-27 13:22:34 -05:00
|
|
|
const strings = useStrings();
|
2026-10-15 00:38:01 -05:00
|
|
|
const selectedBy = TankSort.use((state) => state.by);
|
2025-01-07 13:50:06 -06:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<DropdownMenu.CheckboxItem
|
2026-10-15 00:38:01 -05:00
|
|
|
checked={selectedBy === by}
|
2025-01-07 13:50:06 -06:00
|
|
|
onClick={() => {
|
2025-09-01 18:13:41 -05:00
|
|
|
TankSort.mutate((draft) => {
|
|
|
|
|
draft.by = by;
|
|
|
|
|
});
|
2025-01-07 13:50:06 -06:00
|
|
|
}}
|
|
|
|
|
>
|
2026-10-31 17:43:57 -05:00
|
|
|
<DropdownMenu.ItemIndicator>
|
|
|
|
|
<DotFilledIcon />
|
|
|
|
|
</DropdownMenu.ItemIndicator>
|
|
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
{strings.tanks.characteristics.items[by]}
|
2025-01-07 13:50:06 -06:00
|
|
|
</DropdownMenu.CheckboxItem>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-31 17:43:57 -05:00
|
|
|
export function TankSearchSort() {
|
2026-10-15 00:38:01 -05:00
|
|
|
const by = TankSort.use((state) => state.by);
|
2025-09-01 18:13:41 -05:00
|
|
|
const direction = TankSort.use((state) => state.direction);
|
2026-09-27 13:22:34 -05:00
|
|
|
const strings = useStrings();
|
2024-05-23 13:29:39 -05:00
|
|
|
|
|
|
|
|
return (
|
2026-08-18 13:57:01 -05:00
|
|
|
<DropdownMenu.Root>
|
2026-08-28 10:42:57 -05:00
|
|
|
<DropdownMenu.Trigger asChild>
|
|
|
|
|
<Button variant="surface" color="gray">
|
2026-10-15 00:38:01 -05:00
|
|
|
{strings.website.common.tank_search.sort.label}
|
2026-08-28 10:42:57 -05:00
|
|
|
<CaretDownIcon />
|
|
|
|
|
</Button>
|
2024-05-23 13:29:39 -05:00
|
|
|
</DropdownMenu.Trigger>
|
2024-06-22 16:39:31 -05:00
|
|
|
|
|
|
|
|
<DropdownMenu.Content align="end">
|
2025-01-07 13:50:06 -06:00
|
|
|
<DropdownMenu.Label>
|
2026-10-31 17:43:57 -05:00
|
|
|
{strings.website.common.tank_search.sort.by}
|
2025-01-07 13:50:06 -06:00
|
|
|
</DropdownMenu.Label>
|
2024-05-23 13:29:39 -05:00
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
<DropdownMenu.CheckboxItem
|
|
|
|
|
checked={by === null || !sortableCharacteristics.has(by)}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
TankSort.mutate((draft) => {
|
|
|
|
|
draft.by = null;
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
2026-10-31 17:43:57 -05:00
|
|
|
<DropdownMenu.ItemIndicator>
|
|
|
|
|
<DotFilledIcon />
|
|
|
|
|
</DropdownMenu.ItemIndicator>
|
|
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
{strings.website.common.tank_search.sort.none}
|
|
|
|
|
</DropdownMenu.CheckboxItem>
|
2024-05-23 13:29:39 -05:00
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
{characteristicsGroups.map((group) => {
|
|
|
|
|
const items = group.order.filter(
|
|
|
|
|
(item) => "name" in item && sortableCharacteristics.has(item.name),
|
|
|
|
|
);
|
2024-05-23 13:29:39 -05:00
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
return (
|
|
|
|
|
<DropdownMenu.Sub key={group.name}>
|
|
|
|
|
<DropdownMenu.SubTrigger>
|
|
|
|
|
{
|
|
|
|
|
(
|
|
|
|
|
strings.tanks.characteristics.titles as Record<
|
|
|
|
|
string,
|
|
|
|
|
string
|
|
|
|
|
>
|
|
|
|
|
)[group.name]
|
|
|
|
|
}
|
2026-10-31 17:43:57 -05:00
|
|
|
|
|
|
|
|
<CaretRightIcon />
|
2026-10-15 00:38:01 -05:00
|
|
|
</DropdownMenu.SubTrigger>
|
2024-05-23 13:29:39 -05:00
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
<DropdownMenu.SubContent>
|
|
|
|
|
{items.map((item) => {
|
|
|
|
|
if (!("name" in item)) return null;
|
|
|
|
|
|
|
|
|
|
return <Item key={item.name} by={item.name} />;
|
|
|
|
|
})}
|
|
|
|
|
</DropdownMenu.SubContent>
|
|
|
|
|
</DropdownMenu.Sub>
|
|
|
|
|
);
|
|
|
|
|
})}
|
2024-05-23 13:29:39 -05:00
|
|
|
|
2025-01-07 13:50:06 -06:00
|
|
|
<DropdownMenu.Label>
|
2026-10-15 00:38:01 -05:00
|
|
|
{strings.website.common.tank_search.sort.direction.label}
|
2025-01-07 13:50:06 -06:00
|
|
|
</DropdownMenu.Label>
|
2024-05-23 13:29:39 -05:00
|
|
|
<DropdownMenu.RadioGroup
|
2026-10-31 17:43:57 -05:00
|
|
|
value={`${direction}`}
|
|
|
|
|
onValueChange={(_value) => {
|
|
|
|
|
const value = Number(_value);
|
|
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
if (
|
|
|
|
|
value !== TankopediaSortDirection.Ascending &&
|
|
|
|
|
value !== TankopediaSortDirection.Descending
|
|
|
|
|
) {
|
|
|
|
|
throw new Error(`Unknown tankopedia sort direction: ${value}`);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-01 18:13:41 -05:00
|
|
|
TankSort.mutate((draft) => {
|
2026-10-15 00:38:01 -05:00
|
|
|
draft.direction = value;
|
2025-09-01 18:13:41 -05:00
|
|
|
});
|
2024-09-17 22:13:35 -05:00
|
|
|
}}
|
2024-05-23 13:29:39 -05:00
|
|
|
>
|
2026-10-31 17:43:57 -05:00
|
|
|
<DropdownMenu.RadioItem
|
|
|
|
|
value={`${TankopediaSortDirection.Ascending}`}
|
|
|
|
|
>
|
|
|
|
|
<DropdownMenu.ItemIndicator>
|
|
|
|
|
<DotFilledIcon />
|
|
|
|
|
</DropdownMenu.ItemIndicator>
|
|
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
{strings.website.common.tank_search.sort.direction.ascending}
|
2024-05-23 13:29:39 -05:00
|
|
|
</DropdownMenu.RadioItem>
|
2026-10-31 17:43:57 -05:00
|
|
|
<DropdownMenu.RadioItem
|
|
|
|
|
value={`${TankopediaSortDirection.Descending}`}
|
|
|
|
|
>
|
|
|
|
|
<DropdownMenu.ItemIndicator>
|
|
|
|
|
<DotFilledIcon />
|
|
|
|
|
</DropdownMenu.ItemIndicator>
|
|
|
|
|
|
2026-10-15 00:38:01 -05:00
|
|
|
{strings.website.common.tank_search.sort.direction.descending}
|
2024-05-23 13:29:39 -05:00
|
|
|
</DropdownMenu.RadioItem>
|
|
|
|
|
</DropdownMenu.RadioGroup>
|
|
|
|
|
</DropdownMenu.Content>
|
|
|
|
|
</DropdownMenu.Root>
|
|
|
|
|
);
|
|
|
|
|
}
|