import { type FormEvent, useEffect, useState } from 'react' import { Link, useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom' import { ApiHttpError } from '../../api/http' import { fetchInventoryCreateForm, fetchInventoryItem, postInventoryItem, putInventoryItem, } from '../../api/inventory' import { catLabelBook, gradeLabel, parseClassesSelection } from './inventoryHelpers' import { INVENTORY_BOOK_BASE } from './inventoryPaths' /** CI `inventory/book/form.php` */ export function InventoryBookFormPage() { const { itemId } = useParams() const { pathname } = useLocation() const navigate = useNavigate() const [searchParams] = useSearchParams() const isCreate = pathname.endsWith('/create') const [categories, setCategories] = useState[]>([]) const [name, setName] = useState('') const [categoryId, setCategoryId] = useState('') const [classes, setClasses] = useState([]) const [author, setAuthor] = useState('') const [isbn, setIsbn] = useState('') const [edition, setEdition] = useState('') const [quantity, setQuantity] = useState('0') const [unit, setUnit] = useState('') const [sku, setSku] = useState('') const [description, setDescription] = useState('') const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [error, setError] = useState(null) useEffect(() => { let c = false setLoading(true) const run = isCreate ? fetchInventoryCreateForm('book', searchParams) : fetchInventoryItem(itemId ?? '') run .then((data) => { if (c) return if (data && typeof data === 'object') { const o = data as Record const cats = Array.isArray(o.categories) ? (o.categories as Record[]) : [] setCategories(cats) const item = (o.item ?? o) as Record if (!isCreate && item && typeof item === 'object') { setName(String(item.name ?? '')) setCategoryId(item.category_id != null ? String(item.category_id) : '') setClasses(parseClassesSelection(item)) setAuthor(String(item.author ?? '')) setIsbn(String(item.isbn ?? '')) setEdition(String(item.edition ?? '')) setQuantity(String(item.quantity ?? 0)) setUnit(String(item.unit ?? '')) setSku(String(item.sku ?? '')) setDescription(String(item.description ?? '')) } } setError(null) }) .catch((e: unknown) => { if (!c) setError(e instanceof ApiHttpError ? e.message : 'Unable to load form.') }) .finally(() => { if (!c) setLoading(false) }) return () => { c = true } }, [isCreate, itemId, searchParams]) const selectedCat = categories.find((x) => String(x.id) === categoryId) const gradeRangeText = gradeLabel(selectedCat ?? null) function toggleClass(n: number) { setClasses((prev) => prev.includes(n) ? prev.filter((x) => x !== n) : [...prev, n].sort((a, b) => a - b), ) } async function onSubmit(e: FormEvent) { e.preventDefault() setSaving(true) setError(null) const body: Record = { type: 'book', name, category_id: categoryId === '' ? null : Number(categoryId), classes, author: author || undefined, isbn: isbn || undefined, edition: edition || undefined, quantity: quantity === '' ? 0 : Number(quantity), unit: unit || undefined, sku: sku || undefined, description: description || undefined, } try { if (isCreate) await postInventoryItem(body) else await putInventoryItem(itemId ?? '', body) navigate(INVENTORY_BOOK_BASE) } catch (err: unknown) { setError(err instanceof ApiHttpError ? err.message : 'Save failed.') } finally { setSaving(false) } } return (

{isCreate ? 'Add' : 'Edit'} Book

{error ?
{error}
: null} {loading ?

Loading…

: null} {!loading ? (
void onSubmit(ev)}>
setName(e.target.value)} />
Grade Range: {gradeRangeText}
{Array.from({ length: 13 }, (_, i) => i + 1).map((n) => (
toggleClass(n)} />
))}
Choose all class numbers that use this book.
setAuthor(e.target.value)} />
setIsbn(e.target.value)} />
setEdition(e.target.value)} />
setQuantity(e.target.value)} />
setUnit(e.target.value)} />
setSku(e.target.value)} />