[Feature] Copy filament (#1246)

This commit is contained in:
Miguel Ángel López Vicente
2026-05-09 09:40:21 +02:00
committed by GitHub
parent 30fe88a334
commit 6a130c09d7
18 changed files with 479 additions and 118 deletions
+16 -7
View File
@@ -21,10 +21,13 @@ type TabId = 'filament' | 'pa-profile';
const CLEAR_TAG_PAYLOAD = { tag_uid: null, tray_uuid: null, tag_type: null, data_origin: null };
export type SpoolFormMode = 'create' | 'edit' | 'copy';
interface SpoolFormModalProps {
isOpen: boolean;
onClose: () => void;
spool?: InventorySpool | null;
mode: SpoolFormMode;
printersWithCalibrations?: PrinterWithCalibrations[];
currencySymbol: string;
onSpoolsCreated?: (spools: InventorySpool[]) => void;
@@ -38,6 +41,7 @@ export function SpoolFormModal({
isOpen,
onClose,
spool,
mode,
printersWithCalibrations = [],
currencySymbol,
onSpoolsCreated,
@@ -48,7 +52,8 @@ export function SpoolFormModal({
const queryClient = useQueryClient();
const { showToast } = useToast();
const isEditing = !!spool;
const isEditing = mode === 'edit';
const isCopying = mode === 'copy';
// Form state
const [formData, setFormData] = useState<SpoolFormData>(defaultFormData);
@@ -305,7 +310,7 @@ export function SpoolFormModal({
label_weight: spool.label_weight || 1000,
core_weight: spool.core_weight || 250,
core_weight_catalog_id: spool.core_weight_catalog_id ?? null,
weight_used: spool.weight_used || 0,
weight_used: isCopying ? 0 : spool.weight_used || 0,
slicer_filament: spool.slicer_filament || '',
note: spool.note || '',
cost_per_kg: spool.cost_per_kg ?? null,
@@ -340,7 +345,7 @@ export function SpoolFormModal({
setWeightTouched(false);
setStorageLocationTouched(false);
}
}, [isOpen, spool]);
}, [isOpen, spool, mode, isCopying]);
// Expand all printers in PA profile section when calibrations are available
useEffect(() => {
@@ -704,7 +709,7 @@ export function SpoolFormModal({
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-bambu-dark-tertiary flex-shrink-0">
<h2 className="text-lg font-semibold text-white">
{isEditing ? t('inventory.editSpool') : t('inventory.addSpool')}
{isEditing ? t('inventory.editSpool') : isCopying ? t('inventory.copySpool') : t('inventory.addSpool')}
</h2>
<button
onClick={onClose}
@@ -714,8 +719,12 @@ export function SpoolFormModal({
</button>
</div>
{/* Quick Add toggle — only in create mode */}
{!isEditing && (
{/* Quick Add toggle — only in create mode (not edit, not copy).
In copy mode the modal title is the singular "Copy Spool", so the
quantity-driven bulkCreateMutation path would silently produce N
copies under a misleading title — keep this toggle out of that
mode entirely. */}
{mode === 'create' && (
<div className="flex items-center justify-between px-4 py-2 border-b border-bambu-dark-tertiary flex-shrink-0">
<div className="flex items-center gap-2">
<Zap className="w-4 h-4 text-amber-400" />
@@ -904,7 +913,7 @@ export function SpoolFormModal({
) : (
<>
<Save className="w-4 h-4" />
{isEditing ? t('common.save') : t('inventory.addSpool')}
{isEditing ? t('common.save') : isCopying ? t('inventory.copySpool') : t('inventory.addSpool')}
</>
)}
</Button>