refactor character edit page to use section components
- use DetailScaffold wrapper - extract metadata, uncap, taxonomy, stats sections - standardize field naming (camelCase) - add element-themed checkboxes
This commit is contained in:
parent
817084cee5
commit
b58cbbe72f
5 changed files with 98 additions and 360 deletions
|
|
@ -5,11 +5,13 @@
|
||||||
import DetailItem from '$lib/components/ui/DetailItem.svelte'
|
import DetailItem from '$lib/components/ui/DetailItem.svelte'
|
||||||
import { getRarityLabel, getRarityOptions } from '$lib/utils/rarity'
|
import { getRarityLabel, getRarityOptions } from '$lib/utils/rarity'
|
||||||
|
|
||||||
let {
|
interface Props {
|
||||||
character,
|
character: any
|
||||||
editMode = false,
|
editMode?: boolean
|
||||||
editData = $bindable<any>()
|
editData?: any
|
||||||
}: { character: any; editMode?: boolean; editData?: any } = $props()
|
}
|
||||||
|
|
||||||
|
let { character, editMode = false, editData = $bindable() }: Props = $props()
|
||||||
|
|
||||||
const rarityOptions = getRarityOptions()
|
const rarityOptions = getRarityOptions()
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -17,10 +19,11 @@
|
||||||
<DetailsContainer title="Metadata">
|
<DetailsContainer title="Metadata">
|
||||||
{#if editMode}
|
{#if editMode}
|
||||||
<DetailItem label="Rarity" bind:value={editData.rarity} editable={true} type="select" options={rarityOptions} />
|
<DetailItem label="Rarity" bind:value={editData.rarity} editable={true} type="select" options={rarityOptions} />
|
||||||
<DetailItem label="Granblue ID" bind:value={editData.granblue_id} editable={true} type="text" />
|
<DetailItem label="Granblue ID" bind:value={editData.granblueId} editable={true} type="text" />
|
||||||
|
<DetailItem label="Character ID" bind:value={editData.characterId} editable={true} type="number" />
|
||||||
{:else}
|
{:else}
|
||||||
<DetailItem label="Rarity" value={getRarityLabel(character.rarity)} />
|
<DetailItem label="Rarity" value={getRarityLabel(character.rarity)} />
|
||||||
<DetailItem label="Granblue ID" value={character.granblue_id} />
|
<DetailItem label="Granblue ID" value={character.granblueId} />
|
||||||
{/if}
|
{/if}
|
||||||
</DetailsContainer>
|
</DetailsContainer>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,39 +4,41 @@
|
||||||
import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
|
import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
|
||||||
import DetailItem from '$lib/components/ui/DetailItem.svelte'
|
import DetailItem from '$lib/components/ui/DetailItem.svelte'
|
||||||
|
|
||||||
let {
|
interface Props {
|
||||||
character,
|
character: any
|
||||||
editMode = false,
|
editMode?: boolean
|
||||||
editData = $bindable<any>()
|
editData?: any
|
||||||
}: { character: any; editMode?: boolean; editData?: any } = $props()
|
}
|
||||||
|
|
||||||
|
let { character, editMode = false, editData = $bindable() }: Props = $props()
|
||||||
|
|
||||||
const flb = $derived(editMode ? Boolean(editData.flb) : Boolean(character?.uncap?.flb))
|
const flb = $derived(editMode ? Boolean(editData.flb) : Boolean(character?.uncap?.flb))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DetailsContainer title="HP Stats">
|
<DetailsContainer title="HP Stats">
|
||||||
{#if editMode}
|
{#if editMode}
|
||||||
<DetailItem label="Base HP" bind:value={editData.min_hp} editable={true} type="number" placeholder="0" />
|
<DetailItem label="Base HP" bind:value={editData.minHp} editable={true} type="number" placeholder="0" />
|
||||||
<DetailItem label="Max HP" bind:value={editData.max_hp} editable={true} type="number" placeholder="0" />
|
<DetailItem label="Max HP" bind:value={editData.maxHp} editable={true} type="number" placeholder="0" />
|
||||||
<DetailItem label="Max HP (FLB)" bind:value={editData.max_hp_flb} editable={true} type="number" placeholder="0" />
|
<DetailItem label="Max HP (FLB)" bind:value={editData.maxHpFlb} editable={true} type="number" placeholder="0" />
|
||||||
{:else}
|
{:else}
|
||||||
<DetailItem label="Base HP" value={character.hp?.min_hp} />
|
<DetailItem label="Base HP" value={character.hp?.minHp} />
|
||||||
<DetailItem label="Max HP" value={character.hp?.max_hp} />
|
<DetailItem label="Max HP" value={character.hp?.maxHp} />
|
||||||
{#if flb}
|
{#if flb}
|
||||||
<DetailItem label="Max HP (FLB)" value={character.hp?.max_hp_flb} />
|
<DetailItem label="Max HP (FLB)" value={character.hp?.maxHpFlb} />
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</DetailsContainer>
|
</DetailsContainer>
|
||||||
|
|
||||||
<DetailsContainer title="Attack Stats">
|
<DetailsContainer title="Attack Stats">
|
||||||
{#if editMode}
|
{#if editMode}
|
||||||
<DetailItem label="Base Attack" bind:value={editData.min_atk} editable={true} type="number" placeholder="0" />
|
<DetailItem label="Base Attack" bind:value={editData.minAtk} editable={true} type="number" placeholder="0" />
|
||||||
<DetailItem label="Max Attack" bind:value={editData.max_atk} editable={true} type="number" placeholder="0" />
|
<DetailItem label="Max Attack" bind:value={editData.maxAtk} editable={true} type="number" placeholder="0" />
|
||||||
<DetailItem label="Max Attack (FLB)" bind:value={editData.max_atk_flb} editable={true} type="number" placeholder="0" />
|
<DetailItem label="Max Attack (FLB)" bind:value={editData.maxAtkFlb} editable={true} type="number" placeholder="0" />
|
||||||
{:else}
|
{:else}
|
||||||
<DetailItem label="Base Attack" value={character.atk?.min_atk} />
|
<DetailItem label="Base Attack" value={character.atk?.minAtk} />
|
||||||
<DetailItem label="Max Attack" value={character.atk?.max_atk} />
|
<DetailItem label="Max Attack" value={character.atk?.maxAtk} />
|
||||||
{#if flb}
|
{#if flb}
|
||||||
<DetailItem label="Max Attack (FLB)" value={character.atk?.max_atk_flb} />
|
<DetailItem label="Max Attack (FLB)" value={character.atk?.maxAtkFlb} />
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</DetailsContainer>
|
</DetailsContainer>
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@
|
||||||
import { getGenderLabel, getGenderOptions } from '$lib/utils/gender'
|
import { getGenderLabel, getGenderOptions } from '$lib/utils/gender'
|
||||||
import { getProficiencyLabel, getProficiencyOptions } from '$lib/utils/proficiency'
|
import { getProficiencyLabel, getProficiencyOptions } from '$lib/utils/proficiency'
|
||||||
|
|
||||||
let {
|
interface Props {
|
||||||
character,
|
character: any
|
||||||
editMode = false,
|
editMode?: boolean
|
||||||
editData = $bindable<any>()
|
editData?: any
|
||||||
}: { character: any; editMode?: boolean; editData?: any } = $props()
|
}
|
||||||
|
|
||||||
|
let { character, editMode = false, editData = $bindable() }: Props = $props()
|
||||||
|
|
||||||
const elementOptions = getElementOptions()
|
const elementOptions = getElementOptions()
|
||||||
const raceOptions = getRaceOptions()
|
const raceOptions = getRaceOptions()
|
||||||
|
|
@ -35,8 +37,8 @@
|
||||||
<DetailItem label="Race 2" value={getRaceLabel(character.race?.[1])} />
|
<DetailItem label="Race 2" value={getRaceLabel(character.race?.[1])} />
|
||||||
{/if}
|
{/if}
|
||||||
<DetailItem label="Gender" value={getGenderLabel(character.gender)} />
|
<DetailItem label="Gender" value={getGenderLabel(character.gender)} />
|
||||||
<DetailItem label="Proficiency 1" value={getProficiencyLabel(character.proficiency[0])} />
|
<DetailItem label="Proficiency 1" value={getProficiencyLabel(character.proficiency?.[0] ?? 0)} />
|
||||||
<DetailItem label="Proficiency 2" value={getProficiencyLabel(character.proficiency[1])} />
|
<DetailItem label="Proficiency 2" value={getProficiencyLabel(character.proficiency?.[1] ?? 0)} />
|
||||||
{/if}
|
{/if}
|
||||||
</DetailsContainer>
|
</DetailsContainer>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,17 @@
|
||||||
import DetailItem from '$lib/components/ui/DetailItem.svelte'
|
import DetailItem from '$lib/components/ui/DetailItem.svelte'
|
||||||
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
|
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
|
||||||
import { getCharacterMaxUncapLevel } from '$lib/utils/uncap'
|
import { getCharacterMaxUncapLevel } from '$lib/utils/uncap'
|
||||||
|
import { getElementLabel } from '$lib/utils/element'
|
||||||
|
|
||||||
let {
|
type ElementName = 'wind' | 'fire' | 'water' | 'earth' | 'dark' | 'light'
|
||||||
character,
|
|
||||||
editMode = false,
|
interface Props {
|
||||||
editData = $bindable<any>()
|
character: any
|
||||||
}: { character: any; editMode?: boolean; editData?: any } = $props()
|
editMode?: boolean
|
||||||
|
editData?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
let { character, editMode = false, editData = $bindable() }: Props = $props()
|
||||||
|
|
||||||
const uncap = $derived(
|
const uncap = $derived(
|
||||||
editMode
|
editMode
|
||||||
|
|
@ -23,10 +28,19 @@
|
||||||
const special = $derived(editMode ? editData.special : (character?.special ?? false))
|
const special = $derived(editMode ? editData.special : (character?.special ?? false))
|
||||||
const uncapLevel = $derived(getCharacterMaxUncapLevel({ special, uncap }))
|
const uncapLevel = $derived(getCharacterMaxUncapLevel({ special, uncap }))
|
||||||
const transcendenceStage = $derived(transcendence ? 5 : 0)
|
const transcendenceStage = $derived(transcendence ? 5 : 0)
|
||||||
|
|
||||||
|
// Get element name for checkbox theming
|
||||||
|
const elementName = $derived.by((): ElementName | undefined => {
|
||||||
|
const el = editMode ? editData.element : character?.element
|
||||||
|
const label = getElementLabel(el)
|
||||||
|
return label !== '—' && label !== 'Null'
|
||||||
|
? (label.toLowerCase() as ElementName)
|
||||||
|
: undefined
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DetailsContainer title="Details">
|
<DetailsContainer title="Uncap">
|
||||||
{#if character.uncap}
|
{#if character?.uncap || editMode}
|
||||||
<DetailItem label="Uncap">
|
<DetailItem label="Uncap">
|
||||||
<UncapIndicator
|
<UncapIndicator
|
||||||
type="character"
|
type="character"
|
||||||
|
|
@ -42,10 +56,10 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if editMode}
|
{#if editMode}
|
||||||
<DetailItem label="FLB" bind:value={editData.flb} editable={true} type="checkbox" />
|
<DetailItem label="FLB" bind:value={editData.flb} editable={true} type="checkbox" element={elementName} />
|
||||||
<DetailItem label="ULB" bind:value={editData.ulb} editable={true} type="checkbox" />
|
<DetailItem label="ULB" bind:value={editData.ulb} editable={true} type="checkbox" element={elementName} />
|
||||||
<DetailItem label="Transcendence" bind:value={editData.transcendence} editable={true} type="checkbox" />
|
<DetailItem label="Transcendence" bind:value={editData.transcendence} editable={true} type="checkbox" element={elementName} />
|
||||||
<DetailItem label="Special" bind:value={editData.special} editable={true} type="checkbox" />
|
<DetailItem label="Special" bind:value={editData.special} editable={true} type="checkbox" element={elementName} />
|
||||||
{/if}
|
{/if}
|
||||||
</DetailsContainer>
|
</DetailsContainer>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,20 +10,13 @@
|
||||||
import { entityAdapter } from '$lib/api/adapters/entity.adapter'
|
import { entityAdapter } from '$lib/api/adapters/entity.adapter'
|
||||||
import { withInitialData } from '$lib/query/ssr'
|
import { withInitialData } from '$lib/query/ssr'
|
||||||
|
|
||||||
// Utility functions
|
|
||||||
import { getRarityLabel, getRarityOptions } from '$lib/utils/rarity'
|
|
||||||
import { getElementLabel, getElementOptions } from '$lib/utils/element'
|
|
||||||
import { getProficiencyLabel, getProficiencyOptions } from '$lib/utils/proficiency'
|
|
||||||
import { getRaceLabel, getRaceOptions } from '$lib/utils/race'
|
|
||||||
import { getGenderLabel, getGenderOptions } from '$lib/utils/gender'
|
|
||||||
import { getCharacterMaxUncapLevel } from '$lib/utils/uncap'
|
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
|
import DetailScaffold from '$lib/features/database/detail/DetailScaffold.svelte'
|
||||||
|
import CharacterMetadataSection from '$lib/features/database/characters/sections/CharacterMetadataSection.svelte'
|
||||||
|
import CharacterUncapSection from '$lib/features/database/characters/sections/CharacterUncapSection.svelte'
|
||||||
|
import CharacterTaxonomySection from '$lib/features/database/characters/sections/CharacterTaxonomySection.svelte'
|
||||||
|
import CharacterStatsSection from '$lib/features/database/characters/sections/CharacterStatsSection.svelte'
|
||||||
import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
|
import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
|
||||||
import DetailItem from '$lib/components/ui/DetailItem.svelte'
|
|
||||||
import DetailsHeader from '$lib/components/ui/DetailsHeader.svelte'
|
|
||||||
import Button from '$lib/components/ui/Button.svelte'
|
|
||||||
import { getCharacterImage } from '$lib/utils/images'
|
import { getCharacterImage } from '$lib/utils/images'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
@ -54,6 +47,7 @@
|
||||||
},
|
},
|
||||||
enabled: !!character?.characterId && !editMode
|
enabled: !!character?.characterId && !editMode
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let isSaving = $state(false)
|
let isSaving = $state(false)
|
||||||
let saveError = $state<string | null>(null)
|
let saveError = $state<string | null>(null)
|
||||||
let saveSuccess = $state(false)
|
let saveSuccess = $state(false)
|
||||||
|
|
@ -110,13 +104,6 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Options for select dropdowns - using centralized utilities
|
|
||||||
const rarityOptions = getRarityOptions()
|
|
||||||
const elementOptions = getElementOptions()
|
|
||||||
const raceOptions = getRaceOptions()
|
|
||||||
const genderOptions = getGenderOptions()
|
|
||||||
const proficiencyOptions = getProficiencyOptions()
|
|
||||||
|
|
||||||
function toggleEditMode() {
|
function toggleEditMode() {
|
||||||
editMode = !editMode
|
editMode = !editMode
|
||||||
saveError = null
|
saveError = null
|
||||||
|
|
@ -155,7 +142,7 @@
|
||||||
saveSuccess = false
|
saveSuccess = false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Prepare the data for API
|
// Prepare the data for API (convert to snake_case)
|
||||||
const payload = {
|
const payload = {
|
||||||
name: editData.name,
|
name: editData.name,
|
||||||
granblue_id: editData.granblueId,
|
granblue_id: editData.granblueId,
|
||||||
|
|
@ -208,264 +195,32 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get character image
|
|
||||||
// Helper function for character grid image
|
// Helper function for character grid image
|
||||||
function getCharacterGridImage(character: any): string {
|
function getCharacterGridImage(character: any): string {
|
||||||
return getCharacterImage(character?.granblueId, 'grid', '01')
|
return getCharacterImage(character?.granblueId, 'grid', '01')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate uncap properties for the indicator
|
|
||||||
const uncap = $derived(
|
|
||||||
editMode
|
|
||||||
? { flb: editData.flb, ulb: editData.ulb, transcendence: editData.transcendence }
|
|
||||||
: (character?.uncap ?? { flb: false, ulb: false, transcendence: false })
|
|
||||||
)
|
|
||||||
const flb = $derived(uncap.flb ?? false)
|
|
||||||
const ulb = $derived(uncap.ulb ?? false)
|
|
||||||
const transcendence = $derived(uncap.transcendence ?? false)
|
|
||||||
const special = $derived(editMode ? editData.special : (character?.special ?? false))
|
|
||||||
|
|
||||||
const uncapLevel = $derived(
|
|
||||||
getCharacterMaxUncapLevel({ special, uncap: { flb, ulb, transcendence } })
|
|
||||||
)
|
|
||||||
const transcendenceStage = $derived(transcendence ? 5 : 0)
|
|
||||||
|
|
||||||
// Get element name for checkbox theming
|
|
||||||
const elementName = $derived.by(() => {
|
|
||||||
const el = editMode ? editData.element : character?.element
|
|
||||||
const label = getElementLabel(el)
|
|
||||||
return label !== '—' && label !== 'Null'
|
|
||||||
? (label.toLowerCase() as 'wind' | 'fire' | 'water' | 'earth' | 'dark' | 'light')
|
|
||||||
: undefined
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{#if character}
|
{#if character}
|
||||||
<div class="content">
|
<DetailScaffold
|
||||||
<DetailsHeader
|
type="character"
|
||||||
type="character"
|
item={character}
|
||||||
item={character}
|
image={getCharacterGridImage(character)}
|
||||||
image={getCharacterGridImage(character)}
|
showEdit={canEdit}
|
||||||
onEdit={toggleEditMode}
|
{editMode}
|
||||||
showEdit={canEdit}
|
{isSaving}
|
||||||
{editMode}
|
{saveSuccess}
|
||||||
onSave={saveChanges}
|
{saveError}
|
||||||
onCancel={toggleEditMode}
|
onEdit={toggleEditMode}
|
||||||
{isSaving}
|
onSave={saveChanges}
|
||||||
/>
|
onCancel={toggleEditMode}
|
||||||
|
>
|
||||||
{#if saveSuccess || saveError}
|
|
||||||
<div class="edit-controls">
|
|
||||||
{#if saveSuccess}
|
|
||||||
<span class="success-message">Changes saved successfully!</span>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if saveError}
|
|
||||||
<span class="error-message">{saveError}</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<section class="details">
|
<section class="details">
|
||||||
<DetailsContainer title="Metadata">
|
<CharacterMetadataSection {character} {editMode} bind:editData />
|
||||||
{#if editMode}
|
<CharacterUncapSection {character} {editMode} bind:editData />
|
||||||
<DetailItem
|
<CharacterTaxonomySection {character} {editMode} bind:editData />
|
||||||
label="Rarity"
|
<CharacterStatsSection {character} {editMode} bind:editData />
|
||||||
bind:value={editData.rarity}
|
|
||||||
editable={true}
|
|
||||||
type="select"
|
|
||||||
options={rarityOptions}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Granblue ID"
|
|
||||||
bind:value={editData.granblueId}
|
|
||||||
editable={true}
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Character ID"
|
|
||||||
bind:value={editData.characterId}
|
|
||||||
editable={true}
|
|
||||||
type="number"
|
|
||||||
/>
|
|
||||||
{:else}
|
|
||||||
<DetailItem label="Rarity" value={getRarityLabel(character.rarity)} />
|
|
||||||
<DetailItem label="Granblue ID" value={character.granblueId} />
|
|
||||||
{/if}
|
|
||||||
</DetailsContainer>
|
|
||||||
|
|
||||||
<DetailsContainer title="Details">
|
|
||||||
{#if character.uncap}
|
|
||||||
<DetailItem label="Uncap">
|
|
||||||
<UncapIndicator
|
|
||||||
type="character"
|
|
||||||
{uncapLevel}
|
|
||||||
{transcendenceStage}
|
|
||||||
{flb}
|
|
||||||
{ulb}
|
|
||||||
{transcendence}
|
|
||||||
{special}
|
|
||||||
editable={false}
|
|
||||||
/>
|
|
||||||
</DetailItem>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if editMode}
|
|
||||||
<DetailItem
|
|
||||||
label="FLB"
|
|
||||||
bind:value={editData.flb}
|
|
||||||
editable={true}
|
|
||||||
type="checkbox"
|
|
||||||
element={elementName}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="ULB"
|
|
||||||
bind:value={editData.ulb}
|
|
||||||
editable={true}
|
|
||||||
type="checkbox"
|
|
||||||
element={elementName}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Transcendence"
|
|
||||||
bind:value={editData.transcendence}
|
|
||||||
editable={true}
|
|
||||||
type="checkbox"
|
|
||||||
element={elementName}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Special"
|
|
||||||
bind:value={editData.special}
|
|
||||||
editable={true}
|
|
||||||
type="checkbox"
|
|
||||||
element={elementName}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if editMode}
|
|
||||||
<DetailItem
|
|
||||||
label="Element"
|
|
||||||
bind:value={editData.element}
|
|
||||||
editable={true}
|
|
||||||
type="select"
|
|
||||||
options={elementOptions}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Race 1"
|
|
||||||
bind:value={editData.race1}
|
|
||||||
editable={true}
|
|
||||||
type="select"
|
|
||||||
options={raceOptions}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Race 2"
|
|
||||||
bind:value={editData.race2}
|
|
||||||
editable={true}
|
|
||||||
type="select"
|
|
||||||
options={raceOptions}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Gender"
|
|
||||||
bind:value={editData.gender}
|
|
||||||
editable={true}
|
|
||||||
type="select"
|
|
||||||
options={genderOptions}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Proficiency 1"
|
|
||||||
bind:value={editData.proficiency1}
|
|
||||||
editable={true}
|
|
||||||
type="select"
|
|
||||||
options={proficiencyOptions}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Proficiency 2"
|
|
||||||
bind:value={editData.proficiency2}
|
|
||||||
editable={true}
|
|
||||||
type="select"
|
|
||||||
options={proficiencyOptions}
|
|
||||||
/>
|
|
||||||
{:else}
|
|
||||||
<DetailItem label="Element" value={getElementLabel(character.element)} />
|
|
||||||
<DetailItem label="Race 1" value={getRaceLabel(character.race?.[0])} />
|
|
||||||
{#if character.race?.[1]}
|
|
||||||
<DetailItem label="Race 2" value={getRaceLabel(character.race?.[1])} />
|
|
||||||
{/if}
|
|
||||||
<DetailItem label="Gender" value={getGenderLabel(character.gender)} />
|
|
||||||
<DetailItem
|
|
||||||
label="Proficiency 1"
|
|
||||||
value={getProficiencyLabel(character.proficiency?.[0] ?? 0)}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Proficiency 2"
|
|
||||||
value={getProficiencyLabel(character.proficiency?.[1] ?? 0)}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</DetailsContainer>
|
|
||||||
|
|
||||||
<DetailsContainer title="HP Stats">
|
|
||||||
{#if editMode}
|
|
||||||
<DetailItem
|
|
||||||
label="Base HP"
|
|
||||||
bind:value={editData.minHp}
|
|
||||||
editable={true}
|
|
||||||
type="number"
|
|
||||||
placeholder="0"
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Max HP"
|
|
||||||
bind:value={editData.maxHp}
|
|
||||||
editable={true}
|
|
||||||
type="number"
|
|
||||||
placeholder="0"
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Max HP (FLB)"
|
|
||||||
bind:value={editData.maxHpFlb}
|
|
||||||
editable={true}
|
|
||||||
type="number"
|
|
||||||
placeholder="0"
|
|
||||||
/>
|
|
||||||
{:else}
|
|
||||||
<DetailItem label="Base HP" value={character.hp?.minHp} />
|
|
||||||
<DetailItem label="Max HP" value={character.hp?.maxHp} />
|
|
||||||
{#if flb}
|
|
||||||
<DetailItem label="Max HP (FLB)" value={character.hp?.maxHpFlb} />
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</DetailsContainer>
|
|
||||||
|
|
||||||
<DetailsContainer title="Attack Stats">
|
|
||||||
{#if editMode}
|
|
||||||
<DetailItem
|
|
||||||
label="Base Attack"
|
|
||||||
bind:value={editData.minAtk}
|
|
||||||
editable={true}
|
|
||||||
type="number"
|
|
||||||
placeholder="0"
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Max Attack"
|
|
||||||
bind:value={editData.maxAtk}
|
|
||||||
editable={true}
|
|
||||||
type="number"
|
|
||||||
placeholder="0"
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label="Max Attack (FLB)"
|
|
||||||
bind:value={editData.maxAtkFlb}
|
|
||||||
editable={true}
|
|
||||||
type="number"
|
|
||||||
placeholder="0"
|
|
||||||
/>
|
|
||||||
{:else}
|
|
||||||
<DetailItem label="Base Attack" value={character.atk?.minAtk} />
|
|
||||||
<DetailItem label="Max Attack" value={character.atk?.maxAtk} />
|
|
||||||
{#if flb}
|
|
||||||
<DetailItem label="Max Attack (FLB)" value={character.atk?.maxAtkFlb} />
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</DetailsContainer>
|
|
||||||
|
|
||||||
{#if !editMode && relatedQuery.data?.length}
|
{#if !editMode && relatedQuery.data?.length}
|
||||||
<DetailsContainer title="Related Units">
|
<DetailsContainer title="Related Units">
|
||||||
|
|
@ -484,7 +239,7 @@
|
||||||
</DetailsContainer>
|
</DetailsContainer>
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</DetailScaffold>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="not-found">
|
<div class="not-found">
|
||||||
<h2>Character Not Found</h2>
|
<h2>Character Not Found</h2>
|
||||||
|
|
@ -499,7 +254,6 @@
|
||||||
@use '$src/themes/layout' as layout;
|
@use '$src/themes/layout' as layout;
|
||||||
@use '$src/themes/spacing' as spacing;
|
@use '$src/themes/spacing' as spacing;
|
||||||
@use '$src/themes/typography' as typography;
|
@use '$src/themes/typography' as typography;
|
||||||
@use '$src/themes/effects' as effects;
|
|
||||||
|
|
||||||
.not-found {
|
.not-found {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -520,46 +274,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.details {
|
||||||
background: white;
|
|
||||||
border-radius: layout.$card-corner;
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
||||||
overflow: visible;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.details {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-controls {
|
|
||||||
padding: spacing.$unit-2x;
|
|
||||||
border-bottom: 1px solid colors.$grey-80;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: spacing.$unit;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.success-message {
|
|
||||||
color: colors.$grey-30;
|
|
||||||
font-size: typography.$font-small;
|
|
||||||
animation: fadeIn effects.$duration-opacity-fade ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-message {
|
|
||||||
color: colors.$error;
|
|
||||||
font-size: typography.$font-small;
|
|
||||||
animation: fadeIn effects.$duration-opacity-fade ease-in;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.related-units {
|
.related-units {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue