move delete to detail pane overflow, add disabled save button to edit
This commit is contained in:
parent
db71e6dc80
commit
f5f7743055
2 changed files with 81 additions and 65 deletions
|
|
@ -10,6 +10,7 @@
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
import type { CollectionArtifact } from '$lib/types/api/artifact'
|
import type { CollectionArtifact } from '$lib/types/api/artifact'
|
||||||
import { isQuirkArtifact } from '$lib/types/api/artifact'
|
import { isQuirkArtifact } from '$lib/types/api/artifact'
|
||||||
|
import { useDeleteCollectionArtifact } from '$lib/api/mutations/artifact.mutations'
|
||||||
import { usePaneStack, type PaneConfig, type ElementType } from '$lib/stores/paneStack.svelte'
|
import { usePaneStack, type PaneConfig, type ElementType } from '$lib/stores/paneStack.svelte'
|
||||||
import { sidebar } from '$lib/stores/sidebar.svelte'
|
import { sidebar } from '$lib/stores/sidebar.svelte'
|
||||||
import { getArtifactImage } from '$lib/utils/images'
|
import { getArtifactImage } from '$lib/utils/images'
|
||||||
|
|
@ -30,6 +31,7 @@
|
||||||
let { artifact, isOwner = false, onClose }: Props = $props()
|
let { artifact, isOwner = false, onClose }: Props = $props()
|
||||||
|
|
||||||
const paneStack = usePaneStack()
|
const paneStack = usePaneStack()
|
||||||
|
const deleteMutation = useDeleteCollectionArtifact()
|
||||||
|
|
||||||
// Image and name
|
// Image and name
|
||||||
const imageUrl = $derived(getArtifactImage(artifact.artifact?.granblueId))
|
const imageUrl = $derived(getArtifactImage(artifact.artifact?.granblueId))
|
||||||
|
|
@ -68,22 +70,39 @@
|
||||||
title: 'Edit Artifact',
|
title: 'Edit Artifact',
|
||||||
component: CollectionArtifactEditPane,
|
component: CollectionArtifactEditPane,
|
||||||
props: {
|
props: {
|
||||||
artifact,
|
artifact
|
||||||
onClose
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paneStack.push(config)
|
paneStack.push(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the Edit action button in the pane header for owners
|
// Handle delete
|
||||||
|
function handleDelete() {
|
||||||
|
if (confirm('Are you sure you want to remove this artifact from your collection?')) {
|
||||||
|
deleteMutation.mutate(artifact.id, {
|
||||||
|
onSuccess: () => {
|
||||||
|
onClose?.()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the Edit action button and overflow menu for owners
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (isOwner) {
|
if (isOwner) {
|
||||||
sidebar.setAction(handleEdit, 'Edit', elementType)
|
sidebar.setAction(handleEdit, 'Edit', elementType)
|
||||||
|
sidebar.setOverflowMenu([
|
||||||
|
{
|
||||||
|
label: 'Remove from collection',
|
||||||
|
handler: handleDelete,
|
||||||
|
variant: 'danger'
|
||||||
|
}
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// Clean up action when component unmounts
|
|
||||||
sidebar.clearAction()
|
sidebar.clearAction()
|
||||||
|
sidebar.clearOverflowMenu()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -7,96 +7,93 @@
|
||||||
* Pushed onto pane stack from CollectionArtifactDetailPane.
|
* Pushed onto pane stack from CollectionArtifactDetailPane.
|
||||||
* Handles saving and deleting artifacts.
|
* Handles saving and deleting artifacts.
|
||||||
*/
|
*/
|
||||||
|
import { onMount, untrack } from 'svelte'
|
||||||
import type { CollectionArtifact } from '$lib/types/api/artifact'
|
import type { CollectionArtifact } from '$lib/types/api/artifact'
|
||||||
import { useUpdateCollectionArtifact, useDeleteCollectionArtifact } from '$lib/api/mutations/artifact.mutations'
|
import { useUpdateCollectionArtifact } from '$lib/api/mutations/artifact.mutations'
|
||||||
import { usePaneStack } from '$lib/stores/paneStack.svelte'
|
import { usePaneStack, type ElementType } from '$lib/stores/paneStack.svelte'
|
||||||
|
import { sidebar } from '$lib/stores/sidebar.svelte'
|
||||||
import ArtifactEditPane from '$lib/components/artifact/ArtifactEditPane.svelte'
|
import ArtifactEditPane from '$lib/components/artifact/ArtifactEditPane.svelte'
|
||||||
import Button from '$lib/components/ui/Button.svelte'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
artifact: CollectionArtifact
|
artifact: CollectionArtifact
|
||||||
onClose?: () => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let { artifact, onClose }: Props = $props()
|
let { artifact }: Props = $props()
|
||||||
|
|
||||||
const paneStack = usePaneStack()
|
const paneStack = usePaneStack()
|
||||||
|
|
||||||
// Mutations
|
// Mutations
|
||||||
const updateMutation = useUpdateCollectionArtifact()
|
const updateMutation = useUpdateCollectionArtifact()
|
||||||
const deleteMutation = useDeleteCollectionArtifact()
|
|
||||||
|
|
||||||
// Handle updates from ArtifactEditPane
|
// Track pending changes
|
||||||
|
let pendingUpdates = $state<Partial<CollectionArtifact> | null>(null)
|
||||||
|
let hasChanges = $derived(pendingUpdates !== null)
|
||||||
|
|
||||||
|
// Convert numeric element to ElementType string
|
||||||
|
const elementNames: Record<number, ElementType> = {
|
||||||
|
1: 'wind',
|
||||||
|
2: 'fire',
|
||||||
|
3: 'water',
|
||||||
|
4: 'earth',
|
||||||
|
5: 'dark',
|
||||||
|
6: 'light'
|
||||||
|
}
|
||||||
|
const elementType = $derived(elementNames[artifact.element] ?? undefined)
|
||||||
|
|
||||||
|
// Handle updates from ArtifactEditPane (store locally until save)
|
||||||
function handleUpdate(updates: Partial<CollectionArtifact>) {
|
function handleUpdate(updates: Partial<CollectionArtifact>) {
|
||||||
|
pendingUpdates = { ...pendingUpdates, ...updates }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle save
|
||||||
|
function handleSave() {
|
||||||
|
if (!pendingUpdates) return
|
||||||
|
|
||||||
updateMutation.mutate({
|
updateMutation.mutate({
|
||||||
id: artifact.id,
|
id: artifact.id,
|
||||||
input: {
|
input: {
|
||||||
element: updates.element,
|
element: pendingUpdates.element,
|
||||||
level: updates.level,
|
level: pendingUpdates.level,
|
||||||
proficiency: updates.proficiency,
|
proficiency: pendingUpdates.proficiency,
|
||||||
skill1: updates.skills?.[0] ?? undefined,
|
skill1: pendingUpdates.skills?.[0] ?? undefined,
|
||||||
skill2: updates.skills?.[1] ?? undefined,
|
skill2: pendingUpdates.skills?.[1] ?? undefined,
|
||||||
skill3: updates.skills?.[2] ?? undefined,
|
skill3: pendingUpdates.skills?.[2] ?? undefined,
|
||||||
skill4: updates.skills?.[3] ?? undefined
|
skill4: pendingUpdates.skills?.[3] ?? undefined
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
onSuccess: () => {
|
||||||
|
paneStack.pop()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle delete
|
// Set up header action (Save button always visible, disabled when no changes)
|
||||||
function handleDelete() {
|
function updateHeader() {
|
||||||
if (confirm('Are you sure you want to delete this artifact from your collection?')) {
|
const canSave = hasChanges && !updateMutation.isPending
|
||||||
deleteMutation.mutate(artifact.id, {
|
sidebar.setAction(canSave ? handleSave : undefined, 'Save', elementType)
|
||||||
onSuccess: () => {
|
|
||||||
onClose?.()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
updateHeader()
|
||||||
|
return () => sidebar.clearAction()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Reactively update header when state changes
|
||||||
|
$effect(() => {
|
||||||
|
const _ = [hasChanges, updateMutation.isPending]
|
||||||
|
untrack(() => updateHeader())
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="artifact-edit-pane">
|
<div class="artifact-edit-pane">
|
||||||
<!-- Edit pane content -->
|
<ArtifactEditPane
|
||||||
<div class="pane-content">
|
{artifact}
|
||||||
<ArtifactEditPane
|
onUpdate={handleUpdate}
|
||||||
{artifact}
|
/>
|
||||||
onUpdate={handleUpdate}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Actions footer -->
|
|
||||||
<div class="pane-footer">
|
|
||||||
<Button
|
|
||||||
variant="destructive"
|
|
||||||
size="small"
|
|
||||||
onclick={handleDelete}
|
|
||||||
disabled={deleteMutation.isPending}
|
|
||||||
>
|
|
||||||
{deleteMutation.isPending ? 'Deleting...' : 'Delete'}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@use '$src/themes/spacing' as *;
|
|
||||||
@use '$src/themes/typography' as *;
|
|
||||||
@use '$src/themes/layout' as *;
|
|
||||||
|
|
||||||
.artifact-edit-pane {
|
.artifact-edit-pane {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pane-content {
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pane-footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: $unit-2x;
|
|
||||||
border-top: 1px solid var(--border-secondary);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue