From 90e5ded9421589e2c5e4dfe89e32c11886e32bd1 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 4 Jan 2026 14:43:53 -0800 Subject: [PATCH] add maxExorcismLevel to weapons (#452) ## Summary - add `maxExorcismLevel` to Weapon type - add field to WeaponStatsSection in database pages (with min=1 validation) - include in new/edit/import page payloads - make BefoulmentSelect exorcism options dynamic (0 to maxExorcismLevel) - pass maxExorcismLevel to BefoulmentSelect from edit panes ## Test plan - [ ] verify maxExorcismLevel field appears in weapon stats section - [ ] verify min=1 validation works - [ ] verify exorcism dropdown shows correct options based on weapon's maxExorcismLevel --- .../collection/WeaponEditPane.svelte | 1 + .../sidebar/EditWeaponSidebar.svelte | 1 + .../sidebar/edit/BefoulmentSelect.svelte | 21 ++++++++++--------- src/lib/components/ui/DetailItem.svelte | 10 ++++++++- .../sections/WeaponStatsSection.svelte | 12 +++++++++++ src/lib/types/api/entities.ts | 1 + .../weapons/[granblueId]/edit/+page.svelte | 3 +++ .../database/weapons/import/+page.svelte | 8 ++++--- .../(app)/database/weapons/new/+page.svelte | 2 ++ 9 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/lib/components/collection/WeaponEditPane.svelte b/src/lib/components/collection/WeaponEditPane.svelte index 1e91e251..999d5399 100644 --- a/src/lib/components/collection/WeaponEditPane.svelte +++ b/src/lib/components/collection/WeaponEditPane.svelte @@ -302,6 +302,7 @@ onChange={(bef) => { befoulment = bef }} + maxExorcismLevel={weaponData?.maxExorcismLevel} /> diff --git a/src/lib/components/sidebar/EditWeaponSidebar.svelte b/src/lib/components/sidebar/EditWeaponSidebar.svelte index f78a582a..13f1bd85 100644 --- a/src/lib/components/sidebar/EditWeaponSidebar.svelte +++ b/src/lib/components/sidebar/EditWeaponSidebar.svelte @@ -328,6 +328,7 @@ onChange={(bef) => { befoulment = bef }} + maxExorcismLevel={weaponData?.maxExorcismLevel} /> diff --git a/src/lib/components/sidebar/edit/BefoulmentSelect.svelte b/src/lib/components/sidebar/edit/BefoulmentSelect.svelte index 0fc3a02f..8c89236d 100644 --- a/src/lib/components/sidebar/edit/BefoulmentSelect.svelte +++ b/src/lib/components/sidebar/edit/BefoulmentSelect.svelte @@ -12,9 +12,11 @@ onChange?: (befoulment: Befoulment | null) => void /** Language for display */ locale?: 'en' | 'ja' + /** Maximum exorcism level for this weapon (from weapon's maxExorcismLevel) */ + maxExorcismLevel?: number | null } - let { currentBefoulment = null, onChange, locale = 'en' }: Props = $props() + let { currentBefoulment = null, onChange, locale = 'en', maxExorcismLevel = null }: Props = $props() const { befoulments, findBefoulment, isLoading } = useWeaponStatModifiers() @@ -44,15 +46,14 @@ return items }) - // Exorcism level options (0-5) - const exorcismOptions: Array<{ value: number; label: string }> = [ - { value: 0, label: 'Level 0 (Full Effect)' }, - { value: 1, label: 'Level 1' }, - { value: 2, label: 'Level 2' }, - { value: 3, label: 'Level 3' }, - { value: 4, label: 'Level 4' }, - { value: 5, label: 'Level 5 (Fully Exorcised)' } - ] + // Exorcism level options (0 to maxExorcismLevel, fallback to 5) + const exorcismOptions = $derived.by(() => { + const max = maxExorcismLevel ?? 5 + return Array.from({ length: max + 1 }, (_, i) => ({ + value: i, + label: `Level ${i}` + })) + }) // Get suffix for display function getSuffix(modifier: WeaponStatModifier | undefined): string { diff --git a/src/lib/components/ui/DetailItem.svelte b/src/lib/components/ui/DetailItem.svelte index 1163f836..98c26059 100644 --- a/src/lib/components/ui/DetailItem.svelte +++ b/src/lib/components/ui/DetailItem.svelte @@ -28,7 +28,9 @@ onchange, width, linkUrl, - hasLinkButton = false + hasLinkButton = false, + min, + max }: { label: string /** Secondary label displayed below the main label */ @@ -48,6 +50,10 @@ linkUrl?: string | null /** Whether to show the link button (disabled when linkUrl is empty) */ hasLinkButton?: boolean + /** Minimum value for number inputs */ + min?: number + /** Maximum value for number inputs */ + max?: number } = $props() // For checkbox type, derive the checked state from value @@ -110,6 +116,8 @@ contained={true} {placeholder} alignRight={true} + {min} + {max} /> {:else if type === 'date'} diff --git a/src/lib/features/database/weapons/sections/WeaponStatsSection.svelte b/src/lib/features/database/weapons/sections/WeaponStatsSection.svelte index a1b43ffc..7efeb464 100644 --- a/src/lib/features/database/weapons/sections/WeaponStatsSection.svelte +++ b/src/lib/features/database/weapons/sections/WeaponStatsSection.svelte @@ -158,6 +158,15 @@ type="number" placeholder="0" /> + {:else} {#if weapon.maxSkillLevel} @@ -166,5 +175,8 @@ {#if weapon.maxAwakeningLevel} {/if} + {#if weapon.maxExorcismLevel != null} + + {/if} {/if} diff --git a/src/lib/types/api/entities.ts b/src/lib/types/api/entities.ts index 31047a8e..b5371d91 100644 --- a/src/lib/types/api/entities.ts +++ b/src/lib/types/api/entities.ts @@ -20,6 +20,7 @@ export interface Weapon { maxLevel: number maxSkillLevel: number maxAwakeningLevel: number + maxExorcismLevel?: number | null /** Weapon series - object with slug/name/flags */ series: WeaponSeriesRef | null ax: boolean diff --git a/src/routes/(app)/database/weapons/[granblueId]/edit/+page.svelte b/src/routes/(app)/database/weapons/[granblueId]/edit/+page.svelte index 76dec8e3..fd83d041 100644 --- a/src/routes/(app)/database/weapons/[granblueId]/edit/+page.svelte +++ b/src/routes/(app)/database/weapons/[granblueId]/edit/+page.svelte @@ -87,6 +87,7 @@ maxLevel: 100, maxSkillLevel: 10, maxAwakeningLevel: 0, + maxExorcismLevel: null as number | null, flb: false, ulb: false, transcendence: false, @@ -134,6 +135,7 @@ maxLevel: weapon.maxLevel || 100, maxSkillLevel: weapon.maxSkillLevel || 10, maxAwakeningLevel: weapon.maxAwakeningLevel || 0, + maxExorcismLevel: weapon.maxExorcismLevel ?? null, flb: weapon.uncap?.flb || false, ulb: weapon.uncap?.ulb || false, transcendence: weapon.uncap?.transcendence || false, @@ -186,6 +188,7 @@ max_level: editData.maxLevel, max_skill_level: editData.maxSkillLevel, max_awakening_level: editData.maxAwakeningLevel, + max_exorcism_level: editData.maxExorcismLevel, flb: editData.flb, ulb: editData.ulb, transcendence: editData.transcendence, diff --git a/src/routes/(app)/database/weapons/import/+page.svelte b/src/routes/(app)/database/weapons/import/+page.svelte index ba20061e..a88ebfe7 100644 --- a/src/routes/(app)/database/weapons/import/+page.svelte +++ b/src/routes/(app)/database/weapons/import/+page.svelte @@ -137,9 +137,10 @@ maxLevel: parsedData?.maxLevel ?? 100, maxSkillLevel: 10, maxAwakeningLevel: 0, - flb: parsedData?.flb ?? false, - ulb: parsedData?.ulb ?? false, - transcendence: parsedData?.transcendence ?? false, + maxExorcismLevel: null as number | null, + flb: suggestions?.flb ?? false, + ulb: suggestions?.ulb ?? false, + transcendence: suggestions?.transcendence ?? false, extraPrerequisite: '' as number | '', extra: false, limit: false, @@ -277,6 +278,7 @@ max_level: formData.maxLevel, max_skill_level: formData.maxSkillLevel, max_awakening_level: formData.maxAwakeningLevel, + max_exorcism_level: formData.maxExorcismLevel, flb: formData.flb, ulb: formData.ulb, transcendence: formData.transcendence, diff --git a/src/routes/(app)/database/weapons/new/+page.svelte b/src/routes/(app)/database/weapons/new/+page.svelte index 53bf4625..c4c3d192 100644 --- a/src/routes/(app)/database/weapons/new/+page.svelte +++ b/src/routes/(app)/database/weapons/new/+page.svelte @@ -75,6 +75,7 @@ maxLevel: 100, maxSkillLevel: 10, maxAwakeningLevel: 0, + maxExorcismLevel: null as number | null, // Uncap flb: false, @@ -184,6 +185,7 @@ max_level: editData.maxLevel, max_skill_level: editData.maxSkillLevel, max_awakening_level: editData.maxAwakeningLevel, + max_exorcism_level: editData.maxExorcismLevel, // Uncap flb: editData.flb,