CUB-130: Build Add/Edit Filament form with backend endpoints for finishes and modifiers
All checks were successful
Dev Build / build-test (pull_request) Successful in 2m39s

This commit is contained in:
2026-05-10 14:13:29 -04:00
parent f1614029b5
commit fc564c6c5a
8 changed files with 587 additions and 4 deletions

View File

@@ -2,6 +2,7 @@ import { useState, useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import { Search, Filter, ChevronLeft, ChevronRight, Trash2, Pencil, Plus, AlertTriangle } from 'lucide-react'
import ColorSwatch from '../components/ColorSwatch'
import FilamentForm from '../components/FilamentForm'
import { fetchFilaments, deleteFilament } from '../services/filamentService'
import type { FilamentSpool, FilamentFilter } from '../types/filament'
@@ -19,6 +20,9 @@ export default function InventoryPage() {
const [sortDir, setSortDir] = useState<SortDir>('asc')
const [page, setPage] = useState(0)
const [deleteId, setDeleteId] = useState<number | null>(null)
const [formOpen, setFormOpen] = useState(false)
const [formMode, setFormMode] = useState<'create' | 'edit'>('create')
const [formInitial, setFormInitial] = useState<FilamentSpool | null>(null)
const filter: FilamentFilter = useMemo(() => ({
material: material || undefined,
@@ -79,7 +83,10 @@ export default function InventoryPage() {
<h2 className="text-xl font-bold text-slate-100">Filament Inventory</h2>
<p className="text-sm text-slate-400">{total} spool(s) total</p>
</div>
<button className="inline-flex items-center gap-2 rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-500 active:bg-emerald-700 transition-colors">
<button
onClick={() => { setFormMode('create'); setFormInitial(null); setFormOpen(true) }}
className="inline-flex items-center gap-2 rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-500 active:bg-emerald-700 transition-colors"
>
<Plus size={16} /> Add Spool
</button>
</div>
@@ -208,7 +215,11 @@ export default function InventoryPage() {
</td>
<td className="px-4 py-3 text-right">
<div className="flex items-center justify-end gap-2">
<button className="p-1.5 rounded hover:bg-slate-600 text-slate-400 hover:text-blue-400 transition-colors" title="Edit">
<button
onClick={() => { setFormMode('edit'); setFormInitial(spool); setFormOpen(true) }}
className="p-1.5 rounded hover:bg-slate-600 text-slate-400 hover:text-blue-400 transition-colors"
title="Edit"
>
<Pencil size={14} />
</button>
<button
@@ -263,7 +274,10 @@ export default function InventoryPage() {
</div>
<div className="flex items-center justify-end gap-2 pt-1">
<button className="flex items-center gap-1 rounded-md bg-slate-700 px-3 py-1.5 text-xs font-medium text-slate-200 hover:bg-slate-600">
<button
onClick={() => { setFormMode('edit'); setFormInitial(spool); setFormOpen(true) }}
className="flex items-center gap-1 rounded-md bg-slate-700 px-3 py-1.5 text-xs font-medium text-slate-200 hover:bg-slate-600"
>
<Pencil size={12} /> Edit
</button>
<button
@@ -304,6 +318,16 @@ export default function InventoryPage() {
</>
)}
{/* Add/Edit Form Modal */}
{formOpen && (
<FilamentForm
mode={formMode}
initialData={formInitial}
onClose={() => setFormOpen(false)}
onSuccess={() => refetch()}
/>
)}
{/* Delete confirmation modal */}
{deleteId !== null && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4">