"use client"; import { RiBarcodeFill, RiCheckboxCircleFill, RiCheckboxCircleLine, RiLoader4Line, RiMoneyDollarCircleLine, } from "@remixicon/react"; import { useRouter } from "next/navigation"; import { useEffect, useMemo, useState, useTransition } from "react"; import { toast } from "sonner"; import { toggleLancamentoSettlementAction } from "@/app/(dashboard)/lancamentos/actions"; import { EstabelecimentoLogo } from "@/components/lancamentos/shared/estabelecimento-logo"; import MoneyValues from "@/components/money-values"; import { Button } from "@/components/ui/button"; import { CardContent } from "@/components/ui/card"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter as ModalFooter, } from "@/components/ui/dialog"; import type { DashboardBoleto } from "@/lib/dashboard/boletos"; import { cn } from "@/lib/utils/ui"; import { Badge } from "../ui/badge"; import { WidgetEmptyState } from "../widget-empty-state"; type BoletosWidgetProps = { boletos: DashboardBoleto[]; }; type ModalState = "idle" | "processing" | "success"; const DATE_FORMATTER = new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "short", year: "numeric", timeZone: "UTC", }); const buildDateLabel = (value: string | null, prefix?: string) => { if (!value) { return null; } const [year, month, day] = value.split("-").map((part) => Number(part)); if (!year || !month || !day) { return null; } const formatted = DATE_FORMATTER.format( new Date(Date.UTC(year, month - 1, day)), ); return prefix ? `${prefix} ${formatted}` : formatted; }; const buildStatusLabel = (boleto: DashboardBoleto) => { if (boleto.isSettled) { return buildDateLabel(boleto.boletoPaymentDate, "Pago em"); } return buildDateLabel(boleto.dueDate, "Vence em"); }; const getTodayDateString = () => { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, "0"); const day = String(now.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; }; export function BoletosWidget({ boletos }: BoletosWidgetProps) { const router = useRouter(); const [items, setItems] = useState(boletos); const [selectedId, setSelectedId] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [modalState, setModalState] = useState("idle"); const [isPending, startTransition] = useTransition(); useEffect(() => { setItems(boletos); }, [boletos]); const selectedBoleto = useMemo( () => items.find((boleto) => boleto.id === selectedId) ?? null, [items, selectedId], ); const isProcessing = modalState === "processing" || isPending; const selectedBoletoDueLabel = selectedBoleto ? buildDateLabel(selectedBoleto.dueDate, "Vencimento:") : null; const handleOpenModal = (boletoId: string) => { setSelectedId(boletoId); setModalState("idle"); setIsModalOpen(true); }; const resetModalState = () => { setIsModalOpen(false); setSelectedId(null); setModalState("idle"); }; const handleConfirmPayment = () => { if (!selectedBoleto || selectedBoleto.isSettled || isProcessing) { return; } setModalState("processing"); startTransition(async () => { const result = await toggleLancamentoSettlementAction({ id: selectedBoleto.id, value: true, }); if (!result.success) { toast.error(result.error); setModalState("idle"); return; } setItems((previous) => previous.map((boleto) => boleto.id === selectedBoleto.id ? { ...boleto, isSettled: true, boletoPaymentDate: getTodayDateString(), } : boleto, ), ); toast.success(result.message); router.refresh(); setModalState("success"); }); }; const getStatusBadgeVariant = (status: string): "success" | "info" => { const normalizedStatus = status.toLowerCase(); if (normalizedStatus === "pendente") { return "info"; } return "success"; }; return ( <> {items.length === 0 ? ( } title="Nenhum boleto cadastrado para o período selecionado" description="Cadastre boletos para monitorar os pagamentos aqui." /> ) : (
    {items.map((boleto) => { const statusLabel = buildStatusLabel(boleto); const isOverdue = (() => { if (boleto.isSettled || !boleto.dueDate) return false; const [y, m, d] = boleto.dueDate.split("-").map(Number); if (!y || !m || !d) return false; return new Date(Date.UTC(y, m - 1, d)) < new Date(); })(); return (
  • {boleto.name}
    {statusLabel}
  • ); })}
)}
{ if (!open) { if (isProcessing) { return; } resetModalState(); return; } setIsModalOpen(true); }} > { if (isProcessing) { event.preventDefault(); return; } resetModalState(); }} onPointerDownOutside={(event) => { if (isProcessing) { event.preventDefault(); } }} > {modalState === "success" ? (
Pagamento registrado! Atualizamos o status do boleto para pago. Em instantes ele aparecerá como baixado no histórico.
) : ( <> Confirmar pagamento do boleto Confirme os dados para registrar o pagamento. Você poderá editar o lançamento depois, se necessário. {selectedBoleto ? (

Boleto

{selectedBoleto.name}

{selectedBoletoDueLabel ? (

{selectedBoletoDueLabel}

) : null}
Valor do Boleto
Status
{selectedBoleto.isSettled ? "Pago" : "Pendente"}
) : null} )}
); }