mirror of
https://github.com/AventurasTeam/Aventuras.git
synced 2026-04-28 03:40:11 +00:00
feat(07-04): integrate RuntimeVariableDisplay into InventoryPanel and QuestPanel
- InventoryPanel: runtime vars in all 3 item sections (equipped, backpack, world) with display and edit modes for each - QuestPanel: runtime vars in both active and history beat sections - Both panels load definitions via database.getRuntimeVariablesByEntityType - All four entity panels now have identical runtime variable integration
This commit is contained in:
parent
7e111651d9
commit
08d9147a00
2 changed files with 229 additions and 0 deletions
|
|
@ -14,6 +14,7 @@
|
|||
X,
|
||||
} from 'lucide-svelte'
|
||||
import type { Item } from '$lib/types'
|
||||
import type { RuntimeVariable, RuntimeVarsMap } from '$lib/services/packs/types'
|
||||
import { Button } from '$lib/components/ui/button'
|
||||
import { Input } from '$lib/components/ui/input'
|
||||
import { Textarea } from '$lib/components/ui/textarea'
|
||||
|
|
@ -23,6 +24,8 @@
|
|||
import * as Select from '$lib/components/ui/select'
|
||||
import IconRow from '$lib/components/ui/icon-row.svelte'
|
||||
import { cn } from '$lib/utils/cn'
|
||||
import { database } from '$lib/services/database'
|
||||
import RuntimeVariableDisplay from './RuntimeVariableDisplay.svelte'
|
||||
|
||||
let showAddForm = $state(false)
|
||||
let newName = $state('')
|
||||
|
|
@ -36,6 +39,41 @@
|
|||
let droppingItemId = $state<string | null>(null)
|
||||
let dropLocationId = $state<string>('')
|
||||
|
||||
// Runtime variables
|
||||
let runtimeVarDefs = $state<RuntimeVariable[]>([])
|
||||
let editRuntimeVars = $state<RuntimeVarsMap>({})
|
||||
|
||||
$effect(() => {
|
||||
if (story.currentStory) {
|
||||
loadRuntimeVarDefs()
|
||||
}
|
||||
})
|
||||
|
||||
async function loadRuntimeVarDefs() {
|
||||
if (!story.currentStory) return
|
||||
try {
|
||||
const packId = await database.getStoryPackId(story.currentStory.id)
|
||||
if (packId) {
|
||||
runtimeVarDefs = await database.getRuntimeVariablesByEntityType(packId, 'item')
|
||||
} else {
|
||||
runtimeVarDefs = []
|
||||
}
|
||||
} catch {
|
||||
runtimeVarDefs = []
|
||||
}
|
||||
}
|
||||
|
||||
function updateEditRuntimeVar(
|
||||
defId: string,
|
||||
variableName: string,
|
||||
value: string | number | null,
|
||||
) {
|
||||
editRuntimeVars = {
|
||||
...editRuntimeVars,
|
||||
[defId]: { variableName, v: value },
|
||||
}
|
||||
}
|
||||
|
||||
const worldItems = $derived(story.items.filter((item) => item.location !== 'inventory'))
|
||||
|
||||
function toggleCollapse(itemId: string) {
|
||||
|
|
@ -60,6 +98,9 @@
|
|||
editEquipped = item.equipped
|
||||
// Reset other modes
|
||||
droppingItemId = null
|
||||
// Initialize runtime vars from entity metadata
|
||||
const rv = (item.metadata as Record<string, unknown> | null)?.runtimeVars
|
||||
editRuntimeVars = rv && typeof rv === 'object' ? { ...(rv as RuntimeVarsMap) } : {}
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
|
|
@ -68,6 +109,7 @@
|
|||
editDescription = ''
|
||||
editQuantity = 1
|
||||
editEquipped = false
|
||||
editRuntimeVars = {}
|
||||
}
|
||||
|
||||
async function saveEdit(item: Item) {
|
||||
|
|
@ -75,11 +117,26 @@
|
|||
if (!name) return
|
||||
|
||||
const quantity = Math.max(1, Number(editQuantity) || 1)
|
||||
|
||||
// Merge runtime vars into metadata
|
||||
const existingMeta = (item.metadata as Record<string, unknown>) ?? {}
|
||||
const hasRuntimeVarEdits = Object.keys(editRuntimeVars).length > 0
|
||||
const updatedMetadata = hasRuntimeVarEdits
|
||||
? {
|
||||
...existingMeta,
|
||||
runtimeVars: {
|
||||
...((existingMeta.runtimeVars as RuntimeVarsMap) ?? {}),
|
||||
...editRuntimeVars,
|
||||
},
|
||||
}
|
||||
: item.metadata
|
||||
|
||||
await story.updateItem(item.id, {
|
||||
name,
|
||||
description: editDescription.trim() || null,
|
||||
quantity,
|
||||
equipped: item.location === 'inventory' ? editEquipped : false,
|
||||
metadata: updatedMetadata,
|
||||
})
|
||||
|
||||
cancelEdit()
|
||||
|
|
@ -240,6 +297,20 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<!-- Runtime Variables (Edit - Equipped) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={editRuntimeVars}
|
||||
entityId={item.id}
|
||||
editMode={true}
|
||||
onValueChange={(defId, value) => {
|
||||
const def = runtimeVarDefs.find((d) => d.id === defId)
|
||||
if (def) updateEditRuntimeVar(defId, def.variableName, value)
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="border-border flex justify-end gap-2 border-t pt-2">
|
||||
<Button variant="text" size="sm" class="h-7 text-xs" onclick={cancelEdit}>
|
||||
Cancel
|
||||
|
|
@ -339,6 +410,15 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Runtime Variables (Display - Equipped) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={item.metadata?.runtimeVars as RuntimeVarsMap | undefined}
|
||||
entityId={item.id}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<!-- Footer Actions -->
|
||||
<div class="mt-2 flex items-center justify-between">
|
||||
<div class="-ml-1.5 flex items-center">
|
||||
|
|
@ -452,6 +532,20 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<!-- Runtime Variables (Edit - Backpack) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={editRuntimeVars}
|
||||
entityId={item.id}
|
||||
editMode={true}
|
||||
onValueChange={(defId, value) => {
|
||||
const def = runtimeVarDefs.find((d) => d.id === defId)
|
||||
if (def) updateEditRuntimeVar(defId, def.variableName, value)
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="border-border flex justify-end gap-2 border-t pt-2">
|
||||
<Button variant="text" size="sm" class="h-7 text-xs" onclick={cancelEdit}>
|
||||
Cancel
|
||||
|
|
@ -543,6 +637,15 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Runtime Variables (Display - Backpack) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={item.metadata?.runtimeVars as RuntimeVarsMap | undefined}
|
||||
entityId={item.id}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<!-- Footer Actions -->
|
||||
<div class="mt-2 flex items-center justify-between">
|
||||
<div class="-ml-1.5 flex items-center">
|
||||
|
|
@ -667,6 +770,20 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<!-- Runtime Variables (Edit - World) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={editRuntimeVars}
|
||||
entityId={item.id}
|
||||
editMode={true}
|
||||
onValueChange={(defId, value) => {
|
||||
const def = runtimeVarDefs.find((d) => d.id === defId)
|
||||
if (def) updateEditRuntimeVar(defId, def.variableName, value)
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="border-border flex justify-end gap-2 border-t pt-2">
|
||||
<Button variant="text" size="sm" class="h-7 text-xs" onclick={cancelEdit}>
|
||||
Cancel
|
||||
|
|
@ -766,6 +883,15 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Runtime Variables (Display - World) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={item.metadata?.runtimeVars as RuntimeVarsMap | undefined}
|
||||
entityId={item.id}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<!-- Footer Actions -->
|
||||
<div class="mt-2 flex items-center justify-between">
|
||||
<div class="-ml-1.5 flex items-center">
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
X,
|
||||
} from 'lucide-svelte'
|
||||
import type { StoryBeat } from '$lib/types'
|
||||
import type { RuntimeVariable, RuntimeVarsMap } from '$lib/services/packs/types'
|
||||
import { Button } from '$lib/components/ui/button'
|
||||
import { Input } from '$lib/components/ui/input'
|
||||
import { Textarea } from '$lib/components/ui/textarea'
|
||||
|
|
@ -21,6 +22,8 @@
|
|||
import * as Select from '$lib/components/ui/select'
|
||||
import IconRow from '$lib/components/ui/icon-row.svelte'
|
||||
import { cn } from '$lib/utils/cn'
|
||||
import { database } from '$lib/services/database'
|
||||
import RuntimeVariableDisplay from './RuntimeVariableDisplay.svelte'
|
||||
|
||||
let showAddForm = $state(false)
|
||||
let newTitle = $state('')
|
||||
|
|
@ -32,6 +35,41 @@
|
|||
let editType = $state<StoryBeat['type']>('quest')
|
||||
let editStatus = $state<StoryBeat['status']>('pending')
|
||||
|
||||
// Runtime variables
|
||||
let runtimeVarDefs = $state<RuntimeVariable[]>([])
|
||||
let editRuntimeVars = $state<RuntimeVarsMap>({})
|
||||
|
||||
$effect(() => {
|
||||
if (story.currentStory) {
|
||||
loadRuntimeVarDefs()
|
||||
}
|
||||
})
|
||||
|
||||
async function loadRuntimeVarDefs() {
|
||||
if (!story.currentStory) return
|
||||
try {
|
||||
const packId = await database.getStoryPackId(story.currentStory.id)
|
||||
if (packId) {
|
||||
runtimeVarDefs = await database.getRuntimeVariablesByEntityType(packId, 'story_beat')
|
||||
} else {
|
||||
runtimeVarDefs = []
|
||||
}
|
||||
} catch {
|
||||
runtimeVarDefs = []
|
||||
}
|
||||
}
|
||||
|
||||
function updateEditRuntimeVar(
|
||||
defId: string,
|
||||
variableName: string,
|
||||
value: string | number | null,
|
||||
) {
|
||||
editRuntimeVars = {
|
||||
...editRuntimeVars,
|
||||
[defId]: { variableName, v: value },
|
||||
}
|
||||
}
|
||||
|
||||
function toggleCollapse(beatId: string) {
|
||||
const isCollapsed = ui.isEntityCollapsed(beatId)
|
||||
ui.toggleEntityCollapsed(beatId, !isCollapsed)
|
||||
|
|
@ -52,6 +90,9 @@
|
|||
editDescription = beat.description ?? ''
|
||||
editType = beat.type
|
||||
editStatus = beat.status
|
||||
// Initialize runtime vars from entity metadata
|
||||
const rv = (beat.metadata as Record<string, unknown> | null)?.runtimeVars
|
||||
editRuntimeVars = rv && typeof rv === 'object' ? { ...(rv as RuntimeVarsMap) } : {}
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
|
|
@ -60,16 +101,32 @@
|
|||
editDescription = ''
|
||||
editType = 'quest'
|
||||
editStatus = 'pending'
|
||||
editRuntimeVars = {}
|
||||
}
|
||||
|
||||
async function saveEdit(beat: StoryBeat) {
|
||||
const title = editTitle.trim()
|
||||
if (!title) return
|
||||
|
||||
// Merge runtime vars into metadata
|
||||
const existingMeta = (beat.metadata as Record<string, unknown>) ?? {}
|
||||
const hasRuntimeVarEdits = Object.keys(editRuntimeVars).length > 0
|
||||
const updatedMetadata = hasRuntimeVarEdits
|
||||
? {
|
||||
...existingMeta,
|
||||
runtimeVars: {
|
||||
...((existingMeta.runtimeVars as RuntimeVarsMap) ?? {}),
|
||||
...editRuntimeVars,
|
||||
},
|
||||
}
|
||||
: beat.metadata
|
||||
|
||||
await story.updateStoryBeat(beat.id, {
|
||||
title,
|
||||
description: editDescription.trim() || null,
|
||||
type: editType,
|
||||
status: editStatus,
|
||||
metadata: updatedMetadata,
|
||||
})
|
||||
cancelEdit()
|
||||
}
|
||||
|
|
@ -267,6 +324,20 @@
|
|||
class="min-h-[60px] resize-none text-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Runtime Variables (Edit - Active) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={editRuntimeVars}
|
||||
entityId={beat.id}
|
||||
editMode={true}
|
||||
onValueChange={(defId, value) => {
|
||||
const def = runtimeVarDefs.find((d) => d.id === defId)
|
||||
if (def) updateEditRuntimeVar(defId, def.variableName, value)
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="border-border flex justify-end gap-2 border-t pt-2">
|
||||
|
|
@ -318,6 +389,15 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Runtime Variables (Display - Active) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={beat.metadata?.runtimeVars as RuntimeVarsMap | undefined}
|
||||
entityId={beat.id}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<!-- Footer Actions -->
|
||||
<div class="mt-2 flex items-center justify-between">
|
||||
<div class="-ml-1.5 flex items-center">
|
||||
|
|
@ -468,6 +548,20 @@
|
|||
class="min-h-[60px] resize-none text-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Runtime Variables (Edit - History) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={editRuntimeVars}
|
||||
entityId={beat.id}
|
||||
editMode={true}
|
||||
onValueChange={(defId, value) => {
|
||||
const def = runtimeVarDefs.find((d) => d.id === defId)
|
||||
if (def) updateEditRuntimeVar(defId, def.variableName, value)
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="border-border flex justify-end gap-2 border-t pt-2">
|
||||
|
|
@ -525,6 +619,15 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Runtime Variables (Display - History) -->
|
||||
{#if runtimeVarDefs.length > 0}
|
||||
<RuntimeVariableDisplay
|
||||
definitions={runtimeVarDefs}
|
||||
values={beat.metadata?.runtimeVars as RuntimeVarsMap | undefined}
|
||||
entityId={beat.id}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<!-- Footer Actions -->
|
||||
<div class="mt-2 flex items-center justify-between">
|
||||
<div class="-ml-1.5 flex items-center">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue