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
All checks were successful
Dev Build / build-test (pull_request) Successful in 2m39s
This commit is contained in:
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user