diff --git a/src/app/(app)/cotizaciones/[id]/RegistroHorasPanel.tsx b/src/app/(app)/cotizaciones/[id]/RegistroHorasPanel.tsx index 6550ac2..e84cfdf 100644 --- a/src/app/(app)/cotizaciones/[id]/RegistroHorasPanel.tsx +++ b/src/app/(app)/cotizaciones/[id]/RegistroHorasPanel.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useRef, useState } from "react"; -import { Clock, Plus, Trash2, Pencil, Printer, Eye, X, CheckCircle2, CircleDashed } from "lucide-react"; +import { Clock, Plus, Trash2, Pencil, Download, Eye, X, CheckCircle2, CircleDashed } from "lucide-react"; import { formatCurrency, formatFechaRegistro, @@ -97,6 +97,7 @@ export function RegistroHorasPanel({ const [from, setFrom] = useState(""); const [to, setTo] = useState(""); const [saving, setSaving] = useState(false); + const [descargando, setDescargando] = useState(false); const [togglingId, setTogglingId] = useState(null); const [error, setError] = useState(null); // HTML de la nota congelado al abrir la previsualización (null = modal cerrado). @@ -254,12 +255,35 @@ export function RegistroHorasPanel({ // Congela el HTML de la nota (con branding) y abre el modal de previsualización. const abrirPreview = () => setPreviewHtml(construirHTMLNota()); - // Imprime / guarda como PDF solo el contenido de la nota previsualizada. - const imprimirDesdePreview = () => { - const w = iframeRef.current?.contentWindow; - if (!w) return; - w.focus(); - w.print(); + // Descarga la nota como PDF generado en el SERVIDOR (pdfkit). A diferencia de imprimir + // el HTML desde el navegador, este PDF no lleva encabezados/pies del navegador (URL, + // fecha, no. de pagina). Respeta el filtro de estado, periodo y desglose actuales. + const descargarNotaPDF = async () => { + setDescargando(true); + try { + const res = await fetch(`/api/cotizaciones/${cotizacionId}/nota-horas`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ estado: estadoFiltro, modo, from, to }), + }); + if (!res.ok) { + alert("No se pudo generar el PDF"); + return; + } + const blob = await res.blob(); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `${TITULO_NOTA[estadoFiltro]} ${numero}.pdf`; + document.body.appendChild(a); + a.click(); + a.remove(); + setTimeout(() => URL.revokeObjectURL(url), 2000); + } catch { + alert("Error de conexion al generar el PDF"); + } finally { + setDescargando(false); + } }; const badgeEstado = (estadoPago: string) => { @@ -715,11 +739,12 @@ export function RegistroHorasPanel({

{TITULO_NOTA[estadoFiltro]} — {numero}