feat: tier filters

This commit is contained in:
TrèsAbhi committed 2023-12-04 11:47:33 -06:00
1 parent 5b4601b671
commit 7020e5641f
4 files changed
+127 -70

No files matched your search

+87 -45
View File
@@ -3,6 +3,10 @@
import { CaretDownIcon } from '@radix-ui/react-icons';
import { Button, DropdownMenu, Flex } from '@radix-ui/themes';
import {
TIERS,
TIER_ROMAN_NUMERALS,
} from '../../../../core/blitzkrieg/tankopedia';
import mutateTankopedia, {
TankopediaSortBy,
TankopediaSortDirection,
useTankopedia,
@@ -12,52 +16,90 @@ export function Options() {
const tankopediaState = useTankopedia();
return (
<Flex gap="1">
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Button variant="soft">
Sort by
<CaretDownIcon />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.RadioGroup
value={tankopediaState.sortBy}
onValueChange={(value) =>
useTankopedia.setState({ sortBy: value as TankopediaSortBy })
}
>
<DropdownMenu.RadioItem value="tier">Tier</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem value="name">Name</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.Content>
</DropdownMenu.Root>
<Flex justify="between">
<Flex gap="1">
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Button variant="soft">
Sort by
<CaretDownIcon />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.RadioGroup
value={tankopediaState.sort.by}
onValueChange={(value) =>
mutateTankopedia((draft) => {
draft.sort.by = value as TankopediaSortBy;
})
}
>
<DropdownMenu.RadioItem value="tier">Tier</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem value="name">Name</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.Content>
</DropdownMenu.Root>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Button variant="soft">
Sort order
<CaretDownIcon />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.RadioGroup
value={tankopediaState.sortDirection}
onValueChange={(value) =>
useTankopedia.setState({
sortDirection: value as TankopediaSortDirection,
})
}
>
<DropdownMenu.RadioItem value="ascending">
Ascending
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem value="descending">
Descending
</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.Content>
</DropdownMenu.Root>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Button variant="soft">
Sort order
<CaretDownIcon />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.RadioGroup
value={tankopediaState.sort.direction}
onValueChange={(value) =>
mutateTankopedia((draft) => {
draft.sort.direction = value as TankopediaSortDirection;
})
}
>
<DropdownMenu.RadioItem value="ascending">
Ascending
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem value="descending">
Descending
</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Flex>
<Flex gap="1">
<Flex>
{TIERS.toReversed().map((tier, index) => (
<Button
variant={
tankopediaState.filters.tiers.includes(tier) ? 'solid' : 'soft'
}
style={{
margin: -0.5,
borderTopLeftRadius: index === 0 ? undefined : 0,
borderBottomLeftRadius: index === 0 ? undefined : 0,
borderTopRightRadius:
index === TIERS.length - 1 ? undefined : 0,
borderBottomRightRadius:
index === TIERS.length - 1 ? undefined : 0,
}}
onClick={() =>
mutateTankopedia((draft) => {
if (draft.filters.tiers.includes(tier)) {
draft.filters.tiers = draft.filters.tiers.filter(
(preexistingTier) => preexistingTier !== tier,
);
} else {
draft.filters.tiers.push(tier);
}
})
}
>
{TIER_ROMAN_NUMERALS[tier]}
</Button>
))}
</Flex>
</Flex>
</Flex>
);
}
+23 -21
View File
@@ -30,34 +30,36 @@ export default function Page() {
const tankopediaState = useTankopedia();
const awaitedTanks = use(tanks);
const input = useRef<HTMLInputElement>(null);
const sortedTanks = useMemo(
const searchableTanks = useMemo(
() =>
awaitedTanks.toSorted((a, b) => {
let diff = 0;
awaitedTanks
.filter((tank) => tankopediaState.filters.tiers.includes(tank.tier))
.toSorted((a, b) => {
let diff = 0;
if (tankopediaState.sortBy === 'tier') {
diff = a.tier - b.tier;
}
if (tankopediaState.sortBy === 'name') {
diff = (
a.name_short ??
a.name ??
`Unknown tank ${a.id}`
).localeCompare(b.name_short ?? b.name ?? `Unknown tank ${b.id}`);
}
if (tankopediaState.sort.by === 'tier') {
diff = a.tier - b.tier;
}
if (tankopediaState.sort.by === 'name') {
diff = (
a.name_short ??
a.name ??
`Unknown tank ${a.id}`
).localeCompare(b.name_short ?? b.name ?? `Unknown tank ${b.id}`);
}
return tankopediaState.sortDirection === 'ascending' ? diff : -diff;
}),
[tankopediaState.sortBy, tankopediaState.sortDirection],
return tankopediaState.sort.direction === 'ascending' ? diff : -diff;
}),
[tankopediaState.filters, tankopediaState.sort],
);
const [searchedList, setSearchedList] = useState(sortedTanks);
const [searchedList, setSearchedList] = useState(searchableTanks);
const [page, setPage] = useState(0);
const pageInput = useRef<HTMLInputElement>(null);
useEffect(() => {
setSearchedList(sortedTanks);
setSearchedList(searchableTanks);
if (input.current) input.current.value = '';
}, [sortedTanks]);
}, [searchableTanks]);
useEffect(() => {
if (pageInput.current) pageInput.current.value = `${page + 1}`;
@@ -84,10 +86,10 @@ export default function Page() {
placeholder="Search tanks..."
onChange={(event) => {
if (event.target.value.length === 0) {
setSearchedList(sortedTanks);
setSearchedList(searchableTanks);
} else {
setSearchedList(
go(event.target.value, sortedTanks, {
go(event.target.value, searchableTanks, {
keys: [
'name',
'name_short',