fetch weapon series from API in collection filters

This commit is contained in:
Justin Edmund 2025-12-03 11:59:26 -08:00
parent a251240331
commit 139e602808
4 changed files with 54 additions and 22 deletions

View file

@ -45,7 +45,7 @@
let elementFilters = $state<number[]>([])
let rarityFilters = $state<number[]>([])
let seasonFilters = $state<number[]>([])
let seriesFilters = $state<number[]>([])
let seriesFilters = $state<(number | string)[]>([])
let raceFilters = $state<number[]>([])
let proficiencyFilters = $state<number[]>([])
let genderFilters = $state<number[]>([])

View file

@ -7,6 +7,8 @@
import MultiSelect from '$lib/components/ui/MultiSelect.svelte'
import Select from '$lib/components/ui/Select.svelte'
import Icon from '$lib/components/Icon.svelte'
import { createQuery, queryOptions } from '@tanstack/svelte-query'
import { entityAdapter } from '$lib/api/adapters/entity.adapter'
type EntityType = 'character' | 'weapon' | 'summon'
@ -16,7 +18,8 @@
elementFilters?: number[]
rarityFilters?: number[]
seasonFilters?: number[]
seriesFilters?: number[]
/** Series filters - number[] for characters, string[] for weapons (UUIDs) */
seriesFilters?: (number | string)[]
raceFilters?: number[]
proficiencyFilters?: number[]
genderFilters?: number[]
@ -47,7 +50,8 @@
element: number[]
rarity: number[]
season: number[]
series: number[]
/** Series filters - number[] for characters, string[] for weapons (UUIDs) */
series: (number | string)[]
race: number[]
proficiency: number[]
gender: number[]
@ -149,17 +153,44 @@
{ value: 10, label: 'Katana' }
]
// Fetch weapon series from API (only when entityType is weapon)
const weaponSeriesQuery = createQuery(() =>
queryOptions({
queryKey: ['weaponSeries', 'list'] as const,
queryFn: () => entityAdapter.getWeaponSeriesList(),
enabled: entityType === 'weapon',
staleTime: 1000 * 60 * 60, // 1 hour
gcTime: 1000 * 60 * 60 * 24 // 24 hours
})
)
// Convert record maps to arrays for iteration
const seasons = Object.entries(CHARACTER_SEASON_NAMES).map(([value, label]) => ({
value: Number(value),
label
}))
const series = Object.entries(CHARACTER_SERIES_NAMES).map(([value, label]) => ({
// Character series (hardcoded enum)
const characterSeries = Object.entries(CHARACTER_SERIES_NAMES).map(([value, label]) => ({
value: Number(value),
label
}))
// Build series options based on entity type
// For weapons: use API-fetched series with string IDs
// For characters: use hardcoded enum with number values
const seriesOptions = $derived.by(() => {
if (entityType === 'weapon' && weaponSeriesQuery.data) {
return weaponSeriesQuery.data
.sort((a, b) => a.order - b.order)
.map((s) => ({
value: s.id,
label: s.name.en
}))
}
return characterSeries
})
const races = Object.entries(RACE_LABELS)
.filter(([value]) => Number(value) !== 0) // Exclude Unknown
.map(([value, label]) => ({
@ -201,7 +232,7 @@
emitChange()
}
function handleSeriesChange(value: number[]) {
function handleSeriesChange(value: (number | string)[]) {
seriesFilters = value
emitChange()
}
@ -281,7 +312,7 @@
{#if effectiveShowFilters.series}
<MultiSelect
options={series}
options={seriesOptions}
bind:value={seriesFilters}
onValueChange={handleSeriesChange}
placeholder={entityType === 'weapon' ? 'Weapon Series' : 'Series'}

View file

@ -19,6 +19,7 @@
import Button from '$lib/components/ui/Button.svelte'
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
import { getElementIcon } from '$lib/utils/images'
import { seriesHasWeaponKeys, getSeriesSlug } from '$lib/utils/weaponSeries'
export interface WeaponEditValues {
uncapLevel: number
@ -106,21 +107,21 @@
// Derived conditions
const canChangeElement = $derived(weaponData?.element === 0)
const series = $derived(weaponData?.series ?? 0)
const series = $derived(weaponData?.series)
const seriesSlug = $derived(getSeriesSlug(series))
// Weapon key config keyed by WEAPON series
const WEAPON_KEY_SERIES: Record<number, { name: string; slots: number; keySeries: number }> = {
2: { name: 'Dark Opus', slots: 2, keySeries: 3 },
3: { name: 'Ultima', slots: 3, keySeries: 13 },
17: { name: 'Draconic', slots: 2, keySeries: 27 },
22: { name: 'Astral', slots: 1, keySeries: 19 },
34: { name: 'Superlative', slots: 2, keySeries: 40 }
// Weapon key slot configuration by series slug
const WEAPON_KEY_SLOTS: Record<string, number> = {
'dark-opus': 2,
'ultima': 3,
'draconic': 2,
'draconic-providence': 2,
'superlative': 2
}
const weaponKeyConfig = $derived(WEAPON_KEY_SERIES[series])
const hasWeaponKeys = $derived(!!weaponKeyConfig)
const keySlotCount = $derived(weaponKeyConfig?.slots ?? 0)
const keySeries = $derived(weaponKeyConfig?.keySeries ?? 0)
// Check if series has weapon keys using the utility (handles both formats)
const hasWeaponKeys = $derived(seriesHasWeaponKeys(series))
const keySlotCount = $derived(seriesSlug ? (WEAPON_KEY_SLOTS[seriesSlug] ?? 2) : 0)
const hasAxSkills = $derived(weaponData?.ax === true)
const axType = $derived(weaponData?.axType ?? 1)
@ -272,7 +273,7 @@
<div class="section-content key-selects">
{#if keySlotCount >= 1}
<WeaponKeySelect
series={keySeries}
{seriesSlug}
slot={0}
bind:value={weaponKey1}
{transcendenceStep}
@ -280,7 +281,7 @@
{/if}
{#if keySlotCount >= 2}
<WeaponKeySelect
series={keySeries}
{seriesSlug}
slot={1}
bind:value={weaponKey2}
{transcendenceStep}
@ -288,7 +289,7 @@
{/if}
{#if keySlotCount >= 3}
<WeaponKeySelect
series={keySeries}
{seriesSlug}
slot={2}
bind:value={weaponKey3}
{transcendenceStep}

View file

@ -20,7 +20,7 @@
let elementFilters = $state<number[]>([])
let rarityFilters = $state<number[]>([])
let proficiencyFilters = $state<number[]>([])
let seriesFilters = $state<number[]>([])
let seriesFilters = $state<(number | string)[]>([])
// Sort state
let sortBy = $state<CollectionSortKey>('name_asc')