diff --git a/src/lib/components/collection/CollectionCharacterPane.svelte b/src/lib/components/collection/CollectionCharacterPane.svelte index 9a6cdfa9..2442a756 100644 --- a/src/lib/components/collection/CollectionCharacterPane.svelte +++ b/src/lib/components/collection/CollectionCharacterPane.svelte @@ -20,8 +20,11 @@ type CharacterEditValues, type CharacterEditUpdates } from '$lib/components/sidebar/CharacterEditPane.svelte' - import Button from '$lib/components/ui/Button.svelte' - import Icon from '$lib/components/Icon.svelte' + import DetailRow from '$lib/components/sidebar/details/DetailRow.svelte' + import { sidebar } from '$lib/stores/sidebar.svelte' + import DetailsSection from '$lib/components/sidebar/details/DetailsSection.svelte' + import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte' + import { getRingStat, getElementalizedEarringStat } from '$lib/utils/masteryUtils' interface Props { character: CollectionCharacter @@ -29,7 +32,10 @@ onClose?: () => void } - let { character, isOwner, onClose }: Props = $props() + let { character: initialCharacter, isOwner, onClose }: Props = $props() + + // Local state for the character - updated when mutation succeeds + let character = $state(initialCharacter) // Tab state let selectedTab = $state<'info' | 'collection'>('collection') @@ -37,6 +43,12 @@ // Edit mode state let isEditing = $state(false) + // Sync local state when a different character is selected + $effect(() => { + character = initialCharacter + isEditing = false + }) + // Update mutation const updateMutation = useUpdateCollectionCharacter() @@ -45,6 +57,8 @@ // Current edit values from the collection character const currentValues = $derived({ + uncapLevel: character.uncapLevel, + transcendenceStep: character.transcendenceStep, awakening: character.awakening ? { type: character.awakening.type, @@ -79,6 +93,16 @@ // Transform updates to API format const input: Record = {} + // Handle uncap level + if (updates.uncapLevel !== undefined) { + input.uncapLevel = updates.uncapLevel + } + + // Handle transcendence step + if (updates.transcendenceStep !== undefined) { + input.transcendenceStep = updates.transcendenceStep + } + // Handle awakening if (updates.awakening !== undefined) { if (updates.awakening === null) { @@ -108,11 +132,14 @@ input.perpetuity = updates.perpetuity } - await updateMutation.mutateAsync({ + const updatedCharacter = await updateMutation.mutateAsync({ id: character.id, input }) + // Update local state with the response from the server + character = updatedCharacter + isEditing = false } catch (error) { console.error('Failed to update collection character:', error) @@ -131,20 +158,77 @@ } } - function displayRing(ring: ExtendedMastery | null): string { + function getRingLabel(ring: ExtendedMastery | null): string { if (!ring || ring.modifier === 0) return '—' - // TODO: Add proper ring modifier labels - return `Modifier ${ring.modifier}: ${ring.strength}` + const stat = getRingStat(ring.modifier) + return stat?.name?.en ?? '—' } - function displayAwakening(): string { + function getRingValue(ring: ExtendedMastery | null): string { + if (!ring || ring.modifier === 0) return '' + const stat = getRingStat(ring.modifier) + if (!stat) return String(ring.strength) + return `${ring.strength}${stat.suffix}` + } + + function getEarringLabel(): string { + if (!character.earring || character.earring.modifier === 0) return '—' + const stat = getElementalizedEarringStat(character.earring.modifier, characterData?.element) + return stat?.name?.en ?? '—' + } + + function getEarringValue(): string { + if (!character.earring || character.earring.modifier === 0) return '' + const stat = getElementalizedEarringStat(character.earring.modifier, characterData?.element) + if (!stat) return String(character.earring.strength) + return `${character.earring.strength}${stat.suffix}` + } + + function getAwakeningType(): string { if (!character.awakening) return '—' const name = typeof character.awakening.type.name === 'string' ? character.awakening.type.name : character.awakening.type.name?.en || 'Unknown' - return `${name} Lv.${character.awakening.level}` + return name } + + function getAwakeningLevel(): string { + if (!character.awakening) return '—' + return String(character.awakening.level) + } + + // Check if awakening is set + const hasAwakening = $derived(character.awakening !== null) + + // Check if any rings are equipped (modifier must be a positive number) + const hasRings = $derived( + (character.ring1?.modifier != null && character.ring1.modifier !== 0) || + (character.ring2?.modifier != null && character.ring2.modifier !== 0) || + (character.ring3?.modifier != null && character.ring3.modifier !== 0) || + (character.ring4?.modifier != null && character.ring4.modifier !== 0) + ) + + // Check if earring is equipped (modifier must be a positive number) + const hasEarring = $derived( + character.earring && character.earring.modifier != null && character.earring.modifier !== 0 + ) + + // Update sidebar header action based on current state + $effect(() => { + if (isOwner && selectedTab === 'collection' && !isEditing) { + sidebar.setAction(() => (isEditing = true), 'Edit', elementName) + } else { + sidebar.clearAction() + } + }) + + // Clean up sidebar action when component is destroyed + $effect(() => { + return () => { + sidebar.clearAction() + } + })
@@ -158,7 +242,13 @@
- + Info My Collection @@ -189,44 +279,60 @@ {:else}
-
-

Awakening

-

{displayAwakening()}

-
+ + + + + + -
-

Over Mastery Rings

-
-

Ring 1: {displayRing(character.ring1)}

-

Ring 2: {displayRing(character.ring2)}

-

Ring 3: {displayRing(character.ring3)}

-

Ring 4: {displayRing(character.ring4)}

-
-
+ + + + -
-

Aetherial Mastery

-

{displayRing(character.earring)}

-
+ + {#if character.ring1?.modifier != null && character.ring1.modifier !== 0} + + {/if} + {#if character.ring2?.modifier != null && character.ring2.modifier !== 0} + + {/if} + {#if character.ring3?.modifier != null && character.ring3.modifier !== 0} + + {/if} + {#if character.ring4?.modifier != null && character.ring4.modifier !== 0} + + {/if} + -
-

Perpetuity Ring

-

{character.perpetuity ? 'Equipped' : 'Not equipped'}

-
- - {#if isOwner} -
- -
- {/if} + + +
{/if}
@@ -245,7 +351,7 @@ } .tab-nav { - padding: 0 spacing.$unit-2x spacing.$unit-2x; + padding: spacing.$unit-2x; } .pane-content { @@ -266,38 +372,5 @@ display: flex; flex-direction: column; gap: spacing.$unit-3x; - padding: 0 spacing.$unit-2x; - } - - .customization-section { - h4 { - font-size: typography.$font-small; - font-weight: typography.$bold; - text-transform: uppercase; - color: var(--text-secondary, colors.$grey-50); - margin: 0 0 spacing.$unit-half; - letter-spacing: 0.5px; - } - - p { - margin: 0; - color: var(--text-primary, colors.$grey-10); - } - } - - .rings-list { - display: flex; - flex-direction: column; - gap: spacing.$unit-half; - - p { - margin: 0; - } - } - - .edit-button-container { - margin-top: spacing.$unit-2x; - padding-top: spacing.$unit-2x; - border-top: 1px solid var(--border-secondary, colors.$grey-80); }