import { useEffect, useState } from 'react'; import { toast } from '@/lib/toast'; type Unidad = { id: number; etiqueta: string; estado: 'disponible' | 'prestado' | 'mantenimiento' | 'baja'; notas: string | null; created_at: string; }; const ESTADOS = ['disponible', 'mantenimiento', 'baja'] as const; export default function UnidadesManager({ materialId }: { materialId: number }) { const [unidades, setUnidades] = useState([]); const [loading, setLoading] = useState(true); const [nuevaEtiqueta, setNuevaEtiqueta] = useState(''); const [creando, setCreando] = useState(false); const load = async () => { setLoading(true); try { const res = await fetch(`/api/admin/materiales/${materialId}/unidades`); const j = await res.json(); if (!res.ok) throw new Error(j?.error ?? 'Error al cargar'); setUnidades(j.unidades ?? []); } catch (e) { toast({ kind: 'error', title: 'No se pudieron cargar las unidades', description: e instanceof Error ? e.message : '' }); } finally { setLoading(false); } }; useEffect(() => { load(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [materialId]); const crear = async (e: React.FormEvent) => { e.preventDefault(); const et = nuevaEtiqueta.trim(); if (!et || creando) return; setCreando(true); try { const res = await fetch(`/api/admin/materiales/${materialId}/unidades`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ etiqueta: et }), }); const j = await res.json(); if (!res.ok) throw new Error(j?.error ?? 'No se pudo crear'); setNuevaEtiqueta(''); await load(); toast({ kind: 'success', title: 'Unidad agregada', description: et }); } catch (e) { toast({ kind: 'error', title: 'No se pudo agregar', description: e instanceof Error ? e.message : '' }); } finally { setCreando(false); } }; const patch = async (u: Unidad, body: Partial>) => { const res = await fetch(`/api/admin/materiales/unidades/${u.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); const j = await res.json().catch(() => ({})); if (!res.ok) { toast({ kind: 'error', title: 'No se pudo actualizar', description: j?.error }); await load(); return; } setUnidades((prev) => prev.map((x) => (x.id === u.id ? { ...x, ...body } as Unidad : x))); }; const eliminar = async (u: Unidad) => { if (!confirm(`Eliminar unidad "${u.etiqueta}"?`)) return; const res = await fetch(`/api/admin/materiales/unidades/${u.id}`, { method: 'DELETE' }); const j = await res.json().catch(() => ({})); if (!res.ok) { toast({ kind: 'error', title: 'No se pudo eliminar', description: j?.error }); return; } setUnidades((prev) => prev.filter((x) => x.id !== u.id)); toast({ kind: 'success', title: 'Unidad eliminada' }); }; return (

Unidades individuales

setNuevaEtiqueta(e.target.value)} maxLength={80} />
{loading ? (

Cargando…

) : unidades.length === 0 ? (

Sin unidades registradas.

) : (
{unidades.map((u) => { const bloqueada = u.estado === 'prestado'; return ( ); })}
Etiqueta Estado Notas Acción
{ const v = e.target.value.trim(); if (v && v !== u.etiqueta) patch(u, { etiqueta: v }); else e.target.value = u.etiqueta; }} /> { const v = e.target.value; if ((u.notas ?? '') !== v) patch(u, { notas: v || null }); }} />
)}
); }