"use client" import { useState, useEffect } from "react" import { useAuth } from "@/lib/auth-context" import { apiFetch, getErrorMessage } from "@/lib/apiutils" import { toast } from "sonner" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { format } from "date-fns" import { es } from "date-fns/locale" import { ClipboardList, Trash2, Pencil, Plus, MapPin, Calendar, Ruler, Search } from "lucide-react" import { PaginationControl } from "@/components/ui/pagination-control" import { DashboardLayout } from "@/components/dashboard-layout" import { Badge } from "@/components/ui/badge" interface Establecimiento { id: number nombre: string } interface Lote { id: number nombre: string establecimiento_id: number } interface Visita { id: number establecimiento_id: number lote_id: number | null fecha: string estado_general: string | null altura_plantas_cm: number | null color_cultivo: string | null nivel_maleza: string | null nivel_plagas_enfermedades: string | null observaciones: string | null establecimiento?: Establecimiento lote?: Lote } export default function VisitasPage() { const { user } = useAuth() const [mounted, setMounted] = useState(false) // Data const [establecimientos, setEstablecimientos] = useState([]) const [lotes, setLotes] = useState([]) const [visitas, setVisitas] = useState([]) // Filters and Pagination const [selectedEstablecimiento, setSelectedEstablecimiento] = useState("all") const [selectedEstado, setSelectedEstado] = useState("all") const [selectedMaleza, setSelectedMaleza] = useState("all") const [currentPage, setCurrentPage] = useState(1) const [loading, setLoading] = useState(false) // Modal Form State const [isDialogOpen, setIsDialogOpen] = useState(false) const [editingId, setEditingId] = useState(null) const [fecha, setFecha] = useState(format(new Date(), "yyyy-MM-dd")) const [establecimientoId, setEstablecimientoId] = useState("") const [loteId, setLoteId] = useState("none") const [estadoGeneral, setEstadoGeneral] = useState("Bueno") const [alturaPlantas, setAlturaPlantas] = useState("") const [colorCultivo, setColorCultivo] = useState("Verde Intenso") const [nivelMaleza, setNivelMaleza] = useState("Nulo") const [nivelPlagas, setNivelPlagas] = useState("Nulo") const [observaciones, setObservaciones] = useState("") const [isSubmitting, setIsSubmitting] = useState(false) const itemsPerPage = 10 useEffect(() => { setMounted(true) fetchEstablecimientos() fetchVisitas() }, []) useEffect(() => { if (mounted) { fetchVisitas() } }, [selectedEstablecimiento, selectedEstado, selectedMaleza]) useEffect(() => { if (establecimientoId) { fetchLotes(establecimientoId) } else { setLotes([]) } }, [establecimientoId]) const fetchEstablecimientos = async () => { try { const response = await apiFetch("/establecimientos?all=1") if (response.ok) { const responseData = await response.json() const data = responseData.data || responseData setEstablecimientos(data) } } catch (error) { console.error("Error fetching establecimientos", error) } } const fetchLotes = async (estId: string) => { try { const response = await apiFetch(`/lotes?establecimiento_id=${estId}&all=1`) if (response.ok) { const responseData = await response.json() const data = responseData.data || responseData setLotes(data) } } catch (error) { console.error("Error fetching lotes", error) } } const fetchVisitas = async () => { setLoading(true) try { let url = "/visitas?" const params = new URLSearchParams() if (selectedEstablecimiento !== "all") params.append('establecimiento_id', selectedEstablecimiento) if (selectedEstado !== "all") params.append('estado_general', selectedEstado) if (selectedMaleza !== "all") params.append('nivel_maleza', selectedMaleza) url += params.toString() const response = await apiFetch(url) if (response.ok) { const data = await response.json() setVisitas(data) setCurrentPage(1) } } catch (error) { console.error("Error fetching visitas", error) } finally { setLoading(false) } } const handleOpenDialog = (v?: Visita) => { if (v) { setEditingId(v.id) setFecha(v.fecha.substring(0, 10)) setEstablecimientoId(v.establecimiento_id.toString()) setLoteId(v.lote_id ? v.lote_id.toString() : "none") setEstadoGeneral(v.estado_general || "Bueno") setAlturaPlantas(v.altura_plantas_cm?.toString() || "") setColorCultivo(v.color_cultivo || "Verde Intenso") setNivelMaleza(v.nivel_maleza || "Nulo") setNivelPlagas(v.nivel_plagas_enfermedades || "Nulo") setObservaciones(v.observaciones || "") } else { setEditingId(null) setFecha(format(new Date(), "yyyy-MM-dd")) setObservaciones("") setAlturaPlantas("") setEstadoGeneral("Bueno") setColorCultivo("Verde Intenso") setNivelMaleza("Nulo") setNivelPlagas("Nulo") if (establecimientos.length > 0) { setEstablecimientoId(establecimientos[0].id.toString()) } else { setEstablecimientoId("") } setLoteId("none") } setIsDialogOpen(true) } const handleSubmit = async () => { if (!establecimientoId || !fecha) { toast.error("Complete los campos obligatorios (Establecimiento y Fecha)") return } setIsSubmitting(true) try { const method = editingId ? "PUT" : "POST" const url = editingId ? `/visitas/${editingId}` : "/visitas" const response = await apiFetch(url, { method, body: JSON.stringify({ establecimiento_id: establecimientoId, lote_id: loteId === "none" ? null : loteId, fecha, estado_general: estadoGeneral, altura_plantas_cm: alturaPlantas ? parseFloat(alturaPlantas) : null, color_cultivo: colorCultivo, nivel_maleza: nivelMaleza, nivel_plagas_enfermedades: nivelPlagas, observaciones }), }) if (response.ok) { toast.success(`Visita ${editingId ? 'actualizada' : 'registrada'} correctamente`) setIsDialogOpen(false) fetchVisitas() } else { const error = await getErrorMessage(response) toast.error(error) } } catch (error) { toast.error("Error de red al procesar") } finally { setIsSubmitting(false) } } const handleDelete = async (id: number) => { if (!confirm("¿Está seguro de eliminar este registro de visita?")) return try { const response = await apiFetch(`/visitas/${id}`, { method: "DELETE", }) if (response.ok) { toast.success("Registro eliminado") fetchVisitas() } else { const error = await getErrorMessage(response) toast.error(error) } } catch (error) { toast.error("Error al eliminar") } } if (!mounted) return null // Pagination logic const totalPages = Math.ceil(visitas.length / itemsPerPage) const paginatedVisitas = visitas.slice( (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage ) const getStatusBadge = (status: string | null) => { switch (status) { case "Excelente": return {status} case "Bueno": return {status} case "Regular": return {status} case "Malo": return {status} default: return {status || "N/A"} } } return (

Visitas y Observaciones

Seguimiento detallado del estado de los cultivos y lotes

{editingId ? "Editar Visita" : "Nueva Visita de Campo"} Complete la información observada durante la recorrida
{/* Sección 1: Ubicación */}

Ubicación

{/* Sección 2: Datos de la visita */}

Datos de la Visita

setFecha(e.target.value)} disabled={isSubmitting} />
{ const val = e.target.value; const sanitized = val.replace(',', '.'); if (sanitized === '' || /^\d*\.?\d*$/.test(sanitized)) { setAlturaPlantas(sanitized); } }} disabled={isSubmitting} />
{/* Sección 3: Estado del cultivo */}

Estado del Cultivo

{/* Sección 4: Observaciones */}

Observaciones