feat: simpler filter ui

This commit is contained in:
TrèsAbhi committed 2024-02-06 15:10:54 -06:00
1 parent ed8a1c2f57
commit 4fb0aa3936
3 files changed
+279 -284

No files matched your search

@@ -26,274 +26,110 @@ export function Options() {
const filters = useTankopediaPersistent((state) => state.filters); const filters = useTankopediaPersistent((state) => state.filters);
return ( return (
<Flex justify="center" direction="column" gap="2"> <Flex gap="2" wrap="wrap" justify="center">
<Flex gap="2" style={{ flex: 1 }} wrap="wrap"> <DropdownMenu.Root>
<Button <DropdownMenu.Trigger>
color="red" <Button variant="soft" color="gray">
onClick={() => Test tanks
useTankopediaPersistent.setState({ <CaretDownIcon />
filters: { </Button>
nations: [], </DropdownMenu.Trigger>
tiers: [], <DropdownMenu.Content>
treeTypes: [], <DropdownMenu.RadioGroup
types: [], value={filters.test}
test: 'include', onValueChange={(value) =>
page: 0, mutateTankopediaPersistent((draft) => {
}, draft.filters.test = value as TankopediaTestTankDisplay;
}) })
} }
> >
Reset <DropdownMenu.RadioItem value="include">
</Button> Include
<DropdownMenu.Root> </DropdownMenu.RadioItem>
<DropdownMenu.Trigger> <DropdownMenu.RadioItem value="exclude">
<Button variant="soft" color="gray"> Exclude
Test tanks </DropdownMenu.RadioItem>
<CaretDownIcon /> <DropdownMenu.RadioItem value="only">Only</DropdownMenu.RadioItem>
</Button> </DropdownMenu.RadioGroup>
</DropdownMenu.Trigger> </DropdownMenu.Content>
<DropdownMenu.Content> </DropdownMenu.Root>
<DropdownMenu.RadioGroup <Flex>
value={filters.test} {TREE_TYPES.map((type, index) => (
onValueChange={(value) => <Button
mutateTankopediaPersistent((draft) => { key={type}
draft.filters.test = value as TankopediaTestTankDisplay; color={filters.treeTypes.includes(type) ? undefined : 'gray'}
}) variant={filters.treeTypes.includes(type) ? 'surface' : 'soft'}
} style={{
> flex: 1,
<DropdownMenu.RadioItem value="include"> margin: -0.5,
Include borderTopLeftRadius: index === 0 ? undefined : 0,
</DropdownMenu.RadioItem> borderBottomLeftRadius: index === 0 ? undefined : 0,
<DropdownMenu.RadioItem value="exclude"> borderTopRightRadius:
Exclude index === TREE_TYPES.length - 1 ? undefined : 0,
</DropdownMenu.RadioItem> borderBottomRightRadius:
<DropdownMenu.RadioItem value="only">Only</DropdownMenu.RadioItem> index === TREE_TYPES.length - 1 ? undefined : 0,
</DropdownMenu.RadioGroup> }}
</DropdownMenu.Content> onClick={() =>
</DropdownMenu.Root> mutateTankopediaPersistent((draft) => {
<Flex style={{ flex: 1 }}> if (draft.filters.treeTypes.includes(type)) {
{TREE_TYPES.map((type, index) => ( draft.filters.treeTypes = draft.filters.treeTypes.filter(
<Button (preexistingType) => preexistingType !== type,
key={type} );
color={filters.treeTypes.includes(type) ? undefined : 'gray'} } else {
variant={filters.treeTypes.includes(type) ? 'surface' : 'soft'} draft.filters.treeTypes.push(type);
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: index === 0 ? undefined : 0,
borderBottomLeftRadius: index === 0 ? undefined : 0,
borderTopRightRadius:
index === TREE_TYPES.length - 1 ? undefined : 0,
borderBottomRightRadius:
index === TREE_TYPES.length - 1 ? undefined : 0,
}}
onClick={() =>
mutateTankopediaPersistent((draft) => {
if (draft.filters.treeTypes.includes(type)) {
draft.filters.treeTypes = draft.filters.treeTypes.filter(
(preexistingType) => preexistingType !== type,
);
} else {
draft.filters.treeTypes.push(type);
}
})
}
>
<img
src={TREE_TYPE_IMAGES[type]}
style={{ width: '1em', height: '1em' }}
/>
</Button>
))}
</Flex>
<Flex style={{ flex: 1 }}>
{[...TANK_TYPES].map((type, index) => (
<Button
key={type}
color={filters.types.includes(type) ? undefined : 'gray'}
variant={filters.types.includes(type) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: index === 0 ? undefined : 0,
borderBottomLeftRadius: index === 0 ? undefined : 0,
borderTopRightRadius:
index === TANK_TYPES.length - 1 ? undefined : 0,
borderBottomRightRadius:
index === TANK_TYPES.length - 1 ? undefined : 0,
}}
onClick={() =>
mutateTankopediaPersistent((draft) => {
if (draft.filters.types.includes(type)) {
draft.filters.types = draft.filters.types.filter(
(preexistingType) => preexistingType !== type,
);
} else {
draft.filters.types.push(type);
}
})
}
>
<img
src={TREE_TYPE_ICONS.researchable[type]}
style={{ width: '1em', height: '1em' }}
/>
</Button>
))}
</Flex>
<Flex
direction="column"
className={styles.splitFilters}
style={{ width: '100%' }}
>
<Flex>
{[...TIERS].slice(0, 5).map((tier, index) => (
<Button
key={tier}
color={filters.tiers.includes(tier) ? undefined : 'gray'}
variant={filters.tiers.includes(tier) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: index === 0 ? 16 : 0,
borderBottomLeftRadius: 0,
borderTopRightRadius:
index === TIERS.length - Math.round(TIERS.length / 2) - 1
? 16
: 0,
borderBottomRightRadius: 0,
}}
onClick={() =>
mutateTankopediaPersistent((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> >
))} <img
</Flex> src={TREE_TYPE_IMAGES[type]}
<Flex> style={{ width: '1em', height: '1em' }}
{[...TIERS].slice(5).map((tier, index) => ( />
<Button </Button>
key={tier} ))}
color={filters.tiers.includes(tier) ? undefined : 'gray'}
variant={filters.tiers.includes(tier) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: 0,
borderBottomLeftRadius: index === 0 ? 16 : 0,
borderTopRightRadius: 0,
borderBottomRightRadius:
index === TIERS.length - Math.round(TIERS.length / 2) - 1
? 16
: 0,
}}
onClick={() =>
mutateTankopediaPersistent((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
direction="column"
className={styles.splitFilters}
style={{ width: '100%' }}
>
<Flex>
{nations.slice(0, 5).map((nation, index) => (
<Button
key={nation}
color={filters.nations.includes(nation) ? undefined : 'gray'}
variant={filters.nations.includes(nation) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: index === 0 ? 16 : 0,
borderBottomLeftRadius: 0,
borderTopRightRadius:
index === nations.length - Math.round(nations.length / 2)
? 16
: 0,
borderBottomRightRadius:
index === nations.length - 1 ? undefined : 0,
}}
onClick={() =>
mutateTankopediaPersistent((draft) => {
if (draft.filters.nations.includes(nation)) {
draft.filters.nations = draft.filters.nations.filter(
(preexistingType) => preexistingType !== nation,
);
} else {
draft.filters.nations.push(nation);
}
})
}
>
<Flag nation={nation} />
</Button>
))}
</Flex>
<Flex>
{nations.slice(5).map((nation, index) => (
<Button
key={nation}
color={filters.nations.includes(nation) ? undefined : 'gray'}
variant={filters.nations.includes(nation) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: 0,
borderBottomLeftRadius: index === 0 ? 16 : 0,
borderTopRightRadius:
index === nations.length - 1 ? undefined : 0,
borderBottomRightRadius:
index ===
nations.length - Math.round(nations.length / 2) - 1
? 16
: 0,
}}
onClick={() =>
mutateTankopediaPersistent((draft) => {
if (draft.filters.nations.includes(nation)) {
draft.filters.nations = draft.filters.nations.filter(
(preexistingType) => preexistingType !== nation,
);
} else {
draft.filters.nations.push(nation);
}
})
}
>
<Flag nation={nation} />
</Button>
))}
</Flex>
</Flex>
</Flex> </Flex>
<Flex>
<Flex gap="2" style={{ flex: 1 }} wrap="wrap"> {[...TANK_TYPES].map((type, index) => (
<Flex className={styles.oneLineFilters} style={{ flex: 1 }}> <Button
{[...TIERS].map((tier, index) => ( key={type}
color={filters.types.includes(type) ? undefined : 'gray'}
variant={filters.types.includes(type) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: index === 0 ? undefined : 0,
borderBottomLeftRadius: index === 0 ? undefined : 0,
borderTopRightRadius:
index === TANK_TYPES.length - 1 ? undefined : 0,
borderBottomRightRadius:
index === TANK_TYPES.length - 1 ? undefined : 0,
}}
onClick={() =>
mutateTankopediaPersistent((draft) => {
if (draft.filters.types.includes(type)) {
draft.filters.types = draft.filters.types.filter(
(preexistingType) => preexistingType !== type,
);
} else {
draft.filters.types.push(type);
}
})
}
>
<img
src={TREE_TYPE_ICONS.researchable[type]}
style={{ width: '1em', height: '1em' }}
/>
</Button>
))}
</Flex>
<Flex
direction="column"
className={styles.splitFilters}
style={{ width: '100%' }}
>
<Flex>
{[...TIERS].slice(0, 5).map((tier, index) => (
<Button <Button
key={tier} key={tier}
color={filters.tiers.includes(tier) ? undefined : 'gray'} color={filters.tiers.includes(tier) ? undefined : 'gray'}
@@ -301,12 +137,13 @@ export function Options() {
style={{ style={{
flex: 1, flex: 1,
margin: -0.5, margin: -0.5,
borderTopLeftRadius: index === 0 ? undefined : 0, borderTopLeftRadius: index === 0 ? 16 : 0,
borderBottomLeftRadius: index === 0 ? undefined : 0, borderBottomLeftRadius: 0,
borderTopRightRadius: borderTopRightRadius:
index === TIERS.length - 1 ? undefined : 0, index === TIERS.length - Math.round(TIERS.length / 2) - 1
borderBottomRightRadius: ? 16
index === TIERS.length - 1 ? undefined : 0, : 0,
borderBottomRightRadius: 0,
}} }}
onClick={() => onClick={() =>
mutateTankopediaPersistent((draft) => { mutateTankopediaPersistent((draft) => {
@@ -324,8 +161,47 @@ export function Options() {
</Button> </Button>
))} ))}
</Flex> </Flex>
<Flex className={styles.oneLineFilters} style={{ flex: 1 }}> <Flex>
{nations.map((nation, index) => ( {[...TIERS].slice(5).map((tier, index) => (
<Button
key={tier}
color={filters.tiers.includes(tier) ? undefined : 'gray'}
variant={filters.tiers.includes(tier) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: 0,
borderBottomLeftRadius: index === 0 ? 16 : 0,
borderTopRightRadius: 0,
borderBottomRightRadius:
index === TIERS.length - Math.round(TIERS.length / 2) - 1
? 16
: 0,
}}
onClick={() =>
mutateTankopediaPersistent((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
direction="column"
className={styles.splitFilters}
style={{ width: '100%' }}
>
<Flex>
{nations.slice(0, 5).map((nation, index) => (
<Button <Button
key={nation} key={nation}
color={filters.nations.includes(nation) ? undefined : 'gray'} color={filters.nations.includes(nation) ? undefined : 'gray'}
@@ -333,10 +209,12 @@ export function Options() {
style={{ style={{
flex: 1, flex: 1,
margin: -0.5, margin: -0.5,
borderTopLeftRadius: index === 0 ? undefined : 0, borderTopLeftRadius: index === 0 ? 16 : 0,
borderBottomLeftRadius: index === 0 ? undefined : 0, borderBottomLeftRadius: 0,
borderTopRightRadius: borderTopRightRadius:
index === nations.length - 1 ? undefined : 0, index === nations.length - Math.round(nations.length / 2)
? 16
: 0,
borderBottomRightRadius: borderBottomRightRadius:
index === nations.length - 1 ? undefined : 0, index === nations.length - 1 ? undefined : 0,
}} }}
@@ -356,6 +234,104 @@ export function Options() {
</Button> </Button>
))} ))}
</Flex> </Flex>
<Flex>
{nations.slice(5).map((nation, index) => (
<Button
key={nation}
color={filters.nations.includes(nation) ? undefined : 'gray'}
variant={filters.nations.includes(nation) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: 0,
borderBottomLeftRadius: index === 0 ? 16 : 0,
borderTopRightRadius:
index === nations.length - 1 ? undefined : 0,
borderBottomRightRadius:
index === nations.length - Math.round(nations.length / 2) - 1
? 16
: 0,
}}
onClick={() =>
mutateTankopediaPersistent((draft) => {
if (draft.filters.nations.includes(nation)) {
draft.filters.nations = draft.filters.nations.filter(
(preexistingType) => preexistingType !== nation,
);
} else {
draft.filters.nations.push(nation);
}
})
}
>
<Flag nation={nation} />
</Button>
))}
</Flex>
</Flex>
<Flex className={styles.oneLineFilters}>
{nations.map((nation, index) => (
<Button
key={nation}
color={filters.nations.includes(nation) ? undefined : 'gray'}
variant={filters.nations.includes(nation) ? 'surface' : 'soft'}
style={{
flex: 1,
margin: -0.5,
borderTopLeftRadius: index === 0 ? undefined : 0,
borderBottomLeftRadius: index === 0 ? undefined : 0,
borderTopRightRadius:
index === nations.length - 1 ? undefined : 0,
borderBottomRightRadius:
index === nations.length - 1 ? undefined : 0,
}}
onClick={() =>
mutateTankopediaPersistent((draft) => {
if (draft.filters.nations.includes(nation)) {
draft.filters.nations = draft.filters.nations.filter(
(preexistingType) => preexistingType !== nation,
);
} else {
draft.filters.nations.push(nation);
}
})
}
>
<Flag nation={nation} />
</Button>
))}
</Flex>
<Flex className={styles.oneLineFilters}>
{[...TIERS].map((tier, index) => (
<Button
key={tier}
color={filters.tiers.includes(tier) ? undefined : 'gray'}
variant={filters.tiers.includes(tier) ? 'surface' : 'soft'}
style={{
flex: 1,
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={() =>
mutateTankopediaPersistent((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> </Flex>
); );
@@ -1,5 +1,9 @@
import { slateDark } from '@radix-ui/colors'; import { slateDark } from '@radix-ui/colors';
import { CaretDownIcon, MagnifyingGlassIcon } from '@radix-ui/react-icons'; import {
CaretDownIcon,
MagnifyingGlassIcon,
TrashIcon,
} from '@radix-ui/react-icons';
import { import {
Button, Button,
Card, Card,
@@ -10,7 +14,7 @@ import {
TextField, TextField,
} from '@radix-ui/themes'; } from '@radix-ui/themes';
import { go } from 'fuzzysort'; import { go } from 'fuzzysort';
import { Suspense, use, useEffect, useMemo, useRef, useState } from 'react'; import { use, useEffect, useMemo, useRef, useState } from 'react';
import { TankType, TreeType } from '../../../../../components/Tanks'; import { TankType, TreeType } from '../../../../../components/Tanks';
import { asset } from '../../../../../core/blitzkrieg/asset'; import { asset } from '../../../../../core/blitzkrieg/asset';
import { import {
@@ -202,13 +206,28 @@ export function TankSearch({ compact, onSelect = () => {} }: TankSearchProps) {
</DropdownMenu.RadioGroup> </DropdownMenu.RadioGroup>
</DropdownMenu.Content> </DropdownMenu.Content>
</DropdownMenu.Root> </DropdownMenu.Root>
<Button
color="red"
variant="soft"
onClick={() =>
useTankopediaPersistent.setState({
filters: {
nations: [],
tiers: [],
treeTypes: [],
types: [],
test: 'include',
page: 0,
},
})
}
>
<TrashIcon />
</Button>
</Flex> </Flex>
<Card variant={compact ? 'ghost' : 'surface'}> <Options />
<Suspense fallback={<Text>Loading...</Text>}>
<Options />
</Suspense>
</Card>
</Flex> </Flex>
{!compact && ( {!compact && (
+1 -1
View File
@@ -8,7 +8,7 @@ export default function Page() {
const router = useRouter(); const router = useRouter();
return ( return (
<PageWrapper size="wide" color="purple"> <PageWrapper size="double" color="purple">
<TankSearch <TankSearch
onSelect={(tank) => { onSelect={(tank) => {
router.push(`./tankopedia/${tank.id}`); router.push(`./tankopedia/${tank.id}`);