"use client" import { useState, useEffect } 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 { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Calendar, MapPin, User, TrendingUp, Plus, Eye, Sprout, Droplets, Bug, ArrowLeft, Edit, Save, Search, } from "lucide-react" import Link from "next/link" import { useRouter, useSearchParams } from "next/navigation" import { PaginationControl } from "@/components/ui/pagination-control" interface Labor { id: string tipo: "Siembra" | "Monitoreo" | "Pulverización" | "Fertilización" fecha: string recetaId?: string observaciones: string responsable: string loteNombre?: string cultivo?: string productor?: string establecimiento?: string } import { apiFetch } from "@/lib/apiutils" import { toast } from "sonner" interface Campana { id: string nombre: string establecimiento: { id: string nombre: string hectareas: number productor: { id: string nombre: string } | null } cultivo: string anio: number fecha_inicio: string fecha_fin: string estado: "activa" | "finalizada" hectareas: number rinde_qq_ha?: number produccion_total?: number rinde_estimado?: number produccion_estimada?: number rinde_por_cultivo?: { cultivo: string superficie: number produccion: number rinde: number }[] labores_count: number } export default function DetalleCampanaPage() { const router = useRouter() const searchParams = useSearchParams() const id = searchParams.get("id") as string const establecimientoId = searchParams.get("establecimiento_id") const cultivoId = searchParams.get("cultivo_id") const backUrl = searchParams.get("back_url") const [campana, setCampana] = useState(null) const [labores, setLabores] = useState([]) const [loading, setLoading] = useState(true) const [uniqueCrops, setUniqueCrops] = useState("-") // Note: Manual Rinde editing is deprecated for grouped campaign displays, handled via real harvest recipes. const [isEditingStatus, setIsEditingStatus] = useState(false) const [statusTemp, setStatusTemp] = useState<"activa" | "finalizada">("activa") const [searchTerm, setSearchTerm] = useState("") // Pagination for Labores const [laboresPage, setLaboresPage] = useState(1) const [laboresTotal, setLaboresTotal] = useState(0) const [laboresLastPage, setLaboresLastPage] = useState(1) const fetchCampana = async () => { try { const query = establecimientoId ? `?establecimiento_id=${establecimientoId}` : "" const res = await apiFetch(`/campanas/${id}${query}`) if (res.ok) { const data = await res.json() setCampana(data) // Use the new dynamically calculated grouped stats when available // We utilize the campana fetch only for the campaign details/stats. // Labores will be fetched separately with pagination. } else { console.error("Failed to fetch campana", res.status, res.statusText) } } catch (e) { console.error(e) } } const fetchLabores = async () => { try { // Fetch recipes filtered by this campaign let url = `/recetas?campana_id=${id}&page=${laboresPage}&limit=10` if (searchTerm) url += `&search=${encodeURIComponent(searchTerm)}` const res = await apiFetch(url) if (res.ok) { const data = await res.json() const rawRecetas = data.data || [] const mappedLabores: Labor[] = rawRecetas.map((r: any) => ({ id: String(r.id), tipo: r.labor || "Aplicación", fecha: r.fecha, recetaId: String(r.id), observaciones: r.observaciones || "", responsable: r.ingeniero_responsable || "N/A", loteNombre: r.lotes?.map((l: any) => l.nombre).join(", ") || "N/A", cultivo: r.cultivo_rel?.nombre || r.cultivoRel?.nombre, productor: r.productor?.nombre || "N/A", establecimiento: r.establecimiento?.nombre || "N/A" })) setLabores(mappedLabores) setLaboresTotal(data.total) setLaboresLastPage(data.last_page) // Calculate unique crops from the recipes // Note: Ideally backend should give this, or we fallback to campana's list if available. // We aggregate from the fetched page? No, valid unique crops should summarize the WHOLE campaign. // Campana object from 'fetchCampana' might have 'cultivos_unicos' if we updated controller. // Let's rely on what we have or just show what's visible? // Existing logic used 'mappedLabores', but now we only have one page. // Let's use the 'cultivo' field from the campaign object itself if possible, or leave it simpler. // In CampanaController we added 'cultivos_unicos'. Let's check update there. // For now, let's just use what's in the page or wait for fetchCampana data. } } catch (e) { console.error(e) } } useEffect(() => { setLoading(true) Promise.all([fetchCampana(), fetchLabores()]).finally(() => setLoading(false)) }, [id, establecimientoId]) // Refetch labores when page changes useEffect(() => { fetchLabores() }, [laboresPage, searchTerm]) // Update Unique Crops when Campana loads (if controller provides it) useEffect(() => { if (campana && (campana as any).cultivos_unicos) { setUniqueCrops((campana as any).cultivos_unicos.join(", ")) } else if (campana?.cultivo) { setUniqueCrops(campana.cultivo) } }, [campana]) const handleNuevaReceta = () => { const params = new URLSearchParams() if (campana?.id) params.set("campana_id", campana.id) if (campana?.establecimiento?.id) params.set("establecimiento_id", campana.establecimiento.id) if (establecimientoId && !params.get("establecimiento_id")) params.set("establecimiento_id", establecimientoId) if (cultivoId) params.set("cultivo_id", cultivoId) if (backUrl) params.set("back_url", backUrl) // Forward the original back URL router.push(`/dashboard/recetas/nueva?${params.toString()}`) } const getStatusColor = (status: string) => { const colors = { activa: "bg-green-100 text-green-800 border-green-300", finalizada: "bg-gray-100 text-gray-800 border-gray-300", } return colors[status as keyof typeof colors] || colors.activa } const getTipoIcon = (tipo: string) => { const icons = { Siembra: , Monitoreo: , Pulverización: , Fertilización: , } return icons[tipo as keyof typeof icons] || } // API manual save functions removed since we compute yields from Cosecha recipes const handleGuardarStatus = async () => { try { const res = await apiFetch(`/campanas/${campana?.id}`, { method: "PUT", body: JSON.stringify({ estado: statusTemp }), }) if (res.ok) { const updated = await res.json() setCampana((prev) => (prev ? { ...prev, estado: updated.estado } : null)) setIsEditingStatus(false) toast.success("Estado actualizado exitosamente") } else { toast.error("Error al actualizar estado") } } catch (e) { console.error(e) toast.error("Error de conexión") } } if (loading) return
Cargando...
if (!campana) return
Campaña no encontrada
const backLink = backUrl || `/dashboard/campanas?establecimiento_id=${establecimientoId || ""}&cultivo_id=${cultivoId || ""}` return (

{campana.nombre}

Detalle de campaña y labores realizadas

Información General
Período: {new Date(campana.fecha_inicio).toLocaleDateString("es-AR")} -{" "} {new Date(campana.fecha_fin).toLocaleDateString("es-AR")}
Período: {new Date(campana.fecha_inicio).toLocaleDateString("es-AR")} -{" "} {new Date(campana.fecha_fin).toLocaleDateString("es-AR")}
{isEditingStatus ? (
) : (
{campana.estado === "activa" ? "Activa" : "Finalizada"}
)}
Rendimiento Estimado
Rendimientos calculados en base a recetas de "Cosecha"
{(!campana.rinde_por_cultivo || campana.rinde_por_cultivo.length === 0) ? (

Aún no se ha registrado ninguna labor de "Cosecha".

) : (
{campana.rinde_por_cultivo.map((stat, i) => (
{stat.cultivo} {stat.superficie} ha cosechadas

Rinde Promedio

{stat.rinde} QQ/ha

Producción

{stat.produccion} QQ totales

))}
)}
Labores Realizadas Historial de trabajos y recetas aplicadas en esta campaña
{ setSearchTerm(e.target.value) setLaboresPage(1) }} />
{labores.length === 0 ? (

No hay labores registradas

Comienza agregando la primera labor o receta para esta campaña

) : ( <>
Tipo de Labor Fecha Productor Establecimiento Lote Observaciones Responsable Acciones {labores.map((labor) => (
{getTipoIcon(labor.tipo)} {labor.tipo}
{new Date(labor.fecha).toLocaleDateString("es-AR")} {labor.productor} {labor.establecimiento} {labor.loteNombre} {labor.observaciones} {labor.responsable} {labor.recetaId ? ( ) : ( Sin receta )}
))}
)}
) }