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 elementFilters = $state<number[]>([])
let rarityFilters = $state<number[]>([]) let rarityFilters = $state<number[]>([])
let seasonFilters = $state<number[]>([]) let seasonFilters = $state<number[]>([])
let seriesFilters = $state<number[]>([]) let seriesFilters = $state<(number | string)[]>([])
let raceFilters = $state<number[]>([]) let raceFilters = $state<number[]>([])
let proficiencyFilters = $state<number[]>([]) let proficiencyFilters = $state<number[]>([])
let genderFilters = $state<number[]>([]) let genderFilters = $state<number[]>([])

View file

@ -7,6 +7,8 @@
import MultiSelect from '$lib/components/ui/MultiSelect.svelte' import MultiSelect from '$lib/components/ui/MultiSelect.svelte'
import Select from '$lib/components/ui/Select.svelte' import Select from '$lib/components/ui/Select.svelte'
import Icon from '$lib/components/Icon.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' type EntityType = 'character' | 'weapon' | 'summon'
@ -16,7 +18,8 @@
elementFilters?: number[] elementFilters?: number[]
rarityFilters?: number[] rarityFilters?: number[]
seasonFilters?: number[] seasonFilters?: number[]
seriesFilters?: number[] /** Series filters - number[] for characters, string[] for weapons (UUIDs) */
seriesFilters?: (number | string)[]
raceFilters?: number[] raceFilters?: number[]
proficiencyFilters?: number[] proficiencyFilters?: number[]
genderFilters?: number[] genderFilters?: number[]
@ -47,7 +50,8 @@
element: number[] element: number[]
rarity: number[] rarity: number[]
season: number[] season: number[]
series: number[] /** Series filters - number[] for characters, string[] for weapons (UUIDs) */
series: (number | string)[]
race: number[] race: number[]
proficiency: number[] proficiency: number[]
gender: number[] gender: number[]
@ -149,17 +153,44 @@
{ value: 10, label: 'Katana' } { 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 // Convert record maps to arrays for iteration
const seasons = Object.entries(CHARACTER_SEASON_NAMES).map(([value, label]) => ({ const seasons = Object.entries(CHARACTER_SEASON_NAMES).map(([value, label]) => ({
value: Number(value), value: Number(value),
label 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), value: Number(value),
label 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) const races = Object.entries(RACE_LABELS)
.filter(([value]) => Number(value) !== 0) // Exclude Unknown .filter(([value]) => Number(value) !== 0) // Exclude Unknown
.map(([value, label]) => ({ .map(([value, label]) => ({
@ -201,7 +232,7 @@
emitChange() emitChange()
} }
function handleSeriesChange(value: number[]) { function handleSeriesChange(value: (number | string)[]) {
seriesFilters = value seriesFilters = value
emitChange() emitChange()
} }
@ -281,7 +312,7 @@
{#if effectiveShowFilters.series} {#if effectiveShowFilters.series}
<MultiSelect <MultiSelect
options={series} options={seriesOptions}
bind:value={seriesFilters} bind:value={seriesFilters}
onValueChange={handleSeriesChange} onValueChange={handleSeriesChange}
placeholder={entityType === 'weapon' ? 'Weapon Series' : 'Series'} placeholder={entityType === 'weapon' ? 'Weapon Series' : 'Series'}

View file

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

View file

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