Fix search filters
* Update styles for all search filters * Make search filters function better on mobile * Small refactor on individual filter bar files to extract individual search filter rendering into variables
This commit is contained in:
parent
3434e7042c
commit
c26752d8c1
12 changed files with 386 additions and 366 deletions
|
|
@ -0,0 +1,11 @@
|
||||||
|
.filterBar {
|
||||||
|
display: flex;
|
||||||
|
gap: $unit;
|
||||||
|
padding: $unit-half $unit-3x;
|
||||||
|
|
||||||
|
@include breakpoint(phone) {
|
||||||
|
display: grid;
|
||||||
|
gap: $unit;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -144,16 +144,12 @@ const CharacterSearchFilterBar = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={`${t('filters.labels.proficiency')} ${proficiency}`}
|
label={`${t('filters.labels.proficiency')} ${proficiency}`}
|
||||||
|
display="grid"
|
||||||
numSelected={numSelected}
|
numSelected={numSelected}
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={onOpenChange}
|
onOpenChange={onOpenChange}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">{`${t(
|
{Array.from(Array(proficiencies.length)).map((x, i) => {
|
||||||
'filters.labels.proficiency'
|
|
||||||
)} ${proficiency}`}</DropdownMenu.Label>
|
|
||||||
<section>
|
|
||||||
<DropdownMenu.Group className="Group">
|
|
||||||
{Array.from(Array(proficiencies.length / 2)).map((x, i) => {
|
|
||||||
const checked =
|
const checked =
|
||||||
proficiency == 1
|
proficiency == 1
|
||||||
? proficiency1State[proficiencies[i]].checked
|
? proficiency1State[proficiencies[i]].checked
|
||||||
|
|
@ -170,43 +166,14 @@ const CharacterSearchFilterBar = (props: Props) => {
|
||||||
</SearchFilterCheckboxItem>
|
</SearchFilterCheckboxItem>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</DropdownMenu.Group>
|
|
||||||
<DropdownMenu.Group className="Group">
|
|
||||||
{Array.from(Array(proficiencies.length / 2)).map((x, i) => {
|
|
||||||
const checked =
|
|
||||||
proficiency == 1
|
|
||||||
? proficiency1State[
|
|
||||||
proficiencies[i + proficiencies.length / 2]
|
|
||||||
].checked
|
|
||||||
: proficiency2State[
|
|
||||||
proficiencies[i + proficiencies.length / 2]
|
|
||||||
].checked
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SearchFilterCheckboxItem
|
|
||||||
key={proficiencies[i + proficiencies.length / 2]}
|
|
||||||
onCheckedChange={onCheckedChange}
|
|
||||||
checked={checked}
|
|
||||||
valueKey={proficiencies[i + proficiencies.length / 2]}
|
|
||||||
>
|
|
||||||
{t(
|
|
||||||
`proficiencies.${
|
|
||||||
proficiencies[i + proficiencies.length / 2]
|
|
||||||
}`
|
|
||||||
)}
|
|
||||||
</SearchFilterCheckboxItem>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
</section>
|
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const rarityFilter = (
|
||||||
<div className="SearchFilterBar">
|
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.rarity')}
|
label={t('filters.labels.rarity')}
|
||||||
|
display="list"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(rarityState)
|
Object.values(rarityState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -215,9 +182,6 @@ const CharacterSearchFilterBar = (props: Props) => {
|
||||||
open={rarityMenu}
|
open={rarityMenu}
|
||||||
onOpenChange={rarityMenuOpened}
|
onOpenChange={rarityMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
|
||||||
{t('filters.labels.rarity')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
{Array.from(Array(rarities.length)).map((x, i) => {
|
{Array.from(Array(rarities.length)).map((x, i) => {
|
||||||
return (
|
return (
|
||||||
<SearchFilterCheckboxItem
|
<SearchFilterCheckboxItem
|
||||||
|
|
@ -231,9 +195,12 @@ const CharacterSearchFilterBar = (props: Props) => {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
|
)
|
||||||
|
|
||||||
|
const elementFilter = (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.element')}
|
label={t('filters.labels.element')}
|
||||||
|
display="list"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(elementState)
|
Object.values(elementState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -242,9 +209,6 @@ const CharacterSearchFilterBar = (props: Props) => {
|
||||||
open={elementMenu}
|
open={elementMenu}
|
||||||
onOpenChange={elementMenuOpened}
|
onOpenChange={elementMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
|
||||||
{t('filters.labels.element')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
{Array.from(Array(elements.length)).map((x, i) => {
|
{Array.from(Array(elements.length)).map((x, i) => {
|
||||||
return (
|
return (
|
||||||
<SearchFilterCheckboxItem
|
<SearchFilterCheckboxItem
|
||||||
|
|
@ -258,7 +222,12 @@ const CharacterSearchFilterBar = (props: Props) => {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.filterBar}>
|
||||||
|
{rarityFilter}
|
||||||
|
{elementFilter}
|
||||||
{renderProficiencyFilter(1)}
|
{renderProficiencyFilter(1)}
|
||||||
{renderProficiencyFilter(2)}
|
{renderProficiencyFilter(2)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
.SearchFilterBar .SelectTrigger {
|
.SearchFilterBar .SelectTrigger {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filterBar {
|
||||||
|
display: flex;
|
||||||
|
gap: $unit;
|
||||||
|
padding: $unit-half $unit-3x;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,13 @@ const JobSkillSearchFilterBar = (props: Props) => {
|
||||||
}, [currentGroup])
|
}, [currentGroup])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="SearchFilterBar">
|
<div className={styles.filterBar}>
|
||||||
<Select
|
<Select
|
||||||
value={-1}
|
value={-1}
|
||||||
triggerClass="Bound"
|
trigger={{
|
||||||
|
bound: true,
|
||||||
|
className: 'full',
|
||||||
|
}}
|
||||||
open={open}
|
open={open}
|
||||||
overlayVisible={false}
|
overlayVisible={false}
|
||||||
onValueChange={onChange}
|
onValueChange={onChange}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,54 @@
|
||||||
button.DropdownLabel {
|
.pill {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: var(--button-contained-bg);
|
background: var(--button-contained-bg);
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: $unit-2x;
|
border-radius: $unit-2x;
|
||||||
color: var(--text-secondary);
|
border: 2px solid transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: $font-small;
|
font-size: $font-small;
|
||||||
gap: $unit-half;
|
gap: $unit-half;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: $unit ($unit * 1.5) $unit $unit-2x;
|
padding: $unit ($unit * 1.5);
|
||||||
|
|
||||||
div {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
gap: $unit-half;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--button-contained-bg-hover);
|
background: var(--button-contained-bg-hover);
|
||||||
color: var(--text-primary);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include breakpoint(phone) {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
@include breakpoint(phone) {
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: calc($unit-2x - 1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
font-weight: $bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.count {
|
.count {
|
||||||
color: var(--text-tertiary);
|
color: var(--text-secondary);
|
||||||
font-weight: $medium;
|
font-weight: $medium;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& > .icon {
|
.icon {
|
||||||
$diameter: 16px;
|
$diameter: $unit-2x;
|
||||||
height: $diameter;
|
height: $diameter;
|
||||||
width: $diameter;
|
width: $diameter;
|
||||||
|
|
||||||
|
|
@ -39,16 +58,39 @@ button.DropdownLabel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
gap: $unit-half;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Dropdown {
|
.dropdown {
|
||||||
background: var(--button-contained-bg);
|
background: var(--button-contained-bg);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
border-radius: $unit;
|
border-radius: $unit;
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.18);
|
box-shadow: 0 0 4px rgba(0, 0, 0, 0.18);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: $unit;
|
||||||
padding: $unit;
|
padding: $unit;
|
||||||
min-width: 120px;
|
overflow-y: scroll;
|
||||||
|
max-height: 60vh;
|
||||||
|
|
||||||
|
@include breakpoint(phone) {
|
||||||
|
width: calc(100vw - $unit-6x);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
& > span {
|
& > span {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
@ -64,16 +106,4 @@ button.DropdownLabel {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: $unit;
|
gap: $unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Group {
|
|
||||||
flex: 1 1 0px;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Label {
|
|
||||||
color: var(--text-tertiary);
|
|
||||||
font-size: $font-small;
|
|
||||||
margin-bottom: $unit-half;
|
|
||||||
padding: $unit-half 0 $unit $unit-half;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import classNames from 'classnames'
|
||||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||||
|
|
||||||
import ChevronIcon from '~public/icons/Chevron.svg'
|
import ChevronIcon from '~public/icons/Chevron.svg'
|
||||||
|
|
@ -8,26 +8,35 @@ import styles from './index.module.scss'
|
||||||
interface Props {
|
interface Props {
|
||||||
label: string
|
label: string
|
||||||
open: boolean
|
open: boolean
|
||||||
|
display: 'grid' | 'list'
|
||||||
numSelected: number
|
numSelected: number
|
||||||
onOpenChange: (open: boolean) => void
|
onOpenChange: (open: boolean) => void
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchFilter = (props: Props) => {
|
const SearchFilter = (props: Props) => {
|
||||||
|
const displayClasses = classNames({
|
||||||
|
[styles.grid]: props.display === 'grid',
|
||||||
|
[styles.list]: props.display === 'list',
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root open={props.open} onOpenChange={props.onOpenChange}>
|
<DropdownMenu.Root open={props.open} onOpenChange={props.onOpenChange}>
|
||||||
<DropdownMenu.Trigger className="DropdownLabel">
|
<DropdownMenu.Trigger className={styles.pill}>
|
||||||
<div>
|
<div className={styles.label}>
|
||||||
{props.label}
|
<span className={styles.text}>{props.label}</span>
|
||||||
<span className="count">{props.numSelected}</span>
|
<span className={styles.count}>{props.numSelected}</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="icon">
|
<span className={styles.icon}>
|
||||||
<ChevronIcon />
|
<ChevronIcon />
|
||||||
</span>
|
</span>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Content className="Dropdown" sideOffset={4}>
|
<DropdownMenu.Content
|
||||||
{props.children}
|
className={styles.dropdown}
|
||||||
<DropdownMenu.Arrow />
|
sideOffset={4}
|
||||||
|
collisionPadding={16}
|
||||||
|
>
|
||||||
|
<div className={displayClasses}>{props.children}</div>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
.Item {
|
.item {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: calc($unit / 2);
|
border-radius: calc($unit / 2);
|
||||||
color: var(--text-secondary);
|
color: var(--text-tertiary);
|
||||||
font-size: $font-regular;
|
font-size: $font-regular;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Indicator {
|
.indicator {
|
||||||
$diameter: 20px;
|
$diameter: 20px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,12 @@ const SearchFilterCheckboxItem = (props: Props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.CheckboxItem
|
<DropdownMenu.CheckboxItem
|
||||||
className="Item"
|
className={styles.item}
|
||||||
checked={props.checked || false}
|
checked={props.checked || false}
|
||||||
onCheckedChange={handleCheckedChange}
|
onCheckedChange={handleCheckedChange}
|
||||||
onSelect={(event) => event.preventDefault()}
|
onSelect={(event) => event.preventDefault()}
|
||||||
>
|
>
|
||||||
<DropdownMenu.ItemIndicator className="Indicator">
|
<DropdownMenu.ItemIndicator className={styles.indicator}>
|
||||||
<CheckIcon />
|
<CheckIcon />
|
||||||
</DropdownMenu.ItemIndicator>
|
</DropdownMenu.ItemIndicator>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
.filterBar {
|
||||||
|
display: flex;
|
||||||
|
gap: $unit;
|
||||||
|
padding: $unit-half $unit-3x;
|
||||||
|
|
||||||
|
@include breakpoint(phone) {
|
||||||
|
display: grid;
|
||||||
|
gap: $unit;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -72,10 +72,10 @@ const SummonSearchFilterBar = (props: Props) => {
|
||||||
sendFilters()
|
sendFilters()
|
||||||
}, [rarityState, elementState])
|
}, [rarityState, elementState])
|
||||||
|
|
||||||
return (
|
const rarityFilter = (
|
||||||
<div className="SearchFilterBar">
|
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.rarity')}
|
label={t('filters.labels.rarity')}
|
||||||
|
display="list"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(rarityState)
|
Object.values(rarityState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -84,9 +84,6 @@ const SummonSearchFilterBar = (props: Props) => {
|
||||||
open={rarityMenu}
|
open={rarityMenu}
|
||||||
onOpenChange={rarityMenuOpened}
|
onOpenChange={rarityMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
|
||||||
{t('filters.labels.rarity')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
{Array.from(Array(rarities.length)).map((x, i) => {
|
{Array.from(Array(rarities.length)).map((x, i) => {
|
||||||
return (
|
return (
|
||||||
<SearchFilterCheckboxItem
|
<SearchFilterCheckboxItem
|
||||||
|
|
@ -100,9 +97,12 @@ const SummonSearchFilterBar = (props: Props) => {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
|
)
|
||||||
|
|
||||||
|
const elementFilter = (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.element')}
|
label={t('filters.labels.element')}
|
||||||
|
display="list"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(elementState)
|
Object.values(elementState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -111,9 +111,6 @@ const SummonSearchFilterBar = (props: Props) => {
|
||||||
open={elementMenu}
|
open={elementMenu}
|
||||||
onOpenChange={elementMenuOpened}
|
onOpenChange={elementMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
|
||||||
{t('filters.labels.element')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
{Array.from(Array(elements.length)).map((x, i) => {
|
{Array.from(Array(elements.length)).map((x, i) => {
|
||||||
return (
|
return (
|
||||||
<SearchFilterCheckboxItem
|
<SearchFilterCheckboxItem
|
||||||
|
|
@ -127,6 +124,12 @@ const SummonSearchFilterBar = (props: Props) => {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.filterBar}>
|
||||||
|
{rarityFilter}
|
||||||
|
{elementFilter}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
.filterBar {
|
||||||
|
display: flex;
|
||||||
|
gap: $unit;
|
||||||
|
padding: $unit-half $unit-3x;
|
||||||
|
|
||||||
|
@include breakpoint(phone) {
|
||||||
|
display: grid;
|
||||||
|
gap: $unit;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,6 +40,10 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
emptyWeaponSeriesState
|
emptyWeaponSeriesState
|
||||||
)
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
sendFilters()
|
||||||
|
}, [rarityState, elementState, proficiencyState, seriesState])
|
||||||
|
|
||||||
function rarityMenuOpened(open: boolean) {
|
function rarityMenuOpened(open: boolean) {
|
||||||
if (open) {
|
if (open) {
|
||||||
setRarityMenu(true)
|
setRarityMenu(true)
|
||||||
|
|
@ -124,54 +128,49 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
props.sendFilters(filters)
|
props.sendFilters(filters)
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderWeaponSeries = () => {
|
const renderProficiencies = () => {
|
||||||
const numColumns = 3
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<>
|
||||||
{Array.from({ length: numColumns }, () => 0).map((x, i) => {
|
{proficiencies.map((x, i) => {
|
||||||
return renderWeaponSeriesGroup(i)
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderWeaponSeriesGroup = (index: number) => {
|
|
||||||
return (
|
|
||||||
<DropdownMenu.Group className="Group" key={`Group-${index}`}>
|
|
||||||
{weaponSeries
|
|
||||||
.slice(
|
|
||||||
index * Math.ceil(weaponSeries.length / 3),
|
|
||||||
(index + 1) * Math.ceil(weaponSeries.length / 3)
|
|
||||||
)
|
|
||||||
.map((x, i) => {
|
|
||||||
return renderSingleWeaponSeries(x.id, x.slug)
|
|
||||||
})}
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderSingleWeaponSeries = (id: number, slug: string) => {
|
|
||||||
return (
|
return (
|
||||||
<SearchFilterCheckboxItem
|
<SearchFilterCheckboxItem
|
||||||
key={slug}
|
key={x}
|
||||||
onCheckedChange={handleSeriesChange}
|
onCheckedChange={handleProficiencyChange}
|
||||||
checked={seriesState[slug].checked}
|
checked={proficiencyState[x].checked}
|
||||||
valueKey={slug}
|
valueKey={x}
|
||||||
>
|
>
|
||||||
{t(`series.${slug}`)}
|
{t(`proficiencies.${x}`)}
|
||||||
</SearchFilterCheckboxItem>
|
</SearchFilterCheckboxItem>
|
||||||
)
|
)
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
const renderWeaponSeries = () => {
|
||||||
sendFilters()
|
|
||||||
}, [rarityState, elementState, proficiencyState, seriesState])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="SearchFilterBar">
|
<>
|
||||||
|
{weaponSeries.map((x, i) => {
|
||||||
|
return (
|
||||||
|
<SearchFilterCheckboxItem
|
||||||
|
key={x.slug}
|
||||||
|
onCheckedChange={handleSeriesChange}
|
||||||
|
checked={seriesState[x.slug].checked}
|
||||||
|
valueKey={x.slug}
|
||||||
|
>
|
||||||
|
{t(`series.${x.slug}`)}
|
||||||
|
</SearchFilterCheckboxItem>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const rarityFilter = (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.rarity')}
|
label={t('filters.labels.rarity')}
|
||||||
key="rarity"
|
key="rarity"
|
||||||
|
display="list"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(rarityState)
|
Object.values(rarityState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -180,9 +179,6 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
open={rarityMenu}
|
open={rarityMenu}
|
||||||
onOpenChange={rarityMenuOpened}
|
onOpenChange={rarityMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
|
||||||
{t('filters.labels.rarity')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
{Array.from(Array(rarities.length)).map((x, i) => {
|
{Array.from(Array(rarities.length)).map((x, i) => {
|
||||||
return (
|
return (
|
||||||
<SearchFilterCheckboxItem
|
<SearchFilterCheckboxItem
|
||||||
|
|
@ -196,10 +192,13 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
|
)
|
||||||
|
|
||||||
|
const elementFilter = (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.element')}
|
label={t('filters.labels.element')}
|
||||||
key="element"
|
key="element"
|
||||||
|
display="list"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(elementState)
|
Object.values(elementState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -208,9 +207,6 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
open={elementMenu}
|
open={elementMenu}
|
||||||
onOpenChange={elementMenuOpened}
|
onOpenChange={elementMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
|
||||||
{t('filters.labels.element')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
{Array.from(Array(elements.length)).map((x, i) => {
|
{Array.from(Array(elements.length)).map((x, i) => {
|
||||||
return (
|
return (
|
||||||
<SearchFilterCheckboxItem
|
<SearchFilterCheckboxItem
|
||||||
|
|
@ -224,10 +220,13 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
|
)
|
||||||
|
|
||||||
|
const proficiencyFilter = (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.proficiency')}
|
label={t('filters.labels.proficiency')}
|
||||||
key="proficiency"
|
key="proficiency"
|
||||||
|
display="grid"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(proficiencyState)
|
Object.values(proficiencyState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -236,52 +235,15 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
open={proficiencyMenu}
|
open={proficiencyMenu}
|
||||||
onOpenChange={proficiencyMenuOpened}
|
onOpenChange={proficiencyMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
{renderProficiencies()}
|
||||||
{t('filters.labels.proficiency')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
<section>
|
|
||||||
<DropdownMenu.Group className="Group">
|
|
||||||
{Array.from(Array(proficiencies.length / 2)).map((x, i) => {
|
|
||||||
return (
|
|
||||||
<SearchFilterCheckboxItem
|
|
||||||
key={proficiencies[i]}
|
|
||||||
onCheckedChange={handleProficiencyChange}
|
|
||||||
checked={proficiencyState[proficiencies[i]].checked}
|
|
||||||
valueKey={proficiencies[i]}
|
|
||||||
>
|
|
||||||
{t(`proficiencies.${proficiencies[i]}`)}
|
|
||||||
</SearchFilterCheckboxItem>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
<DropdownMenu.Group className="Group">
|
|
||||||
{Array.from(Array(proficiencies.length / 2)).map((x, i) => {
|
|
||||||
return (
|
|
||||||
<SearchFilterCheckboxItem
|
|
||||||
key={proficiencies[i + proficiencies.length / 2]}
|
|
||||||
onCheckedChange={handleProficiencyChange}
|
|
||||||
checked={
|
|
||||||
proficiencyState[
|
|
||||||
proficiencies[i + proficiencies.length / 2]
|
|
||||||
].checked
|
|
||||||
}
|
|
||||||
valueKey={proficiencies[i + proficiencies.length / 2]}
|
|
||||||
>
|
|
||||||
{t(
|
|
||||||
`proficiencies.${
|
|
||||||
proficiencies[i + proficiencies.length / 2]
|
|
||||||
}`
|
|
||||||
)}
|
|
||||||
</SearchFilterCheckboxItem>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
</section>
|
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
|
)
|
||||||
|
|
||||||
|
const seriesFilter = (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
label={t('filters.labels.series')}
|
label={t('filters.labels.series')}
|
||||||
key="series"
|
key="series"
|
||||||
|
display="grid"
|
||||||
numSelected={
|
numSelected={
|
||||||
Object.values(seriesState)
|
Object.values(seriesState)
|
||||||
.map((x) => x.checked)
|
.map((x) => x.checked)
|
||||||
|
|
@ -290,12 +252,17 @@ const WeaponSearchFilterBar = (props: Props) => {
|
||||||
open={seriesMenu}
|
open={seriesMenu}
|
||||||
onOpenChange={seriesMenuOpened}
|
onOpenChange={seriesMenuOpened}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Label className="Label">
|
{renderWeaponSeries()}
|
||||||
{t('filters.labels.series')}
|
|
||||||
</DropdownMenu.Label>
|
|
||||||
<section>{renderWeaponSeries()}</section>
|
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
</div>
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className={styles.filterBar}>
|
||||||
|
{rarityFilter}
|
||||||
|
{elementFilter}
|
||||||
|
{proficiencyFilter}
|
||||||
|
{seriesFilter}
|
||||||
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue