Improve battlesuit filter behavior
This commit is contained in:
@@ -8,7 +8,7 @@ interface FilterButtonProps {
|
|||||||
active?: boolean
|
active?: boolean
|
||||||
icon?: string
|
icon?: string
|
||||||
label: string
|
label: string
|
||||||
value: string
|
href: string
|
||||||
m?: string | number
|
m?: string | number
|
||||||
close?: () => void
|
close?: () => void
|
||||||
}
|
}
|
||||||
@@ -17,14 +17,14 @@ const FilterButton = ({
|
|||||||
active = false,
|
active = false,
|
||||||
icon,
|
icon,
|
||||||
label,
|
label,
|
||||||
value,
|
href,
|
||||||
m,
|
m,
|
||||||
close,
|
close,
|
||||||
}: FilterButtonProps) => {
|
}: FilterButtonProps) => {
|
||||||
const { push } = useRouter()
|
const { push } = useRouter()
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={`?filter=${value}`}
|
href={href}
|
||||||
m={m}
|
m={m}
|
||||||
py={1}
|
py={1}
|
||||||
px={2}
|
px={2}
|
||||||
@@ -36,7 +36,7 @@ const FilterButton = ({
|
|||||||
if (close != null) {
|
if (close != null) {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
push({ query: { filter: value } }, undefined, { shallow: true })
|
push(href, href, { shallow: true })
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{icon != null && (
|
{icon != null && (
|
||||||
|
|||||||
@@ -54,26 +54,43 @@ const BattlesuitListPage = ({ battlesuits }: BattlesuitListPageProps) => {
|
|||||||
setHiddenFilters(true)
|
setHiddenFilters(true)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const filter = useMemo(() => {
|
const valkyrieFilter = useMemo(() => {
|
||||||
if (query.filter == null) {
|
if (query.valkyrie == null) {
|
||||||
return 'all'
|
return 'all'
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeof query.filter === 'string' ? query.filter : query.filter[0]
|
return typeof query.valkyrie === 'string'
|
||||||
|
? query.valkyrie
|
||||||
|
: query.valkyrie[0]
|
||||||
}, [query])
|
}, [query])
|
||||||
|
|
||||||
const battlesuitList = useMemo(() => {
|
const featureFilter = useMemo(() => {
|
||||||
return battlesuits.map((battlesuit) => {
|
if (query.feature == null) {
|
||||||
const hidden = isBattlesuitHidden(battlesuit, filter)
|
return 'all'
|
||||||
return (
|
}
|
||||||
<BattlesuitCard
|
|
||||||
key={battlesuit.id}
|
return typeof query.feature === 'string' ? query.feature : query.feature[0]
|
||||||
battlesuit={battlesuit}
|
}, [query])
|
||||||
hidden={hidden}
|
|
||||||
/>
|
const battlesuitsFiteredByValkyrie = useMemo(() => {
|
||||||
)
|
return battlesuits.filter((battlesuit) =>
|
||||||
})
|
isValkyrieFilterMatching(battlesuit, valkyrieFilter)
|
||||||
}, [battlesuits, filter])
|
)
|
||||||
|
}, [battlesuits, valkyrieFilter])
|
||||||
|
|
||||||
|
const availableFeatureSet = battlesuitsFiteredByValkyrie.reduce(
|
||||||
|
(set, battlesuit) => {
|
||||||
|
battlesuit.features.forEach((feature) => set.add(feature))
|
||||||
|
return set
|
||||||
|
},
|
||||||
|
new Set()
|
||||||
|
)
|
||||||
|
|
||||||
|
const battlesuitsFilteredByFeature = useMemo(() => {
|
||||||
|
return battlesuitsFiteredByValkyrie.filter((battlesuit) =>
|
||||||
|
isFeatureFilterMatching(battlesuit, featureFilter)
|
||||||
|
)
|
||||||
|
}, [battlesuitsFiteredByValkyrie, featureFilter])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Honkai3rdLayout>
|
<Honkai3rdLayout>
|
||||||
@@ -117,14 +134,14 @@ const BattlesuitListPage = ({ battlesuits }: BattlesuitListPageProps) => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Heading as='h3'>{t('battlesuits-list.filter-by-features')}</Heading>
|
<Heading as='h3'>{t('battlesuits-list.filter-by-valkyries')}</Heading>
|
||||||
<Flex mb={2} sx={{ flexWrap: 'wrap' }}>
|
<Flex mb={2} sx={{ flexWrap: 'wrap' }}>
|
||||||
{featureFilterOptions.map(({ value, label, icon, krLabel }) => {
|
{valkyrieFilterOptions.map(({ value, label, icon, krLabel }) => {
|
||||||
return (
|
return (
|
||||||
<FilterButton
|
<FilterButton
|
||||||
key={value}
|
key={value}
|
||||||
active={value === filter}
|
active={value === valkyrieFilter}
|
||||||
value={value}
|
href={`?valkyrie=${value}`}
|
||||||
label={translate(locale, { 'ko-KR': krLabel }, label)}
|
label={translate(locale, { 'ko-KR': krLabel }, label)}
|
||||||
icon={icon}
|
icon={icon}
|
||||||
m={1}
|
m={1}
|
||||||
@@ -133,22 +150,28 @@ const BattlesuitListPage = ({ battlesuits }: BattlesuitListPageProps) => {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<Heading as='h3'>{t('battlesuits-list.filter-by-features')}</Heading>
|
||||||
<Heading as='h3'>{t('battlesuits-list.filter-by-valkyries')}</Heading>
|
|
||||||
<Flex mb={2} sx={{ flexWrap: 'wrap' }}>
|
<Flex mb={2} sx={{ flexWrap: 'wrap' }}>
|
||||||
{valkyrieFilterOptions.map(({ value, label, icon, krLabel }) => {
|
{featureFilterOptions
|
||||||
return (
|
.filter((filterOption) => {
|
||||||
<FilterButton
|
if (filterOption.value === 'all') {
|
||||||
key={value}
|
return true
|
||||||
active={value === filter}
|
}
|
||||||
value={value}
|
return availableFeatureSet.has(filterOption.value)
|
||||||
label={translate(locale, { 'ko-KR': krLabel }, label)}
|
})
|
||||||
icon={icon}
|
.map(({ value, label, icon, krLabel }) => {
|
||||||
m={1}
|
return (
|
||||||
close={closeFilters}
|
<FilterButton
|
||||||
/>
|
key={value}
|
||||||
)
|
active={value === featureFilter}
|
||||||
})}
|
href={`?valkyrie=${valkyrieFilter}&feature=${value}`}
|
||||||
|
label={translate(locale, { 'ko-KR': krLabel }, label)}
|
||||||
|
icon={icon}
|
||||||
|
m={1}
|
||||||
|
close={closeFilters}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -158,7 +181,11 @@ const BattlesuitListPage = ({ battlesuits }: BattlesuitListPageProps) => {
|
|||||||
justifyContent: 'space-around',
|
justifyContent: 'space-around',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{battlesuitList}
|
{battlesuitsFilteredByFeature.map((battlesuit) => {
|
||||||
|
return (
|
||||||
|
<BattlesuitCard key={battlesuit.id} battlesuit={battlesuit} />
|
||||||
|
)
|
||||||
|
})}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
</Honkai3rdLayout>
|
</Honkai3rdLayout>
|
||||||
@@ -184,36 +211,17 @@ export async function getStaticProps({ locale }: NextPageContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBattlesuitHidden(
|
function isValkyrieFilterMatching(
|
||||||
battlesuit: BattlesuitListItemData,
|
battlesuit: BattlesuitListItemData,
|
||||||
filter: string
|
valkyrieFilter: string
|
||||||
): boolean {
|
) {
|
||||||
switch (filter) {
|
switch (valkyrieFilter) {
|
||||||
case 'physical':
|
|
||||||
case 'fire-dmg':
|
|
||||||
case 'ice-dmg':
|
|
||||||
case 'lightning-dmg':
|
|
||||||
case 'freeze':
|
|
||||||
case 'paralyze':
|
|
||||||
case 'stun':
|
|
||||||
case 'ignite':
|
|
||||||
case 'bleed':
|
|
||||||
case 'heavy-atk':
|
|
||||||
case 'weaken':
|
|
||||||
case 'impair':
|
|
||||||
case 'time mastery':
|
|
||||||
case 'gather':
|
|
||||||
case 'heal':
|
|
||||||
case 'fast atk':
|
|
||||||
case 'burst':
|
|
||||||
case 'aerial':
|
|
||||||
return !battlesuit.features.some((feature) => feature === filter)
|
|
||||||
case 'mecha':
|
case 'mecha':
|
||||||
case 'biologic':
|
case 'biologic':
|
||||||
case 'psychic':
|
case 'psychic':
|
||||||
case 'quantum':
|
case 'quantum':
|
||||||
case 'imaginary':
|
case 'imaginary':
|
||||||
return battlesuit.type !== filter
|
return battlesuit.type === valkyrieFilter
|
||||||
case 'kiana':
|
case 'kiana':
|
||||||
case 'mei':
|
case 'mei':
|
||||||
case 'bronya':
|
case 'bronya':
|
||||||
@@ -237,9 +245,19 @@ function isBattlesuitHidden(
|
|||||||
case 'eden':
|
case 'eden':
|
||||||
case 'griseo':
|
case 'griseo':
|
||||||
case 'vill-v':
|
case 'vill-v':
|
||||||
return battlesuit.valkyrie !== filter
|
return battlesuit.valkyrie === valkyrieFilter
|
||||||
default:
|
default:
|
||||||
case 'all':
|
case 'all':
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isFeatureFilterMatching(
|
||||||
|
battlesuit: BattlesuitListItemData,
|
||||||
|
featureFilter: string
|
||||||
|
) {
|
||||||
|
if (featureFilter === 'all') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return battlesuit.features.some((feature) => feature === featureFilter)
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,20 +41,22 @@ const WeaponListPage = ({ weaponDataList }: WeaponListPageProps) => {
|
|||||||
const { query, locale } = useRouter()
|
const { query, locale } = useRouter()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const filter = useMemo(() => {
|
const categoryFilter = useMemo(() => {
|
||||||
if (query.filter == null) {
|
if (query.category == null) {
|
||||||
return 'all'
|
return 'all'
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeof query.filter === 'string' ? query.filter : query.filter[0]
|
return typeof query.category === 'string'
|
||||||
|
? query.category
|
||||||
|
: query.category[0]
|
||||||
}, [query])
|
}, [query])
|
||||||
|
|
||||||
const weaponList = useMemo(() => {
|
const weaponList = useMemo(() => {
|
||||||
return weaponDataList.map((weapon) => {
|
return weaponDataList.map((weapon) => {
|
||||||
const hidden = isWeaponHidden(weapon, filter)
|
const hidden = isWeaponHidden(weapon, categoryFilter)
|
||||||
return <WeaponCard key={weapon.id} weapon={weapon} hidden={hidden} />
|
return <WeaponCard key={weapon.id} weapon={weapon} hidden={hidden} />
|
||||||
})
|
})
|
||||||
}, [weaponDataList, filter])
|
}, [weaponDataList, categoryFilter])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Honkai3rdLayout>
|
<Honkai3rdLayout>
|
||||||
@@ -82,8 +84,8 @@ const WeaponListPage = ({ weaponDataList }: WeaponListPageProps) => {
|
|||||||
return (
|
return (
|
||||||
<FilterButton
|
<FilterButton
|
||||||
key={value}
|
key={value}
|
||||||
active={value === filter}
|
href={`?category=${value}`}
|
||||||
value={value}
|
active={value === categoryFilter}
|
||||||
label={translate(locale, { 'ko-KR': krLabel }, label)}
|
label={translate(locale, { 'ko-KR': krLabel }, label)}
|
||||||
m={1}
|
m={1}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
"downlevelIteration": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"baseUrl": "./src"
|
"baseUrl": "./src"
|
||||||
|
|||||||
Reference in New Issue
Block a user