feat(summons): add edit mode to summon detail page
- Add edit mode state management (editMode, editData, isSaving) - Use DetailScaffold wrapper for consistent edit UI - Import and integrate section components: - SummonMetadataSection, SummonUncapSection - SummonTaxonomySection, SummonStatsSection - Add Nicknames, Dates, Links sections in edit mode - Connect saveChanges to entityAdapter.updateSummon() - Invalidate TanStack Query cache after successful save 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3e23585ee7
commit
fda2b3188f
1 changed files with 345 additions and 139 deletions
|
|
@ -1,27 +1,33 @@
|
||||||
<svelte:options runes={true} />
|
<svelte:options runes={true} />
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
// SvelteKit imports
|
||||||
import { goto } from '$app/navigation'
|
import { goto } from '$app/navigation'
|
||||||
|
|
||||||
// TanStack Query
|
// TanStack Query
|
||||||
import { createQuery } from '@tanstack/svelte-query'
|
import { createQuery, useQueryClient } from '@tanstack/svelte-query'
|
||||||
import { entityQueries } from '$lib/api/queries/entity.queries'
|
import { entityQueries } from '$lib/api/queries/entity.queries'
|
||||||
|
import { entityAdapter } from '$lib/api/adapters/entity.adapter'
|
||||||
import { withInitialData } from '$lib/query/ssr'
|
import { withInitialData } from '$lib/query/ssr'
|
||||||
|
|
||||||
// Utilities
|
|
||||||
import { getRarityLabel } from '$lib/utils/rarity'
|
|
||||||
import { getElementLabel, getElementIcon } from '$lib/utils/element'
|
|
||||||
import { getSummonImage } from '$lib/utils/images'
|
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
|
import DetailScaffold from '$lib/features/database/detail/DetailScaffold.svelte'
|
||||||
|
import SummonMetadataSection from '$lib/features/database/summons/sections/SummonMetadataSection.svelte'
|
||||||
|
import SummonUncapSection from '$lib/features/database/summons/sections/SummonUncapSection.svelte'
|
||||||
|
import SummonTaxonomySection from '$lib/features/database/summons/sections/SummonTaxonomySection.svelte'
|
||||||
|
import SummonStatsSection from '$lib/features/database/summons/sections/SummonStatsSection.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 DetailItem from '$lib/components/ui/DetailItem.svelte'
|
||||||
import DetailsHeader from '$lib/components/ui/DetailsHeader.svelte'
|
import TagInput from '$lib/components/ui/TagInput.svelte'
|
||||||
|
import { getSummonImage } from '$lib/utils/images'
|
||||||
|
|
||||||
|
// Types
|
||||||
import type { PageData } from './$types'
|
import type { PageData } from './$types'
|
||||||
|
|
||||||
let { data }: { data: PageData } = $props()
|
let { data }: { data: PageData } = $props()
|
||||||
|
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
// Use TanStack Query with SSR initial data
|
// Use TanStack Query with SSR initial data
|
||||||
const summonQuery = createQuery(() => ({
|
const summonQuery = createQuery(() => ({
|
||||||
...entityQueries.summon(data.summon?.id ?? ''),
|
...entityQueries.summon(data.summon?.id ?? ''),
|
||||||
|
|
@ -30,121 +36,352 @@
|
||||||
|
|
||||||
// Get summon from query
|
// Get summon from query
|
||||||
const summon = $derived(summonQuery.data)
|
const summon = $derived(summonQuery.data)
|
||||||
|
const userRole = $derived(data.role || 0)
|
||||||
|
const canEdit = $derived(userRole >= 7)
|
||||||
|
|
||||||
// Helper function to get summon grid image
|
// Edit mode state
|
||||||
|
let editMode = $state(false)
|
||||||
|
let isSaving = $state(false)
|
||||||
|
let saveError = $state<string | null>(null)
|
||||||
|
let saveSuccess = $state(false)
|
||||||
|
|
||||||
|
// Editable fields
|
||||||
|
let editData = $state({
|
||||||
|
name: summon?.name?.en || '',
|
||||||
|
nameJp: summon?.name?.ja || '',
|
||||||
|
granblueId: summon?.granblueId || '',
|
||||||
|
rarity: summon?.rarity || 3,
|
||||||
|
element: summon?.element || 0,
|
||||||
|
series: summon?.series || '',
|
||||||
|
minHp: summon?.hp?.minHp || 0,
|
||||||
|
maxHp: summon?.hp?.maxHp || 0,
|
||||||
|
maxHpFlb: summon?.hp?.maxHpFlb || 0,
|
||||||
|
maxHpUlb: summon?.hp?.maxHpUlb || 0,
|
||||||
|
maxHpTranscendence: summon?.hp?.maxHpXlb || 0,
|
||||||
|
minAtk: summon?.atk?.minAtk || 0,
|
||||||
|
maxAtk: summon?.atk?.maxAtk || 0,
|
||||||
|
maxAtkFlb: summon?.atk?.maxAtkFlb || 0,
|
||||||
|
maxAtkUlb: summon?.atk?.maxAtkUlb || 0,
|
||||||
|
maxAtkTranscendence: summon?.atk?.maxAtkXlb || 0,
|
||||||
|
maxLevel: 100,
|
||||||
|
flb: summon?.uncap?.flb || false,
|
||||||
|
ulb: summon?.uncap?.ulb || false,
|
||||||
|
transcendence: summon?.uncap?.transcendence || false,
|
||||||
|
subaura: summon?.subaura || false,
|
||||||
|
limit: false,
|
||||||
|
releaseDate: '',
|
||||||
|
flbDate: '',
|
||||||
|
ulbDate: '',
|
||||||
|
transcendenceDate: '',
|
||||||
|
wikiEn: '',
|
||||||
|
wikiJa: '',
|
||||||
|
gamewith: '',
|
||||||
|
kamigame: '',
|
||||||
|
nicknamesEn: [] as string[],
|
||||||
|
nicknamesJp: [] as string[]
|
||||||
|
})
|
||||||
|
|
||||||
|
// Reset edit data when summon changes
|
||||||
|
$effect(() => {
|
||||||
|
if (summon) {
|
||||||
|
editData = {
|
||||||
|
name: summon.name?.en || '',
|
||||||
|
nameJp: summon.name?.ja || '',
|
||||||
|
granblueId: summon.granblueId || '',
|
||||||
|
rarity: summon.rarity || 3,
|
||||||
|
element: summon.element || 0,
|
||||||
|
series: summon.series || '',
|
||||||
|
minHp: summon.hp?.minHp || 0,
|
||||||
|
maxHp: summon.hp?.maxHp || 0,
|
||||||
|
maxHpFlb: summon.hp?.maxHpFlb || 0,
|
||||||
|
maxHpUlb: summon.hp?.maxHpUlb || 0,
|
||||||
|
maxHpTranscendence: summon.hp?.maxHpXlb || 0,
|
||||||
|
minAtk: summon.atk?.minAtk || 0,
|
||||||
|
maxAtk: summon.atk?.maxAtk || 0,
|
||||||
|
maxAtkFlb: summon.atk?.maxAtkFlb || 0,
|
||||||
|
maxAtkUlb: summon.atk?.maxAtkUlb || 0,
|
||||||
|
maxAtkTranscendence: summon.atk?.maxAtkXlb || 0,
|
||||||
|
maxLevel: 100,
|
||||||
|
flb: summon.uncap?.flb || false,
|
||||||
|
ulb: summon.uncap?.ulb || false,
|
||||||
|
transcendence: summon.uncap?.transcendence || false,
|
||||||
|
subaura: summon.subaura || false,
|
||||||
|
limit: false,
|
||||||
|
releaseDate: '',
|
||||||
|
flbDate: '',
|
||||||
|
ulbDate: '',
|
||||||
|
transcendenceDate: '',
|
||||||
|
wikiEn: '',
|
||||||
|
wikiJa: '',
|
||||||
|
gamewith: '',
|
||||||
|
kamigame: '',
|
||||||
|
nicknamesEn: [],
|
||||||
|
nicknamesJp: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function toggleEditMode() {
|
||||||
|
editMode = !editMode
|
||||||
|
saveError = null
|
||||||
|
saveSuccess = false
|
||||||
|
|
||||||
|
// Reset data when canceling
|
||||||
|
if (!editMode && summon) {
|
||||||
|
editData = {
|
||||||
|
name: summon.name?.en || '',
|
||||||
|
nameJp: summon.name?.ja || '',
|
||||||
|
granblueId: summon.granblueId || '',
|
||||||
|
rarity: summon.rarity || 3,
|
||||||
|
element: summon.element || 0,
|
||||||
|
series: summon.series || '',
|
||||||
|
minHp: summon.hp?.minHp || 0,
|
||||||
|
maxHp: summon.hp?.maxHp || 0,
|
||||||
|
maxHpFlb: summon.hp?.maxHpFlb || 0,
|
||||||
|
maxHpUlb: summon.hp?.maxHpUlb || 0,
|
||||||
|
maxHpTranscendence: summon.hp?.maxHpXlb || 0,
|
||||||
|
minAtk: summon.atk?.minAtk || 0,
|
||||||
|
maxAtk: summon.atk?.maxAtk || 0,
|
||||||
|
maxAtkFlb: summon.atk?.maxAtkFlb || 0,
|
||||||
|
maxAtkUlb: summon.atk?.maxAtkUlb || 0,
|
||||||
|
maxAtkTranscendence: summon.atk?.maxAtkXlb || 0,
|
||||||
|
maxLevel: 100,
|
||||||
|
flb: summon.uncap?.flb || false,
|
||||||
|
ulb: summon.uncap?.ulb || false,
|
||||||
|
transcendence: summon.uncap?.transcendence || false,
|
||||||
|
subaura: summon.subaura || false,
|
||||||
|
limit: false,
|
||||||
|
releaseDate: '',
|
||||||
|
flbDate: '',
|
||||||
|
ulbDate: '',
|
||||||
|
transcendenceDate: '',
|
||||||
|
wikiEn: '',
|
||||||
|
wikiJa: '',
|
||||||
|
gamewith: '',
|
||||||
|
kamigame: '',
|
||||||
|
nicknamesEn: [],
|
||||||
|
nicknamesJp: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveChanges() {
|
||||||
|
if (!summon?.id) return
|
||||||
|
|
||||||
|
isSaving = true
|
||||||
|
saveError = null
|
||||||
|
saveSuccess = false
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
name_en: editData.name,
|
||||||
|
name_jp: editData.nameJp || undefined,
|
||||||
|
granblue_id: editData.granblueId,
|
||||||
|
rarity: editData.rarity,
|
||||||
|
element: editData.element,
|
||||||
|
series: editData.series || undefined,
|
||||||
|
min_hp: editData.minHp,
|
||||||
|
max_hp: editData.maxHp,
|
||||||
|
max_hp_flb: editData.maxHpFlb,
|
||||||
|
max_hp_ulb: editData.maxHpUlb,
|
||||||
|
max_hp_xlb: editData.maxHpTranscendence,
|
||||||
|
min_atk: editData.minAtk,
|
||||||
|
max_atk: editData.maxAtk,
|
||||||
|
max_atk_flb: editData.maxAtkFlb,
|
||||||
|
max_atk_ulb: editData.maxAtkUlb,
|
||||||
|
max_atk_xlb: editData.maxAtkTranscendence,
|
||||||
|
max_level: editData.maxLevel,
|
||||||
|
flb: editData.flb,
|
||||||
|
ulb: editData.ulb,
|
||||||
|
transcendence: editData.transcendence,
|
||||||
|
subaura: editData.subaura,
|
||||||
|
limit: editData.limit,
|
||||||
|
release_date: editData.releaseDate || null,
|
||||||
|
flb_date: editData.flbDate || null,
|
||||||
|
ulb_date: editData.ulbDate || null,
|
||||||
|
transcendence_date: editData.transcendenceDate || null,
|
||||||
|
wiki_en: editData.wikiEn,
|
||||||
|
wiki_ja: editData.wikiJa,
|
||||||
|
gamewith: editData.gamewith,
|
||||||
|
kamigame: editData.kamigame,
|
||||||
|
nicknames_en: editData.nicknamesEn,
|
||||||
|
nicknames_jp: editData.nicknamesJp
|
||||||
|
}
|
||||||
|
|
||||||
|
await entityAdapter.updateSummon(summon.id, payload)
|
||||||
|
|
||||||
|
// Invalidate TanStack Query cache to refetch fresh data
|
||||||
|
await queryClient.invalidateQueries({ queryKey: ['summon', summon.id] })
|
||||||
|
|
||||||
|
saveSuccess = true
|
||||||
|
editMode = false
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
saveSuccess = false
|
||||||
|
}, 3000)
|
||||||
|
} catch (error) {
|
||||||
|
saveError = 'Failed to save changes. Please try again.'
|
||||||
|
console.error('Save error:', error)
|
||||||
|
} finally {
|
||||||
|
isSaving = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for summon grid image
|
||||||
function getSummonGridImage(summon: any): string {
|
function getSummonGridImage(summon: any): string {
|
||||||
return getSummonImage(summon?.granblueId, 'grid')
|
return getSummonImage(summon?.granblueId, 'grid')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate uncap properties for the indicator
|
|
||||||
const uncap = $derived(summon?.uncap ?? {})
|
|
||||||
const flb = $derived(uncap.flb ?? false)
|
|
||||||
const ulb = $derived(uncap.ulb ?? false)
|
|
||||||
const transcendence = $derived(uncap.transcendence ?? false)
|
|
||||||
|
|
||||||
// Calculate maximum uncap level based on available uncaps
|
|
||||||
// Summons: 3 base + FLB + ULB + transcendence
|
|
||||||
const getMaxUncapLevel = () => {
|
|
||||||
return transcendence ? 6 : ulb ? 5 : flb ? 4 : 3
|
|
||||||
}
|
|
||||||
|
|
||||||
const uncapLevel = $derived(getMaxUncapLevel())
|
|
||||||
// For details view, show maximum transcendence stage when available
|
|
||||||
const transcendenceStage = $derived(transcendence ? 5 : 0)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="summon-detail">
|
<div>
|
||||||
{#if summon}
|
{#if summon}
|
||||||
<div class="summon-content">
|
<DetailScaffold
|
||||||
<DetailsHeader type="summon" item={summon} image={getSummonGridImage(summon)} />
|
type="summon"
|
||||||
|
item={summon}
|
||||||
|
image={getSummonGridImage(summon)}
|
||||||
|
showEdit={canEdit}
|
||||||
|
{editMode}
|
||||||
|
{isSaving}
|
||||||
|
{saveSuccess}
|
||||||
|
{saveError}
|
||||||
|
onEdit={toggleEditMode}
|
||||||
|
onSave={saveChanges}
|
||||||
|
onCancel={toggleEditMode}
|
||||||
|
>
|
||||||
|
<section class="details">
|
||||||
|
<SummonMetadataSection {summon} {editMode} bind:editData />
|
||||||
|
<SummonUncapSection {summon} {editMode} bind:editData />
|
||||||
|
<SummonTaxonomySection {summon} {editMode} bind:editData />
|
||||||
|
<SummonStatsSection {summon} {editMode} bind:editData />
|
||||||
|
|
||||||
<DetailsContainer title="HP Stats">
|
{#if editMode}
|
||||||
<DetailItem label="Base HP" value={summon.hp?.minHp} />
|
<DetailsContainer title="Nicknames">
|
||||||
<DetailItem label="Max HP" value={summon.hp?.maxHp} />
|
<DetailItem label="Nicknames (EN)">
|
||||||
{#if flb}
|
<TagInput bind:value={editData.nicknamesEn} placeholder="Add nickname..." />
|
||||||
<DetailItem label="Max HP (FLB)" value={summon.hp?.maxHpFlb} />
|
</DetailItem>
|
||||||
{/if}
|
<DetailItem label="Nicknames (JP)">
|
||||||
{#if ulb}
|
<TagInput bind:value={editData.nicknamesJp} placeholder="ニックネーム..." />
|
||||||
<DetailItem label="Max HP (ULB)" value={summon.hp?.maxHpUlb} />
|
</DetailItem>
|
||||||
{/if}
|
</DetailsContainer>
|
||||||
{#if transcendence}
|
|
||||||
<DetailItem label="Max HP (XLB)" value={summon.hp?.maxHpXlb} />
|
|
||||||
{/if}
|
|
||||||
</DetailsContainer>
|
|
||||||
|
|
||||||
<DetailsContainer title="Attack Stats">
|
<DetailsContainer title="Dates">
|
||||||
<DetailItem label="Base Attack" value={summon.atk?.minAtk} />
|
<DetailItem
|
||||||
<DetailItem label="Max Attack" value={summon.atk?.maxAtk} />
|
label="Release Date"
|
||||||
{#if flb}
|
bind:value={editData.releaseDate}
|
||||||
<DetailItem label="Max Attack (FLB)" value={summon.atk?.maxAtkFlb} />
|
editable={true}
|
||||||
{/if}
|
type="text"
|
||||||
{#if ulb}
|
placeholder="YYYY-MM-DD"
|
||||||
<DetailItem label="Max Attack (ULB)" value={summon.atk?.maxAtkUlb} />
|
|
||||||
{/if}
|
|
||||||
{#if transcendence}
|
|
||||||
<DetailItem label="Max Attack (XLB)" value={summon.atk?.maxAtkXlb} />
|
|
||||||
{/if}
|
|
||||||
</DetailsContainer>
|
|
||||||
|
|
||||||
<DetailsContainer title="Details">
|
|
||||||
<DetailItem label="Series" value={summon.series} />
|
|
||||||
{#if summon.uncap}
|
|
||||||
<DetailItem label="Uncap">
|
|
||||||
<UncapIndicator
|
|
||||||
type="summon"
|
|
||||||
{uncapLevel}
|
|
||||||
{transcendenceStage}
|
|
||||||
{flb}
|
|
||||||
{ulb}
|
|
||||||
{transcendence}
|
|
||||||
editable={false}
|
|
||||||
/>
|
/>
|
||||||
</DetailItem>
|
{#if editData.flb}
|
||||||
|
<DetailItem
|
||||||
|
label="FLB Date"
|
||||||
|
bind:value={editData.flbDate}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="YYYY-MM-DD"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{#if editData.ulb}
|
||||||
|
<DetailItem
|
||||||
|
label="ULB Date"
|
||||||
|
bind:value={editData.ulbDate}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="YYYY-MM-DD"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{#if editData.transcendence}
|
||||||
|
<DetailItem
|
||||||
|
label="Transcendence Date"
|
||||||
|
bind:value={editData.transcendenceDate}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="YYYY-MM-DD"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</DetailsContainer>
|
||||||
|
|
||||||
|
<DetailsContainer title="Links">
|
||||||
|
<DetailItem
|
||||||
|
label="Wiki (EN)"
|
||||||
|
bind:value={editData.wikiEn}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="https://gbf.wiki/..."
|
||||||
|
width="480px"
|
||||||
|
/>
|
||||||
|
<DetailItem
|
||||||
|
label="Wiki (JP)"
|
||||||
|
bind:value={editData.wikiJa}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="https://gbf-wiki.com/..."
|
||||||
|
width="480px"
|
||||||
|
/>
|
||||||
|
<DetailItem
|
||||||
|
label="Gamewith"
|
||||||
|
bind:value={editData.gamewith}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="https://xn--bck3aza1a2if6kra4ee0hf.gamewith.jp/..."
|
||||||
|
width="480px"
|
||||||
|
/>
|
||||||
|
<DetailItem
|
||||||
|
label="Kamigame"
|
||||||
|
bind:value={editData.kamigame}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="https://kamigame.jp/..."
|
||||||
|
width="480px"
|
||||||
|
/>
|
||||||
|
</DetailsContainer>
|
||||||
{/if}
|
{/if}
|
||||||
</DetailsContainer>
|
|
||||||
|
|
||||||
<div class="summon-abilities">
|
{#if !editMode}
|
||||||
<h3>Call Effect</h3>
|
<div class="summon-abilities">
|
||||||
<div class="abilities-section">
|
<h3>Call Effect</h3>
|
||||||
{#if summon.callName || summon.callDescription}
|
<div class="abilities-section">
|
||||||
<div class="ability-item">
|
{#if summon.callName || summon.callDescription}
|
||||||
<h4 class="ability-name">{summon.callName || 'Call Effect'}</h4>
|
<div class="ability-item">
|
||||||
<p class="ability-description">
|
<h4 class="ability-name">{summon.callName || 'Call Effect'}</h4>
|
||||||
{summon.callDescription || 'No description available'}
|
<p class="ability-description">
|
||||||
</p>
|
{summon.callDescription || 'No description available'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<p class="no-abilities">No call effect information available</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
|
||||||
<p class="no-abilities">No call effect information available</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>Aura Effect</h3>
|
<h3>Aura Effect</h3>
|
||||||
<div class="abilities-section">
|
<div class="abilities-section">
|
||||||
{#if summon.auraName || summon.auraDescription}
|
{#if summon.auraName || summon.auraDescription}
|
||||||
<div class="ability-item">
|
<div class="ability-item">
|
||||||
<h4 class="ability-name">{summon.auraName || 'Aura Effect'}</h4>
|
<h4 class="ability-name">{summon.auraName || 'Aura Effect'}</h4>
|
||||||
<p class="ability-description">
|
<p class="ability-description">
|
||||||
{summon.auraDescription || 'No description available'}
|
{summon.auraDescription || 'No description available'}
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<p class="no-abilities">No aura effect information available</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
|
||||||
<p class="no-abilities">No aura effect information available</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if summon.subAuraName || summon.subAuraDescription}
|
{#if summon.subAuraName || summon.subAuraDescription}
|
||||||
<h3>Sub Aura Effect</h3>
|
<h3>Sub Aura Effect</h3>
|
||||||
<div class="abilities-section">
|
<div class="abilities-section">
|
||||||
<div class="ability-item">
|
<div class="ability-item">
|
||||||
<h4 class="ability-name">{summon.subAuraName || 'Sub Aura Effect'}</h4>
|
<h4 class="ability-name">{summon.subAuraName || 'Sub Aura Effect'}</h4>
|
||||||
<p class="ability-description">
|
<p class="ability-description">
|
||||||
{summon.subAuraDescription || 'No description available'}
|
{summon.subAuraDescription || 'No description available'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</section>
|
||||||
</div>
|
</DetailScaffold>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="not-found">
|
<div class="not-found">
|
||||||
<h2>Summon Not Found</h2>
|
<h2>Summon Not Found</h2>
|
||||||
|
|
@ -160,35 +397,6 @@
|
||||||
@use '$src/themes/spacing' as spacing;
|
@use '$src/themes/spacing' as spacing;
|
||||||
@use '$src/themes/typography' as typography;
|
@use '$src/themes/typography' as typography;
|
||||||
|
|
||||||
.summon-detail {
|
|
||||||
padding: spacing.$unit-2x 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
margin-bottom: spacing.$unit-2x;
|
|
||||||
|
|
||||||
.back-button {
|
|
||||||
background: #f8f9fa;
|
|
||||||
border: 1px solid #dee2e6;
|
|
||||||
padding: spacing.$unit-half spacing.$unit;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: typography.$font-small;
|
|
||||||
margin-bottom: spacing.$unit;
|
|
||||||
transition: all 0.2s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #e9ecef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: typography.$font-xxlarge;
|
|
||||||
font-weight: typography.$bold;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.not-found {
|
.not-found {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: spacing.$unit * 4;
|
padding: spacing.$unit * 4;
|
||||||
|
|
@ -208,11 +416,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.summon-content {
|
.details {
|
||||||
background: white;
|
display: flex;
|
||||||
border-radius: 8px;
|
flex-direction: column;
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.summon-abilities {
|
.summon-abilities {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue