From 63b14fc8b8ba9c817969d6437431c62b55329840 Mon Sep 17 00:00:00 2001 From: urieljareth Date: Sat, 11 Jul 2026 11:31:18 -0600 Subject: [PATCH] Registro de horas: accion explicita para regresar una partida pagada a "Por pagar" El badge de estado deja de ser un toggle (facil de disparar por error) y pasa a ser un indicador. En su lugar, la columna de acciones muestra un boton claro segun el estado: "Marcar como pagada" (pendientes) o "Regresar a Por pagar" (pagadas, con confirmacion). Asi se corrigen los casos donde una partida se marca como pagada por error. El backend ya limpiaba la fechaPago al regresar a por_pagar; solo cambia la UX del panel. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../cotizaciones/[id]/RegistroHorasPanel.tsx | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/app/(app)/cotizaciones/[id]/RegistroHorasPanel.tsx b/src/app/(app)/cotizaciones/[id]/RegistroHorasPanel.tsx index d8481c7..1409d0b 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, Download, Eye, X, CheckCircle2, CircleDashed } from "lucide-react"; +import { Clock, Plus, Trash2, Pencil, Download, Eye, X, CheckCircle2, CircleDashed, RotateCcw } from "lucide-react"; import { formatCurrency, formatFechaRegistro, @@ -230,9 +230,10 @@ export function RegistroHorasPanel({ } }; - // Alterna el estado de cobro de una partida (por_pagar <-> pagada). Optimista. - const handleToggleEstado = async (r: Registro) => { - const nuevo = esPagada(r.estadoPago) ? "por_pagar" : "pagada"; + // Cambia el estado de cobro de una partida a un valor explícito. Optimista. + // Al regresar a "por_pagar" el backend limpia la fechaPago (deja de contar como cobrada). + const cambiarEstado = async (r: Registro, nuevo: "por_pagar" | "pagada") => { + if (esPagada(r.estadoPago) === (nuevo === "pagada")) return; // ya está en ese estado const prev = registros; setTogglingId(r.id); setRegistros((rs) => rs.map((x) => (x.id === r.id ? { ...x, estadoPago: nuevo } : x))); @@ -252,6 +253,13 @@ export function RegistroHorasPanel({ } }; + // Regresa una partida pagada por error a "Por pagar". Pide confirmación porque se + // pierde la marca/fecha de pago y la partida vuelve a entrar en la nota por cobrar. + const regresarPorPagar = (r: Registro) => { + if (!confirm('¿Regresar esta partida a "Por pagar"? Se quitará la marca de pagada.')) return; + cambiarEstado(r, "por_pagar"); + }; + // Congela el HTML de la nota (con branding) y abre el modal de previsualización. const abrirPreview = () => setPreviewHtml(construirHTMLNota()); @@ -658,17 +666,27 @@ export function RegistroHorasPanel({ {formatCurrency(r.tarifaHora)} {formatCurrency(r.horas * r.tarifaHora)} {r.descripcion} - - - + {badgeEstado(r.estadoPago)} + {esPagada(r.estadoPago) ? ( + + ) : ( + + )}