"use client" import { useState } from "react" import { DashboardLayout } from "@/components/dashboard-layout" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Plus, Pencil, Search, Package, Power } from "lucide-react" import { Badge } from "@/components/ui/badge" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" interface Insumo { id: string nombreComercial: string principioActivo: string unidadMedida: string categoria: string categoriaId?: string } import { apiFetch, getErrorMessage } from "@/lib/apiutils" import { useEffect } from "react" import { PaginationControl } from "@/components/ui/pagination-control" // ... imports import { useApi } from "@/lib/use-api" import { toast } from "sonner" interface CategoriaInsumo { id: string nombre: string } export default function InsumosPage() { /* State */ const [searchTerm, setSearchTerm] = useState("") const [currentPage, setCurrentPage] = useState(1) useEffect(() => { setCurrentPage(1) }, [searchTerm]) /* API */ const queryParams = new URLSearchParams() queryParams.append("page", currentPage.toString()) if (searchTerm.trim() !== "") { queryParams.append("search", searchTerm) } const { data: rawData, isLoading, mutate } = useApi(`/insumos?${queryParams.toString()}`) // Fetch categories independently const { data: categoriesData, mutate: mutateCategories } = useApi("/categoria-insumos") const dataList = rawData?.data || [] const lastPage = rawData?.last_page || 1 const total = rawData?.total || 0 const insumos: Insumo[] = dataList.map((i: any) => ({ id: i.id.toString(), nombreComercial: i.nombre_comercial, principioActivo: i.principio_activo, unidadMedida: i.unidad_medida, categoria: i.categoria?.nombre || "Sin Categoría", // Handle relation categoriaId: i.categoria_id?.toString() || "" })) const categorias: CategoriaInsumo[] = (categoriesData || []).map((c: any) => ({ id: c.id.toString(), nombre: c.nombre })).sort((a: CategoriaInsumo, b: CategoriaInsumo) => { const countA = rawData?.stats?.by_category?.[a.nombre] || 0 const countB = rawData?.stats?.by_category?.[b.nombre] || 0 return countB - countA }) const [isDialogOpen, setIsDialogOpen] = useState(false) const [editingInsumo, setEditingInsumo] = useState(null) const [formData, setFormData] = useState & { categoriaId: string }>({ nombreComercial: "", principioActivo: "", unidadMedida: "", categoriaId: "", }) // Helper for duplicate key fix const unidades = ["Litros", "Kilogramos", "Gramos", "Mililitros"] // State for new category dialog const [isCatDialogOpen, setIsCatDialogOpen] = useState(false) const [newCatName, setNewCatName] = useState("") const handleCreateCategory = async () => { if (!newCatName) return try { const res = await apiFetch("/categoria-insumos", { method: "POST", body: JSON.stringify({ nombre: newCatName }) }) if (res.ok) { await mutateCategories() setNewCatName("") setIsCatDialogOpen(false) } else { const msg = await getErrorMessage(res) toast.error(msg) } } catch (e) { console.error(e) } } const filteredInsumos = insumos const handleOpenDialog = (insumo?: Insumo) => { if (insumo) { setEditingInsumo(insumo) // eslint-disable-next-line @typescript-eslint/no-unused-vars const { id, categoria, ...insumoData } = insumo setFormData({ ...insumoData, categoriaId: insumoData.categoriaId || "", }) } else { setEditingInsumo(null) setFormData({ nombreComercial: "", principioActivo: "", unidadMedida: "", categoriaId: "", }) } setIsDialogOpen(true) } const handleSave = async () => { try { const payload = { nombre_comercial: formData.nombreComercial, principio_activo: formData.principioActivo, unidad_medida: formData.unidadMedida, categoria_id: formData.categoriaId } let res; if (editingInsumo) { res = await apiFetch(`/insumos/${editingInsumo.id}`, { method: 'PUT', body: JSON.stringify(payload) }) } else { res = await apiFetch('/insumos', { method: 'POST', body: JSON.stringify(payload) }) } if (res.ok) { mutate() // Revalidate setIsDialogOpen(false) } else { const msg = await getErrorMessage(res) toast.error(msg) } } catch (e) { console.error(e) toast.error("Error de conexión") } } const getCategoriaColor = (categoria: string) => { // Dynamic mapping not possible with hardcoded tailwind classes unless we use a hash or predefined list // Fallback to gray for now or keep existing mapping if names match const colors: Record = { Herbicida: "bg-green-100 text-green-800 border-green-300", Insecticida: "bg-blue-100 text-blue-800 border-blue-300", Fungicida: "bg-purple-100 text-purple-800 border-purple-300", Fertilizante: "bg-amber-100 text-amber-800 border-amber-300", Acaricida: "bg-red-100 text-red-800 border-red-300", Coadyuvante: "bg-gray-100 text-gray-800 border-gray-300", } return colors[categoria] || "bg-gray-100 text-gray-800 border-gray-300" } return (

Gestión de Insumos

Administra el catálogo de insumos agrícolas

Nueva Categoría Agrega una nueva categoría de insumos.
setNewCatName(e.target.value)} placeholder="Ej: Nutriente" />
{editingInsumo ? "Editar Insumo" : "Nuevo Insumo"} {editingInsumo ? "Modifica la información del insumo" : "Completa los datos para registrar un nuevo insumo"}
{ if (e.target.value.length <= 100) { setFormData({ ...formData, nombreComercial: e.target.value }) } }} maxLength={100} placeholder="Glifosato 48%" className={formData.nombreComercial.length >= 100 ? 'border-red-500 focus-visible:ring-red-500' : ''} /> {formData.nombreComercial.length >= 100 && (

Has alcanzado el límite máximo de 100 caracteres.

)}
{ if (e.target.value.length <= 100) { setFormData({ ...formData, principioActivo: e.target.value }) } }} maxLength={100} placeholder="Glifosato" className={formData.principioActivo.length >= 100 ? 'border-red-500 focus-visible:ring-red-500' : ''} /> {formData.principioActivo.length >= 100 && (

Has alcanzado el límite máximo de 100 caracteres.

)}
Total Insumos {isLoading ? (
) : (
{rawData?.stats?.total || 0}
)}

En catálogo

{categorias.map((cat) => (
{cat.nombre}s {isLoading ? (
) : (
{rawData?.stats?.by_category?.[cat.nombre] || 0}
)}

Productos

))}
Catálogo de Insumos Todos los productos agrícolas disponibles
setSearchTerm(e.target.value)} className="pl-10" />
Producto Principio Activo Categoría Unidad Acciones {isLoading && insumos.length === 0 ? ( Cargando insumos... ) : filteredInsumos.length === 0 ? ( No se encontraron insumos ) : ( filteredInsumos.map((insumo) => (
{insumo.nombreComercial}
{insumo.principioActivo} {insumo.categoria} {insumo.unidadMedida}
)) )}
) }