From f5f774305574b853cf56e6f37a89c981204ea5c5 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 3 Dec 2025 18:20:13 -0800 Subject: [PATCH] move delete to detail pane overflow, add disabled save button to edit --- .../CollectionArtifactDetailPane.svelte | 27 +++- .../CollectionArtifactEditPane.svelte | 119 +++++++++--------- 2 files changed, 81 insertions(+), 65 deletions(-) diff --git a/src/lib/components/collection/CollectionArtifactDetailPane.svelte b/src/lib/components/collection/CollectionArtifactDetailPane.svelte index 1fb45d2e..bde4eac5 100644 --- a/src/lib/components/collection/CollectionArtifactDetailPane.svelte +++ b/src/lib/components/collection/CollectionArtifactDetailPane.svelte @@ -10,6 +10,7 @@ import { onMount } from 'svelte' import type { CollectionArtifact } 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 { sidebar } from '$lib/stores/sidebar.svelte' import { getArtifactImage } from '$lib/utils/images' @@ -30,6 +31,7 @@ let { artifact, isOwner = false, onClose }: Props = $props() const paneStack = usePaneStack() + const deleteMutation = useDeleteCollectionArtifact() // Image and name const imageUrl = $derived(getArtifactImage(artifact.artifact?.granblueId)) @@ -68,22 +70,39 @@ title: 'Edit Artifact', component: CollectionArtifactEditPane, props: { - artifact, - onClose + artifact } } 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(() => { if (isOwner) { sidebar.setAction(handleEdit, 'Edit', elementType) + sidebar.setOverflowMenu([ + { + label: 'Remove from collection', + handler: handleDelete, + variant: 'danger' + } + ]) } return () => { - // Clean up action when component unmounts sidebar.clearAction() + sidebar.clearOverflowMenu() } }) diff --git a/src/lib/components/collection/CollectionArtifactEditPane.svelte b/src/lib/components/collection/CollectionArtifactEditPane.svelte index de30e1eb..b951fb40 100644 --- a/src/lib/components/collection/CollectionArtifactEditPane.svelte +++ b/src/lib/components/collection/CollectionArtifactEditPane.svelte @@ -7,96 +7,93 @@ * Pushed onto pane stack from CollectionArtifactDetailPane. * Handles saving and deleting artifacts. */ + import { onMount, untrack } from 'svelte' import type { CollectionArtifact } from '$lib/types/api/artifact' - import { useUpdateCollectionArtifact, useDeleteCollectionArtifact } from '$lib/api/mutations/artifact.mutations' - import { usePaneStack } from '$lib/stores/paneStack.svelte' + import { useUpdateCollectionArtifact } from '$lib/api/mutations/artifact.mutations' + 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 Button from '$lib/components/ui/Button.svelte' interface Props { artifact: CollectionArtifact - onClose?: () => void } - let { artifact, onClose }: Props = $props() + let { artifact }: Props = $props() const paneStack = usePaneStack() // Mutations const updateMutation = useUpdateCollectionArtifact() - const deleteMutation = useDeleteCollectionArtifact() - // Handle updates from ArtifactEditPane + // Track pending changes + let pendingUpdates = $state | null>(null) + let hasChanges = $derived(pendingUpdates !== null) + + // Convert numeric element to ElementType string + const elementNames: Record = { + 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) { + pendingUpdates = { ...pendingUpdates, ...updates } + } + + // Handle save + function handleSave() { + if (!pendingUpdates) return + updateMutation.mutate({ id: artifact.id, input: { - element: updates.element, - level: updates.level, - proficiency: updates.proficiency, - skill1: updates.skills?.[0] ?? undefined, - skill2: updates.skills?.[1] ?? undefined, - skill3: updates.skills?.[2] ?? undefined, - skill4: updates.skills?.[3] ?? undefined + element: pendingUpdates.element, + level: pendingUpdates.level, + proficiency: pendingUpdates.proficiency, + skill1: pendingUpdates.skills?.[0] ?? undefined, + skill2: pendingUpdates.skills?.[1] ?? undefined, + skill3: pendingUpdates.skills?.[2] ?? undefined, + skill4: pendingUpdates.skills?.[3] ?? undefined + } + }, { + onSuccess: () => { + paneStack.pop() } }) } - // Handle delete - function handleDelete() { - if (confirm('Are you sure you want to delete this artifact from your collection?')) { - deleteMutation.mutate(artifact.id, { - onSuccess: () => { - onClose?.() - } - }) - } + // Set up header action (Save button always visible, disabled when no changes) + function updateHeader() { + const canSave = hasChanges && !updateMutation.isPending + sidebar.setAction(canSave ? handleSave : undefined, 'Save', elementType) } + + onMount(() => { + updateHeader() + return () => sidebar.clearAction() + }) + + // Reactively update header when state changes + $effect(() => { + const _ = [hasChanges, updateMutation.isPending] + untrack(() => updateHeader()) + })
- -
- -
- - - +