Add Unassign button to edit spool modal

Allows removing a spool's AMS slot assignment directly from the
  edit modal, clearing the location column in the inventory table.
This commit is contained in:
maziggy
2026-03-25 14:14:40 +01:00
parent 91320e76d3
commit c52ff1dcee
5 changed files with 124 additions and 90 deletions
+44 -12
View File
@@ -1,7 +1,7 @@
import { useState, useEffect, useMemo } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { X, Loader2, Save, Beaker, Palette, Zap, Tag } from 'lucide-react';
import { X, Loader2, Save, Beaker, Palette, Zap, Tag, Unlink } from 'lucide-react';
import { api } from '../api/client';
import type { InventorySpool, SlicerSetting, SpoolCatalogEntry, LocalPreset } from '../api/client';
import { Button } from './Button';
@@ -383,6 +383,29 @@ export function SpoolFormModal({
},
});
// Fetch assignment for this spool (to show Unassign button)
const { data: assignments } = useQuery({
queryKey: ['spool-assignments'],
queryFn: () => api.getAssignments(),
enabled: isOpen && isEditing,
});
const spoolAssignment = spool ? assignments?.find(a => a.spool_id === spool.id) : undefined;
const unassignMutation = useMutation({
mutationFn: () => {
if (!spoolAssignment) throw new Error('No assignment');
return api.unassignSpool(spoolAssignment.printer_id, spoolAssignment.ams_id, spoolAssignment.tray_id);
},
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: ['spool-assignments'] });
showToast(t('inventory.unassignSuccess', 'Spool unassigned'), 'success');
onClose();
},
onError: (error: Error) => {
showToast(error.message, 'error');
},
});
// Save K-profiles for selected calibrations
const saveKProfiles = async (spoolId: number) => {
if (selectedProfiles.size === 0) {
@@ -487,7 +510,7 @@ export function SpoolFormModal({
}
};
const isPending = createMutation.isPending || bulkCreateMutation.isPending || updateMutation.isPending || deleteTagMutation.isPending;
const isPending = createMutation.isPending || bulkCreateMutation.isPending || updateMutation.isPending || deleteTagMutation.isPending || unassignMutation.isPending;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
@@ -646,15 +669,24 @@ export function SpoolFormModal({
{/* Footer */}
<div className="flex gap-2 p-4 border-t border-bambu-dark-tertiary flex-shrink-0">
{isEditing && (
<Button
variant="secondary"
onClick={() => deleteTagMutation.mutate()}
disabled={isPending || !spool?.tag_uid}
className="mr-auto"
>
<Tag className="w-4 h-4" />
{t('inventory.deleteTag', 'Delete Tag')}
</Button>
<div className="flex gap-2 mr-auto">
<Button
variant="secondary"
onClick={() => deleteTagMutation.mutate()}
disabled={isPending || !spool?.tag_uid}
>
<Tag className="w-4 h-4" />
{t('inventory.deleteTag', 'Delete Tag')}
</Button>
<Button
variant="secondary"
onClick={() => unassignMutation.mutate()}
disabled={isPending || !spoolAssignment}
>
<Unlink className="w-4 h-4" />
{t('inventory.unassignSpool', 'Unassign')}
</Button>
</div>
)}
<div className="flex gap-2 ml-auto">
<Button variant="secondary" onClick={onClose}>