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',
+2
View File
@@ -84,6 +84,8 @@ export const TANK_ICONS_COLLECTOR: Record<TankType, string> = {
export type Tier = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
export const TIERS: Tier[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
export const TIER_ROMAN_NUMERALS: Record<Tier, string> = {
1: 'I',
2: 'II',
+15 -4
View File
@@ -1,21 +1,32 @@
import { produce } from 'immer';
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { TIERS, Tier } from '../core/blitzkrieg/tankopedia';
export type TankopediaSortBy = 'tier' | 'name';
export type TankopediaSortDirection = 'ascending' | 'descending';
type Tankopedia = {
sortBy: TankopediaSortBy;
sortDirection: TankopediaSortDirection;
sort: {
by: TankopediaSortBy;
direction: TankopediaSortDirection;
};
filters: {
tiers: Tier[];
};
};
export const useTankopedia = create<Tankopedia>()(
devtools(
persist(
(set) => ({
sortBy: 'tier',
sortDirection: 'descending',
sort: {
by: 'tier',
direction: 'descending',
},
filters: {
tiers: [...TIERS],
},
}),
{ name: 'tankopedia' },
),