import { useEffect, useState } from "react" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Badge } from "@/components/ui/badge" import { Label } from "@/components/ui/label" import { Button } from "@/components/ui/button" import * as Icons from "lucide-react" import type { RefRow } from "@/types/RefRow" // POST -> recibe blob PDF y (opcional) Content-Disposition async function fetchPdfBlob(url: string, body: { documentos_id: string }) { const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }) if (!res.ok) throw new Error(await res.text()) const blob = await res.blob() return { blob, disposition: res.headers.get("content-disposition") ?? undefined } } function filenameFromDisposition(disposition?: string, fallback = "archivo.pdf") { if (!disposition) return fallback const star = /filename\*\=UTF-8''([^;]+)/i.exec(disposition)?.[1] if (star) return decodeURIComponent(star) const simple = /filename\=\"?([^\";]+)\"?/i.exec(disposition)?.[1] return simple ?? fallback } export function DetailDialog({ row, onClose, pdfUrl = "/api/get/documento", // ← permite inyectar el endpoint }: { row: RefRow | null onClose: () => void pdfUrl?: string }) { console.log("DetailDialog render", { row }) const [viewerUrl, setViewerUrl] = useState(null) const [currentBlob, setCurrentBlob] = useState(null) const [filename, setFilename] = useState("archivo.pdf") const open = !!row useEffect(() => { if (!open) return let revoked = false let urlToRevoke: string | null = null const ctrl = new AbortController() async function load() { console.log(row) if (!row?.documentos_id) { setViewerUrl(null) setCurrentBlob(null) console.warn("No hay documentos_id en el row") return } try { const { blob, disposition } = await fetchPdfBlob(`${import.meta.env.VITE_BACK_ORIGIN}/api/get/documento`, { documentos_id: row.documentos_id }) if (ctrl.signal.aborted) return const name = row.titulo_archivo ? `${row.titulo_archivo}.pdf` : filenameFromDisposition(disposition) setFilename(name) const url = URL.createObjectURL(blob) urlToRevoke = url if (!revoked) { setViewerUrl(url) setCurrentBlob(blob) } } catch (e) { console.error("Carga de PDF falló:", e) setViewerUrl(null) setCurrentBlob(null) } } load() return () => { revoked = true ctrl.abort() if (urlToRevoke) URL.revokeObjectURL(urlToRevoke) } }, [open, row?.s3_file_path, row?.titulo_archivo, pdfUrl]) async function downloadFile() { try { // Si ya tenemos el blob, úsalo if (currentBlob) { const link = document.createElement("a") const href = URL.createObjectURL(currentBlob) link.href = href link.download = filename link.click() URL.revokeObjectURL(href) return } // Si no, vuelve a pedirlo (p. ej., si el user abre y descarga sin render previo) if (!row?.documentos_id) throw new Error("No hay contenido para descargar.") const { blob, disposition } = await fetchPdfBlob(`${import.meta.env.VITE_BACK_ORIGIN}/api/get/documento`, { documentos_id: row.documentos_id }) const name = row.titulo_archivo ? `${row.titulo_archivo}.pdf` : filenameFromDisposition(disposition) const link = document.createElement("a") const href = URL.createObjectURL(blob) link.href = href link.download = name link.click() URL.revokeObjectURL(href) } catch (error) { console.error("Error al descargar el archivo:", error) alert("No se pudo descargar el archivo.") } } return ( !o && onClose()}> {row?.titulo_archivo ?? "(Sin título)"} {row?.descripcion || "Sin descripción"} {row && (
{row.tipo_contenido ?? "—"} {row.interno ? "Interno" : "Externo"} {row.procesado ? "Procesado" : "Pendiente"} {row.fuente_autoridad && {row.fuente_autoridad}} {row.fecha_subida && ( {new Date(row.fecha_subida).toLocaleString()} )}
{/* Tags {row.tags?.length ? (
Tags: {row.tags.join(", ")}
) : null} */}
{row.instrucciones || "—"}
{viewerUrl ? (