import pages: add wiki_raw to payload, misc fixes
This commit is contained in:
parent
5edcf6473a
commit
6683a9e53a
5 changed files with 220 additions and 168 deletions
|
|
@ -242,6 +242,7 @@ export interface CreateCharacterPayload {
|
|||
kamigame?: string
|
||||
nicknames_en?: string[]
|
||||
nicknames_jp?: string[]
|
||||
wiki_raw?: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
const placeholderImage = $derived(() => {
|
||||
switch (entityType) {
|
||||
case 'character':
|
||||
return '/images/placeholders/placeholder-character-grid.png'
|
||||
return '/images/placeholders/placeholder-character-square.png'
|
||||
case 'weapon':
|
||||
return '/images/placeholders/placeholder-weapon-grid.png'
|
||||
return '/images/placeholders/placeholder-weapon-square.png'
|
||||
case 'summon':
|
||||
return '/images/placeholders/placeholder-summon-sub.png'
|
||||
return '/images/placeholders/placeholder-summon-square.png'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
status: 'loading' | 'success' | 'error'
|
||||
granblueId?: string
|
||||
suggestions?: CharacterSuggestions
|
||||
wikiRaw?: string
|
||||
error?: string
|
||||
}
|
||||
|
||||
|
|
@ -82,8 +83,8 @@
|
|||
granblueId: entity.granblueId,
|
||||
status: entity.status,
|
||||
imageUrl: entity.granblueId
|
||||
? getCharacterImage(entity.granblueId, 'grid')
|
||||
: '/images/placeholders/placeholder-character-grid.png',
|
||||
? getCharacterImage(entity.granblueId, 'square')
|
||||
: '/images/placeholders/placeholder-character-square.png',
|
||||
error: entity.error,
|
||||
saved: savedEntities.has(wikiPage)
|
||||
}))
|
||||
|
|
@ -95,7 +96,7 @@
|
|||
name: suggestions?.nameEn ?? '',
|
||||
nameJp: suggestions?.nameJp ?? '',
|
||||
granblueId: suggestions?.granblueId ?? '',
|
||||
characterId: '',
|
||||
characterId: suggestions?.characterId?.join(', ') ?? '',
|
||||
rarity: suggestions?.rarity ?? 3,
|
||||
element: suggestions?.element ?? 0,
|
||||
race1: suggestions?.race1 ?? null,
|
||||
|
|
@ -169,6 +170,7 @@
|
|||
status: result.status,
|
||||
granblueId: result.granblueId,
|
||||
suggestions: result.suggestions,
|
||||
wikiRaw: result.wikiRaw,
|
||||
error: result.error
|
||||
})
|
||||
|
||||
|
|
@ -222,6 +224,7 @@
|
|||
if (!selectedWikiPage) return
|
||||
const formData = formDataMap.get(selectedWikiPage)
|
||||
if (!formData) return
|
||||
const entity = entities.get(selectedWikiPage)
|
||||
|
||||
isSaving = true
|
||||
saveError = null
|
||||
|
|
@ -268,7 +271,8 @@
|
|||
gamewith: formData.gamewith,
|
||||
kamigame: formData.kamigame,
|
||||
nicknames_en: formData.nicknamesEn,
|
||||
nicknames_jp: formData.nicknamesJp
|
||||
nicknames_jp: formData.nicknamesJp,
|
||||
wiki_raw: entity?.wikiRaw || null
|
||||
}
|
||||
|
||||
await entityAdapter.createCharacter(payload)
|
||||
|
|
@ -421,7 +425,7 @@
|
|||
<CharacterMetadataSection
|
||||
character={emptyCharacter}
|
||||
editMode={true}
|
||||
bind:editData={formData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -431,7 +435,7 @@
|
|||
<CharacterUncapSection
|
||||
character={emptyCharacter}
|
||||
editMode={true}
|
||||
bind:editData={formData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -441,7 +445,7 @@
|
|||
<CharacterTaxonomySection
|
||||
character={emptyCharacter}
|
||||
editMode={true}
|
||||
bind:editData={formData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -451,7 +455,7 @@
|
|||
<CharacterStatsSection
|
||||
character={emptyCharacter}
|
||||
editMode={true}
|
||||
bind:editData={formData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -549,6 +553,14 @@
|
|||
onDismissSuggestion={() => handleDismissSuggestion('kamigame')}
|
||||
/>
|
||||
</DetailsContainer>
|
||||
|
||||
{#if selectedEntity?.wikiRaw}
|
||||
<DetailsContainer title="Raw Wiki Data">
|
||||
<div class="wiki-raw">
|
||||
<pre>{selectedEntity.wikiRaw}</pre>
|
||||
</div>
|
||||
</DetailsContainer>
|
||||
{/if}
|
||||
</section>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
@ -627,4 +639,20 @@
|
|||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wiki-raw {
|
||||
padding: spacing.$unit;
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: spacing.$unit;
|
||||
background: colors.$grey-95;
|
||||
border-radius: 4px;
|
||||
font-size: typography.$font-small;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import {
|
||||
entityAdapter,
|
||||
type SummonSuggestions,
|
||||
type BatchPreviewResult
|
||||
} from '$lib/api/adapters/entity.adapter'
|
||||
import { entityAdapter, type SummonSuggestions } from '$lib/api/adapters/entity.adapter'
|
||||
import { getSummonImage } from '$lib/utils/images'
|
||||
|
||||
// Components
|
||||
|
|
@ -26,6 +22,15 @@
|
|||
|
||||
import type { PageData } from './$types'
|
||||
|
||||
// Internal entity state including loading status
|
||||
interface EntityState {
|
||||
wikiPage: string
|
||||
status: 'loading' | 'success' | 'error'
|
||||
granblueId?: string
|
||||
suggestions?: SummonSuggestions
|
||||
error?: string
|
||||
}
|
||||
|
||||
let { data }: { data: PageData } = $props()
|
||||
|
||||
// Input phase
|
||||
|
|
@ -34,7 +39,7 @@
|
|||
let fetchError = $state<string | null>(null)
|
||||
|
||||
// Fetched entities
|
||||
let entities = $state<Map<string, BatchPreviewResult<SummonSuggestions>>>(new Map())
|
||||
let entities = $state<Map<string, EntityState>>(new Map())
|
||||
let selectedWikiPage = $state<string | null>(null)
|
||||
|
||||
// Form data per entity (keyed by wikiPage)
|
||||
|
|
@ -65,10 +70,6 @@
|
|||
|
||||
// Get selected entity data
|
||||
const selectedEntity = $derived(selectedWikiPage ? entities.get(selectedWikiPage) : null)
|
||||
const selectedFormData = $derived(selectedWikiPage ? formDataMap.get(selectedWikiPage) : null)
|
||||
const selectedDismissed = $derived(
|
||||
selectedWikiPage ? dismissedSuggestionsMap.get(selectedWikiPage) ?? new Set() : new Set()
|
||||
)
|
||||
|
||||
// Entity tabs for TabbedEntitySelector
|
||||
const entityTabs = $derived<EntityTab[]>(
|
||||
|
|
@ -77,8 +78,8 @@
|
|||
granblueId: entity.granblueId,
|
||||
status: entity.status,
|
||||
imageUrl: entity.granblueId
|
||||
? getSummonImage(entity.granblueId)
|
||||
: '/images/placeholders/placeholder-summon-sub.png',
|
||||
? getSummonImage(entity.granblueId, 'square')
|
||||
: '/images/placeholders/placeholder-summon-square.png',
|
||||
error: entity.error,
|
||||
saved: savedEntities.has(wikiPage)
|
||||
}))
|
||||
|
|
@ -140,11 +141,11 @@
|
|||
fetchError = null
|
||||
|
||||
// Initialize entities as loading
|
||||
const newEntities = new Map<string, BatchPreviewResult<SummonSuggestions>>()
|
||||
const newEntities = new Map<string, EntityState>()
|
||||
pages.forEach((page) => {
|
||||
newEntities.set(page, {
|
||||
wikiPage: page,
|
||||
status: 'loading' as const
|
||||
status: 'loading'
|
||||
})
|
||||
})
|
||||
entities = newEntities
|
||||
|
|
@ -154,15 +155,21 @@
|
|||
const response = await entityAdapter.batchPreviewSummons(pages)
|
||||
|
||||
// Update entities with results
|
||||
const updatedEntities = new Map<string, BatchPreviewResult<SummonSuggestions>>()
|
||||
const updatedEntities = new Map<string, EntityState>()
|
||||
response.results.forEach((result) => {
|
||||
updatedEntities.set(result.wikiPage, result)
|
||||
updatedEntities.set(result.wikiPage, {
|
||||
wikiPage: result.wikiPage,
|
||||
status: result.status,
|
||||
granblueId: result.granblueId,
|
||||
suggestions: result.suggestions,
|
||||
error: result.error
|
||||
})
|
||||
|
||||
// Create form data for successful results
|
||||
if (result.status === 'success') {
|
||||
const formData = createEmptyFormData(result.wikiPage, result.suggestions)
|
||||
formDataMap.set(result.wikiPage, formData)
|
||||
dismissedSuggestionsMap.set(result.wikiPage, new Set())
|
||||
dismissedSuggestionsMap.set(result.wikiPage, new Set<string>())
|
||||
}
|
||||
})
|
||||
entities = updatedEntities
|
||||
|
|
@ -185,7 +192,7 @@
|
|||
|
||||
// Accept a suggestion
|
||||
function handleAcceptSuggestion(field: string, value: any) {
|
||||
if (!selectedWikiPage || !selectedFormData) return
|
||||
if (!selectedWikiPage) return
|
||||
|
||||
const formData = formDataMap.get(selectedWikiPage)
|
||||
if (formData) {
|
||||
|
|
@ -205,46 +212,48 @@
|
|||
|
||||
// Save current entity
|
||||
async function saveCurrentEntity() {
|
||||
if (!selectedWikiPage || !selectedFormData) return
|
||||
if (!selectedWikiPage) return
|
||||
const formData = formDataMap.get(selectedWikiPage)
|
||||
if (!formData) return
|
||||
|
||||
isSaving = true
|
||||
saveError = null
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
granblue_id: selectedFormData.granblue_id,
|
||||
name_en: selectedFormData.name,
|
||||
name_jp: selectedFormData.nameJp,
|
||||
summon_id: selectedFormData.summonId || undefined,
|
||||
rarity: selectedFormData.rarity,
|
||||
element: selectedFormData.element,
|
||||
series: selectedFormData.series || undefined,
|
||||
min_hp: selectedFormData.minHp,
|
||||
max_hp: selectedFormData.maxHp,
|
||||
max_hp_flb: selectedFormData.maxHpFlb,
|
||||
max_hp_ulb: selectedFormData.maxHpUlb,
|
||||
max_hp_xlb: selectedFormData.maxHpTranscendence,
|
||||
min_atk: selectedFormData.minAtk,
|
||||
max_atk: selectedFormData.maxAtk,
|
||||
max_atk_flb: selectedFormData.maxAtkFlb,
|
||||
max_atk_ulb: selectedFormData.maxAtkUlb,
|
||||
max_atk_xlb: selectedFormData.maxAtkTranscendence,
|
||||
max_level: selectedFormData.maxLevel,
|
||||
flb: selectedFormData.flb,
|
||||
ulb: selectedFormData.ulb,
|
||||
transcendence: selectedFormData.transcendence,
|
||||
subaura: selectedFormData.subaura,
|
||||
limit: selectedFormData.limit,
|
||||
release_date: selectedFormData.releaseDate || null,
|
||||
flb_date: selectedFormData.flbDate || null,
|
||||
ulb_date: selectedFormData.ulbDate || null,
|
||||
transcendence_date: selectedFormData.transcendenceDate || null,
|
||||
wiki_en: selectedFormData.wikiEn,
|
||||
wiki_ja: selectedFormData.wikiJa,
|
||||
gamewith: selectedFormData.gamewith,
|
||||
kamigame: selectedFormData.kamigame,
|
||||
nicknames_en: selectedFormData.nicknamesEn,
|
||||
nicknames_jp: selectedFormData.nicknamesJp
|
||||
granblue_id: formData.granblue_id,
|
||||
name_en: formData.name,
|
||||
name_jp: formData.nameJp,
|
||||
summon_id: formData.summonId || undefined,
|
||||
rarity: formData.rarity,
|
||||
element: formData.element,
|
||||
series: formData.series || undefined,
|
||||
min_hp: formData.minHp,
|
||||
max_hp: formData.maxHp,
|
||||
max_hp_flb: formData.maxHpFlb,
|
||||
max_hp_ulb: formData.maxHpUlb,
|
||||
max_hp_xlb: formData.maxHpTranscendence,
|
||||
min_atk: formData.minAtk,
|
||||
max_atk: formData.maxAtk,
|
||||
max_atk_flb: formData.maxAtkFlb,
|
||||
max_atk_ulb: formData.maxAtkUlb,
|
||||
max_atk_xlb: formData.maxAtkTranscendence,
|
||||
max_level: formData.maxLevel,
|
||||
flb: formData.flb,
|
||||
ulb: formData.ulb,
|
||||
transcendence: formData.transcendence,
|
||||
subaura: formData.subaura,
|
||||
limit: formData.limit,
|
||||
release_date: formData.releaseDate || null,
|
||||
flb_date: formData.flbDate || null,
|
||||
ulb_date: formData.ulbDate || null,
|
||||
transcendence_date: formData.transcendenceDate || null,
|
||||
wiki_en: formData.wikiEn,
|
||||
wiki_ja: formData.wikiJa,
|
||||
gamewith: formData.gamewith,
|
||||
kamigame: formData.kamigame,
|
||||
nicknames_en: formData.nicknamesEn,
|
||||
nicknames_jp: formData.nicknamesJp
|
||||
}
|
||||
|
||||
await entityAdapter.createSummon(payload)
|
||||
|
|
@ -269,12 +278,16 @@
|
|||
}
|
||||
|
||||
// Can save current entity
|
||||
const canSave = $derived(
|
||||
selectedFormData &&
|
||||
selectedFormData.name.trim() !== '' &&
|
||||
selectedFormData.granblue_id.trim() !== '' &&
|
||||
!savedEntities.has(selectedWikiPage ?? '')
|
||||
)
|
||||
const canSave = $derived.by(() => {
|
||||
if (!selectedWikiPage) return false
|
||||
const formData = formDataMap.get(selectedWikiPage)
|
||||
if (!formData) return false
|
||||
return (
|
||||
formData.name.trim() !== '' &&
|
||||
formData.granblue_id.trim() !== '' &&
|
||||
!savedEntities.has(selectedWikiPage)
|
||||
)
|
||||
})
|
||||
|
||||
// All entities saved
|
||||
const allSaved = $derived(
|
||||
|
|
@ -352,14 +365,15 @@
|
|||
<div class="entity-loading">
|
||||
<p>Loading wiki data...</p>
|
||||
</div>
|
||||
{:else if selectedFormData}
|
||||
{:else if selectedWikiPage && formDataMap.has(selectedWikiPage)}
|
||||
{@const formData = formDataMap.get(selectedWikiPage)!}
|
||||
{@const suggestions = selectedEntity.suggestions}
|
||||
{@const dismissed = selectedDismissed}
|
||||
{@const dismissed = dismissedSuggestionsMap.get(selectedWikiPage) ?? new Set<string>()}
|
||||
<section class="details">
|
||||
<DetailsContainer title="Basic Info">
|
||||
<SuggestionDetailItem
|
||||
label="Name (EN)"
|
||||
bind:value={selectedFormData.name}
|
||||
bind:value={formData.name}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="Summon name"
|
||||
|
|
@ -370,7 +384,7 @@
|
|||
/>
|
||||
<SuggestionDetailItem
|
||||
label="Name (JP)"
|
||||
bind:value={selectedFormData.nameJp}
|
||||
bind:value={formData.nameJp}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="召喚石名"
|
||||
|
|
@ -382,7 +396,7 @@
|
|||
<DetailItem
|
||||
label="Summon ID"
|
||||
sublabel="Internal game identifier (if known)"
|
||||
bind:value={selectedFormData.summonId}
|
||||
bind:value={formData.summonId}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="Optional"
|
||||
|
|
@ -392,7 +406,7 @@
|
|||
<SummonMetadataSection
|
||||
summon={emptySummon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -402,7 +416,7 @@
|
|||
<SummonUncapSection
|
||||
summon={emptySummon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -412,7 +426,7 @@
|
|||
<SummonTaxonomySection
|
||||
summon={emptySummon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -422,7 +436,7 @@
|
|||
<SummonStatsSection
|
||||
summon={emptySummon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -431,17 +445,17 @@
|
|||
|
||||
<DetailsContainer title="Nicknames">
|
||||
<DetailItem label="Nicknames (EN)">
|
||||
<TagInput bind:value={selectedFormData.nicknamesEn} placeholder="Add nickname..." contained />
|
||||
<TagInput bind:value={formData.nicknamesEn} placeholder="Add nickname..." contained />
|
||||
</DetailItem>
|
||||
<DetailItem label="Nicknames (JP)">
|
||||
<TagInput bind:value={selectedFormData.nicknamesJp} placeholder="ニックネーム..." contained />
|
||||
<TagInput bind:value={formData.nicknamesJp} placeholder="ニックネーム..." contained />
|
||||
</DetailItem>
|
||||
</DetailsContainer>
|
||||
|
||||
<DetailsContainer title="Dates">
|
||||
<SuggestionDetailItem
|
||||
label="Release Date"
|
||||
bind:value={selectedFormData.releaseDate}
|
||||
bind:value={formData.releaseDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -450,10 +464,10 @@
|
|||
onAcceptSuggestion={() => handleAcceptSuggestion('releaseDate', suggestions?.releaseDate)}
|
||||
onDismissSuggestion={() => handleDismissSuggestion('releaseDate')}
|
||||
/>
|
||||
{#if selectedFormData.flb}
|
||||
{#if formData.flb}
|
||||
<SuggestionDetailItem
|
||||
label="FLB Date"
|
||||
bind:value={selectedFormData.flbDate}
|
||||
bind:value={formData.flbDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -463,10 +477,10 @@
|
|||
onDismissSuggestion={() => handleDismissSuggestion('flbDate')}
|
||||
/>
|
||||
{/if}
|
||||
{#if selectedFormData.ulb}
|
||||
{#if formData.ulb}
|
||||
<SuggestionDetailItem
|
||||
label="ULB Date"
|
||||
bind:value={selectedFormData.ulbDate}
|
||||
bind:value={formData.ulbDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -476,10 +490,10 @@
|
|||
onDismissSuggestion={() => handleDismissSuggestion('ulbDate')}
|
||||
/>
|
||||
{/if}
|
||||
{#if selectedFormData.transcendence}
|
||||
{#if formData.transcendence}
|
||||
<DetailItem
|
||||
label="Transcendence Date"
|
||||
bind:value={selectedFormData.transcendenceDate}
|
||||
bind:value={formData.transcendenceDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -490,7 +504,7 @@
|
|||
<DetailsContainer title="Links">
|
||||
<DetailItem
|
||||
label="Wiki (EN)"
|
||||
bind:value={selectedFormData.wikiEn}
|
||||
bind:value={formData.wikiEn}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://gbf.wiki/..."
|
||||
|
|
@ -498,7 +512,7 @@
|
|||
/>
|
||||
<DetailItem
|
||||
label="Wiki (JP)"
|
||||
bind:value={selectedFormData.wikiJa}
|
||||
bind:value={formData.wikiJa}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://gbf-wiki.com/..."
|
||||
|
|
@ -506,7 +520,7 @@
|
|||
/>
|
||||
<SuggestionDetailItem
|
||||
label="Gamewith"
|
||||
bind:value={selectedFormData.gamewith}
|
||||
bind:value={formData.gamewith}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://..."
|
||||
|
|
@ -518,7 +532,7 @@
|
|||
/>
|
||||
<SuggestionDetailItem
|
||||
label="Kamigame"
|
||||
bind:value={selectedFormData.kamigame}
|
||||
bind:value={formData.kamigame}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://..."
|
||||
|
|
|
|||
|
|
@ -69,10 +69,6 @@
|
|||
|
||||
// Get selected entity data
|
||||
const selectedEntity = $derived(selectedWikiPage ? entities.get(selectedWikiPage) : null)
|
||||
const selectedFormData = $derived(selectedWikiPage ? formDataMap.get(selectedWikiPage) : null)
|
||||
const selectedDismissed = $derived(
|
||||
selectedWikiPage ? dismissedSuggestionsMap.get(selectedWikiPage) ?? new Set() : new Set()
|
||||
)
|
||||
|
||||
// Entity tabs for TabbedEntitySelector
|
||||
const entityTabs = $derived<EntityTab[]>(
|
||||
|
|
@ -81,8 +77,8 @@
|
|||
granblueId: entity.granblueId,
|
||||
status: entity.status,
|
||||
imageUrl: entity.granblueId
|
||||
? getWeaponImage(entity.granblueId)
|
||||
: '/images/placeholders/placeholder-weapon-grid.png',
|
||||
? getWeaponImage(entity.granblueId, 'square')
|
||||
: '/images/placeholders/placeholder-weapon-square.png',
|
||||
error: entity.error,
|
||||
saved: savedEntities.has(wikiPage)
|
||||
}))
|
||||
|
|
@ -147,11 +143,11 @@
|
|||
fetchError = null
|
||||
|
||||
// Initialize entities as loading
|
||||
const newEntities = new Map<string, BatchPreviewResult<WeaponSuggestions>>()
|
||||
const newEntities = new Map<string, EntityState>()
|
||||
pages.forEach((page) => {
|
||||
newEntities.set(page, {
|
||||
wikiPage: page,
|
||||
status: 'loading' as const
|
||||
status: 'loading'
|
||||
})
|
||||
})
|
||||
entities = newEntities
|
||||
|
|
@ -161,15 +157,21 @@
|
|||
const response = await entityAdapter.batchPreviewWeapons(pages)
|
||||
|
||||
// Update entities with results
|
||||
const updatedEntities = new Map<string, BatchPreviewResult<WeaponSuggestions>>()
|
||||
const updatedEntities = new Map<string, EntityState>()
|
||||
response.results.forEach((result) => {
|
||||
updatedEntities.set(result.wikiPage, result)
|
||||
updatedEntities.set(result.wikiPage, {
|
||||
wikiPage: result.wikiPage,
|
||||
status: result.status,
|
||||
granblueId: result.granblueId,
|
||||
suggestions: result.suggestions,
|
||||
error: result.error
|
||||
})
|
||||
|
||||
// Create form data for successful results
|
||||
if (result.status === 'success') {
|
||||
const formData = createEmptyFormData(result.wikiPage, result.suggestions)
|
||||
formDataMap.set(result.wikiPage, formData)
|
||||
dismissedSuggestionsMap.set(result.wikiPage, new Set())
|
||||
dismissedSuggestionsMap.set(result.wikiPage, new Set<string>())
|
||||
}
|
||||
})
|
||||
entities = updatedEntities
|
||||
|
|
@ -192,7 +194,7 @@
|
|||
|
||||
// Accept a suggestion
|
||||
function handleAcceptSuggestion(field: string, value: any) {
|
||||
if (!selectedWikiPage || !selectedFormData) return
|
||||
if (!selectedWikiPage) return
|
||||
|
||||
const formData = formDataMap.get(selectedWikiPage)
|
||||
if (formData) {
|
||||
|
|
@ -212,49 +214,51 @@
|
|||
|
||||
// Save current entity
|
||||
async function saveCurrentEntity() {
|
||||
if (!selectedWikiPage || !selectedFormData) return
|
||||
if (!selectedWikiPage) return
|
||||
const formData = formDataMap.get(selectedWikiPage)
|
||||
if (!formData) return
|
||||
|
||||
isSaving = true
|
||||
saveError = null
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
granblue_id: selectedFormData.granblue_id,
|
||||
name_en: selectedFormData.name,
|
||||
name_jp: selectedFormData.nameJp || undefined,
|
||||
rarity: selectedFormData.rarity,
|
||||
element: selectedFormData.element,
|
||||
proficiency: selectedFormData.proficiency,
|
||||
series: selectedFormData.series || undefined,
|
||||
new_series: selectedFormData.newSeries || undefined,
|
||||
min_hp: selectedFormData.minHp,
|
||||
max_hp: selectedFormData.maxHp,
|
||||
max_hp_flb: selectedFormData.maxHpFlb,
|
||||
max_hp_ulb: selectedFormData.maxHpUlb,
|
||||
min_atk: selectedFormData.minAtk,
|
||||
max_atk: selectedFormData.maxAtk,
|
||||
max_atk_flb: selectedFormData.maxAtkFlb,
|
||||
max_atk_ulb: selectedFormData.maxAtkUlb,
|
||||
max_level: selectedFormData.maxLevel,
|
||||
max_skill_level: selectedFormData.maxSkillLevel,
|
||||
max_awakening_level: selectedFormData.maxAwakeningLevel,
|
||||
flb: selectedFormData.flb,
|
||||
ulb: selectedFormData.ulb,
|
||||
transcendence: selectedFormData.transcendence,
|
||||
extra: selectedFormData.extra,
|
||||
limit: selectedFormData.limit,
|
||||
ax: selectedFormData.ax,
|
||||
release_date: selectedFormData.releaseDate || null,
|
||||
flb_date: selectedFormData.flbDate || null,
|
||||
ulb_date: selectedFormData.ulbDate || null,
|
||||
transcendence_date: selectedFormData.transcendenceDate || null,
|
||||
wiki_en: selectedFormData.wikiEn,
|
||||
wiki_ja: selectedFormData.wikiJa,
|
||||
gamewith: selectedFormData.gamewith,
|
||||
kamigame: selectedFormData.kamigame,
|
||||
nicknames_en: selectedFormData.nicknamesEn,
|
||||
nicknames_jp: selectedFormData.nicknamesJp,
|
||||
recruits: selectedFormData.recruits
|
||||
granblue_id: formData.granblue_id,
|
||||
name_en: formData.name,
|
||||
name_jp: formData.nameJp || undefined,
|
||||
rarity: formData.rarity,
|
||||
element: formData.element,
|
||||
proficiency: formData.proficiency,
|
||||
series: formData.series || undefined,
|
||||
new_series: formData.newSeries || undefined,
|
||||
min_hp: formData.minHp,
|
||||
max_hp: formData.maxHp,
|
||||
max_hp_flb: formData.maxHpFlb,
|
||||
max_hp_ulb: formData.maxHpUlb,
|
||||
min_atk: formData.minAtk,
|
||||
max_atk: formData.maxAtk,
|
||||
max_atk_flb: formData.maxAtkFlb,
|
||||
max_atk_ulb: formData.maxAtkUlb,
|
||||
max_level: formData.maxLevel,
|
||||
max_skill_level: formData.maxSkillLevel,
|
||||
max_awakening_level: formData.maxAwakeningLevel,
|
||||
flb: formData.flb,
|
||||
ulb: formData.ulb,
|
||||
transcendence: formData.transcendence,
|
||||
extra: formData.extra,
|
||||
limit: formData.limit,
|
||||
ax: formData.ax,
|
||||
release_date: formData.releaseDate || null,
|
||||
flb_date: formData.flbDate || null,
|
||||
ulb_date: formData.ulbDate || null,
|
||||
transcendence_date: formData.transcendenceDate || null,
|
||||
wiki_en: formData.wikiEn,
|
||||
wiki_ja: formData.wikiJa,
|
||||
gamewith: formData.gamewith,
|
||||
kamigame: formData.kamigame,
|
||||
nicknames_en: formData.nicknamesEn,
|
||||
nicknames_jp: formData.nicknamesJp,
|
||||
recruits: formData.recruits
|
||||
}
|
||||
|
||||
await entityAdapter.createWeapon(payload)
|
||||
|
|
@ -279,12 +283,16 @@
|
|||
}
|
||||
|
||||
// Can save current entity
|
||||
const canSave = $derived(
|
||||
selectedFormData &&
|
||||
selectedFormData.name.trim() !== '' &&
|
||||
selectedFormData.granblue_id.trim() !== '' &&
|
||||
!savedEntities.has(selectedWikiPage ?? '')
|
||||
)
|
||||
const canSave = $derived.by(() => {
|
||||
if (!selectedWikiPage) return false
|
||||
const formData = formDataMap.get(selectedWikiPage)
|
||||
if (!formData) return false
|
||||
return (
|
||||
formData.name.trim() !== '' &&
|
||||
formData.granblue_id.trim() !== '' &&
|
||||
!savedEntities.has(selectedWikiPage)
|
||||
)
|
||||
})
|
||||
|
||||
// All entities saved
|
||||
const allSaved = $derived(
|
||||
|
|
@ -362,14 +370,15 @@
|
|||
<div class="entity-loading">
|
||||
<p>Loading wiki data...</p>
|
||||
</div>
|
||||
{:else if selectedFormData}
|
||||
{:else if selectedWikiPage && formDataMap.has(selectedWikiPage)}
|
||||
{@const formData = formDataMap.get(selectedWikiPage)!}
|
||||
{@const suggestions = selectedEntity.suggestions}
|
||||
{@const dismissed = selectedDismissed}
|
||||
{@const dismissed = dismissedSuggestionsMap.get(selectedWikiPage) ?? new Set<string>()}
|
||||
<section class="details">
|
||||
<DetailsContainer title="Basic Info">
|
||||
<SuggestionDetailItem
|
||||
label="Name (EN)"
|
||||
bind:value={selectedFormData.name}
|
||||
bind:value={formData.name}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="Weapon name"
|
||||
|
|
@ -380,7 +389,7 @@
|
|||
/>
|
||||
<SuggestionDetailItem
|
||||
label="Name (JP)"
|
||||
bind:value={selectedFormData.nameJp}
|
||||
bind:value={formData.nameJp}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="武器名"
|
||||
|
|
@ -394,7 +403,7 @@
|
|||
<WeaponMetadataSection
|
||||
weapon={emptyWeapon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -404,7 +413,7 @@
|
|||
<WeaponUncapSection
|
||||
weapon={emptyWeapon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -414,7 +423,7 @@
|
|||
<WeaponTaxonomySection
|
||||
weapon={emptyWeapon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -424,7 +433,7 @@
|
|||
<WeaponStatsSection
|
||||
weapon={emptyWeapon}
|
||||
editMode={true}
|
||||
bind:editData={selectedFormData}
|
||||
editData={formData}
|
||||
{suggestions}
|
||||
dismissedSuggestions={dismissed}
|
||||
onAcceptSuggestion={handleAcceptSuggestion}
|
||||
|
|
@ -433,23 +442,23 @@
|
|||
|
||||
<DetailsContainer title="Nicknames">
|
||||
<DetailItem label="Nicknames (EN)">
|
||||
<TagInput bind:value={selectedFormData.nicknamesEn} placeholder="Add nickname..." contained />
|
||||
<TagInput bind:value={formData.nicknamesEn} placeholder="Add nickname..." contained />
|
||||
</DetailItem>
|
||||
<DetailItem label="Nicknames (JP)">
|
||||
<TagInput bind:value={selectedFormData.nicknamesJp} placeholder="ニックネーム..." contained />
|
||||
<TagInput bind:value={formData.nicknamesJp} placeholder="ニックネーム..." contained />
|
||||
</DetailItem>
|
||||
</DetailsContainer>
|
||||
|
||||
<DetailsContainer title="Recruits">
|
||||
<DetailItem label="Recruits Character" sublabel="Character recruited by this weapon">
|
||||
<CharacterTypeahead bind:value={selectedFormData.recruits} placeholder="Search for character..." />
|
||||
<CharacterTypeahead bind:value={formData.recruits} placeholder="Search for character..." />
|
||||
</DetailItem>
|
||||
</DetailsContainer>
|
||||
|
||||
<DetailsContainer title="Dates">
|
||||
<SuggestionDetailItem
|
||||
label="Release Date"
|
||||
bind:value={selectedFormData.releaseDate}
|
||||
bind:value={formData.releaseDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -458,10 +467,10 @@
|
|||
onAcceptSuggestion={() => handleAcceptSuggestion('releaseDate', suggestions?.releaseDate)}
|
||||
onDismissSuggestion={() => handleDismissSuggestion('releaseDate')}
|
||||
/>
|
||||
{#if selectedFormData.flb}
|
||||
{#if formData.flb}
|
||||
<SuggestionDetailItem
|
||||
label="FLB Date"
|
||||
bind:value={selectedFormData.flbDate}
|
||||
bind:value={formData.flbDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -471,10 +480,10 @@
|
|||
onDismissSuggestion={() => handleDismissSuggestion('flbDate')}
|
||||
/>
|
||||
{/if}
|
||||
{#if selectedFormData.ulb}
|
||||
{#if formData.ulb}
|
||||
<SuggestionDetailItem
|
||||
label="ULB Date"
|
||||
bind:value={selectedFormData.ulbDate}
|
||||
bind:value={formData.ulbDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -484,10 +493,10 @@
|
|||
onDismissSuggestion={() => handleDismissSuggestion('ulbDate')}
|
||||
/>
|
||||
{/if}
|
||||
{#if selectedFormData.transcendence}
|
||||
{#if formData.transcendence}
|
||||
<DetailItem
|
||||
label="Transcendence Date"
|
||||
bind:value={selectedFormData.transcendenceDate}
|
||||
bind:value={formData.transcendenceDate}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="YYYY-MM-DD"
|
||||
|
|
@ -498,7 +507,7 @@
|
|||
<DetailsContainer title="Links">
|
||||
<DetailItem
|
||||
label="Wiki (EN)"
|
||||
bind:value={selectedFormData.wikiEn}
|
||||
bind:value={formData.wikiEn}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://gbf.wiki/..."
|
||||
|
|
@ -506,7 +515,7 @@
|
|||
/>
|
||||
<DetailItem
|
||||
label="Wiki (JP)"
|
||||
bind:value={selectedFormData.wikiJa}
|
||||
bind:value={formData.wikiJa}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://gbf-wiki.com/..."
|
||||
|
|
@ -514,7 +523,7 @@
|
|||
/>
|
||||
<SuggestionDetailItem
|
||||
label="Gamewith"
|
||||
bind:value={selectedFormData.gamewith}
|
||||
bind:value={formData.gamewith}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://..."
|
||||
|
|
@ -526,7 +535,7 @@
|
|||
/>
|
||||
<SuggestionDetailItem
|
||||
label="Kamigame"
|
||||
bind:value={selectedFormData.kamigame}
|
||||
bind:value={formData.kamigame}
|
||||
editable={true}
|
||||
type="text"
|
||||
placeholder="https://..."
|
||||
|
|
|
|||
Loading…
Reference in a new issue