"use client" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Textarea } from "@/components/ui/textarea" import { Label } from "@/components/ui/label" import ReactMarkdown from "react-markdown" import remarkGfm from "remark-gfm" import { ArrowLeft, CheckCircle2, Edit3, FileText, Paperclip, History, Download, Eye, GitCompare, Calendar, MapPin, Building2, Globe, ExternalLink, DollarSign, MessageSquare, AlertCircle, Copy, Loader2, Archive, RefreshCcw, } from "lucide-react" // Tipos interface TramiteData { id: string nombre: string formaJuridica: string organismos: string[] jurisdiccion: string ultimaInteraccion: string estado: "En proceso" | "Completado" | "Cancelado" createdAt: string deletedAt?: string | null documentacion: string requiereCertificaciones: boolean certificacionesDetalle: string pasoAPaso: string costos: Array<{ descripcion: string monto: string moneda: string observacion: string }> comentariosInternos: string linkGuia: string dondeSeRealiza: string comentarios?: Array<{ id: number contenido: string created_at: string usuario_id: number }> } interface Adjunto { id: string tipo: string titulo: string archivo: string tamaño: string fechaSubida: string url?: string } interface VersionHistorial { id: string versionNro: string tipoCambio: "confirmación" | "edición menor" | "renovación mayor" fecha: string autor: string } interface TramiteDetalleProps { tramiteId: string onConfirm?: () => void onEditMinor?: (data: any) => void onRenewMajor?: (data: any) => void onViewVersion?: (versionId: string) => void onCompareVersions?: (versionA: string, versionB: string) => void } const tipoCambioColors = { confirmación: "bg-green-500/10 text-green-500 border-green-500/20", "edición menor": "bg-blue-500/10 text-blue-500 border-blue-500/20", "renovación mayor": "bg-purple-500/10 text-purple-500 border-purple-500/20", creación: "bg-slate-500/10 text-slate-700 border-slate-500/20", } const getEstadoBadge = (estado: string) => { switch (estado) { case "En proceso": return "bg-blue-500/10 text-blue-500 border-blue-500/20" case "Completado": return "bg-gray-500/10 text-gray-400 border-gray-500/20" case "Cancelado": return "bg-red-500/10 text-red-500 border-red-500/20" default: return "bg-gray-500/10 text-gray-400 border-gray-500/20" } } export function TramiteDetalle({ tramiteId, onConfirm, onEditMinor, onRenewMajor, onViewVersion, onCompareVersions, }: TramiteDetalleProps) { const router = useRouter() const [tramite, setTramite] = useState(null) const [adjuntos, setAdjuntos] = useState([]) const [historial, setHistorial] = useState([]) const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState(null) // Estados para modales const [modalConfirmar, setModalConfirmar] = useState(false) const [modalArchivar, setModalArchivar] = useState(false) const [modalRestaurar, setModalRestaurar] = useState(false) const [comentarioConfirmacion, setComentarioConfirmacion] = useState("") useEffect(() => { const fetchTramite = async () => { try { const token = localStorage.getItem("token") if (!token) { throw new Error("No autenticado") } const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/tramites/${tramiteId}`, { cache: "no-store", headers: { Authorization: `Bearer ${token}`, Accept: "application/json", }, }) if (!response.ok) { throw new Error("Error al cargar el trámite") } const { data } = await response.json() // Map backend data to frontend interface const mappedTramite: TramiteData = { id: data.id.toString(), nombre: data.nombre, formaJuridica: data.formas_juridicas && data.formas_juridicas.length > 0 ? data.formas_juridicas.map((fj: any) => fj.nombre).join(", ") : data.forma_juridica?.nombre || "No especificada", organismos: (data.organismos || []).map((o: any) => o.nombre), jurisdiccion: data.jurisdiccion?.nombre || "No especificada", ultimaInteraccion: data.updated_at, estado: data.estado, createdAt: data.created_at, deletedAt: data.deleted_at, documentacion: data.documentacion || "", requiereCertificaciones: data.requiere_certificaciones_externas, certificacionesDetalle: data.certificaciones_detalle || "", pasoAPaso: data.paso_a_paso || "", costos: data.costos || [], comentariosInternos: data.comentarios_internos || "", linkGuia: data.link_guia_oficial || "", dondeSeRealiza: data.donde_se_realiza || "", comentarios: data.comentarios || [], } const mappedAdjuntos: Adjunto[] = (data.adjuntos || []).map((adj: any) => ({ id: adj.id.toString(), tipo: adj.tipo, titulo: adj.titulo || "Sin título", archivo: adj.ruta ? adj.ruta.split("/").pop() : "Archivo", tamaño: adj.tamano ? `${Math.round(adj.tamano / 1024)} KB` : "N/A", fechaSubida: adj.created_at, url: adj.url, // Ensure URL is passed if available })) const mappedHistorial: VersionHistorial[] = (data.versiones || []).map((ver: any) => ({ id: ver.id.toString(), versionNro: ver.version_nro || "1.0", // Assuming version number exists tipoCambio: ver.tipo_cambio || "edición menor", fecha: ver.created_at, autor: ver.autor || ver.user?.name || "Sistema", })) setTramite(mappedTramite) setAdjuntos(mappedAdjuntos) setHistorial(mappedHistorial) } catch (err) { console.error(err) setError("No se pudo cargar la información del trámite") } finally { setIsLoading(false) } } fetchTramite() }, [tramiteId]) // Handlers const handleConfirmar = async () => { try { const token = localStorage.getItem("token") if (!token) throw new Error("No autenticado") const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/tramites/${tramiteId}/confirmar`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, Accept: "application/json", }, body: JSON.stringify({ comentario: comentarioConfirmacion }), }) if (!response.ok) throw new Error("Error al confirmar el trámite") // Refresh data window.location.reload() } catch (err) { console.error(err) alert("Error al confirmar el trámite") } finally { setModalConfirmar(false) setComentarioConfirmacion("") } } const handleEditar = () => { router.push(`/tramite/${tramiteId}/editar`) } const handleDuplicar = () => { router.push(`/tramite/${tramiteId}/duplicar`) } const handleArchivar = async () => { try { const token = localStorage.getItem("token") if (!token) throw new Error("No autenticado") const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/tramites/${tramiteId}/archive`, { method: "POST", headers: { Authorization: `Bearer ${token}`, Accept: "application/json", }, }) if (!response.ok) throw new Error("Error al archivar el trámite") // Redirect to home router.push("/") } catch (err) { console.error(err) alert("Error al archivar el trámite") } finally { setModalArchivar(false) } } const handleRestaurar = async () => { try { const token = localStorage.getItem("token") if (!token) throw new Error("No autenticado") const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/tramites/${tramiteId}/restore`, { method: "POST", headers: { Authorization: `Bearer ${token}`, Accept: "application/json", }, }) if (!response.ok) throw new Error("Error al restaurar el trámite") // Refresh data window.location.reload() } catch (err) { console.error(err) alert("Error al restaurar el trámite") } finally { setModalRestaurar(false) } } if (isLoading) { return (
) } if (error || !tramite) { return (
{error || "No se encontró el trámite"}
) } return (
{/* Header */}
{/* Botón volver */} {/* Título y chips */}

{tramite.nombre}

{tramite.estado} {tramite.deletedAt && ( Archivado )}

{tramite.organismos.join(", ")} • {tramite.jurisdiccion}

{/* Acciones */}
{tramite.deletedAt ? ( ) : ( <> )}
{tramite.formaJuridica} {tramite.organismos.length > 0 ? tramite.organismos.join(", ") : "No especificado"} {tramite.jurisdiccion} Última interacción: {new Date(tramite.ultimaInteraccion).toLocaleDateString("es-AR")}
{/* Contenido con Tabs */}
Ficha Adjuntos Historial {/* Tab: Ficha */} {/* Información General */} Información General

{tramite.createdAt ? new Date(tramite.createdAt).toLocaleDateString("es-AR", { year: "numeric", month: "2-digit", day: "2-digit", }) : "No especificada"}

{tramite.dondeSeRealiza}

{tramite.linkGuia && (
{tramite.linkGuia}
)}
{/* Documentación y Requisitos */} Documentación y Requisitos
{tramite.documentacion}
{/* Certificaciones Externas */} {tramite.requiereCertificaciones && ( Certificaciones Externas Requeridas

{tramite.certificacionesDetalle}

)} {/* Paso a Paso */} Paso a Paso
{/* Costos */} {tramite.costos.length > 0 && ( Costos
{tramite.costos.map((costo, index) => (

{costo.descripcion}

{costo.observacion && (

{costo.observacion}

)}

{costo.moneda} ${Number(costo.monto).toLocaleString("es-AR")}

))}
)} {/* Comentarios Internos */} {tramite.comentariosInternos && ( Comentarios Internos

{tramite.comentariosInternos}

)} {/* Información de Actualización */} Información de Actualización

{new Date(tramite.ultimaInteraccion).toLocaleString("es-AR", { dateStyle: "long", timeStyle: "short", })}

{tramite.comentarios && tramite.comentarios.length > 0 && (

{tramite.comentarios[tramite.comentarios.length - 1].contenido}

{new Date(tramite.comentarios[tramite.comentarios.length - 1].created_at).toLocaleString( "es-AR", { dateStyle: "medium", timeStyle: "short", }, )}

)}
{/* Tab: Adjuntos */} Archivos Adjuntos Documentos y archivos relacionados con este trámite {adjuntos.length === 0 ? (

No hay archivos adjuntos

) : (
{adjuntos.map((adjunto) => (

{adjunto.titulo}

{adjunto.tipo} {adjunto.archivo} {adjunto.tamaño} Subido: {new Date(adjunto.fechaSubida).toLocaleDateString("es-AR")}
))}
)}
{/* Tab: Historial */} Historial de Versiones Timeline de cambios y actualizaciones del trámite
{/* Línea vertical del timeline */}
{historial.length === 0 ? (

No hay historial disponible

) : ( historial.map((version, index) => (
{/* Punto del timeline */}
{/* Contenido */}

Versión {version.versionNro}

{version.tipoCambio}
{new Date(version.fecha).toLocaleDateString("es-AR")} Por {version.autor}
{index !== 0 && ( )}
)) )}
{/* Modal: Confirmar */} Confirmar que el trámite sigue igual Esto creará una nueva versión de tipo "confirmación" indicando que la información sigue vigente.