import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { formatDateToHumanReadable } from "@/utils/dateUtils"; import React, { useState } from "react"; import { paymentStatusOptions, PaymentWithExtras } from "@repo/db/types"; import { PaymentStatus, PaymentMethod } from "@repo/db/types"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@radix-ui/react-select"; import { Input } from "@/components/ui/input"; import Decimal from "decimal.js"; import { toast } from "@/hooks/use-toast"; type PaymentEditModalProps = { isOpen: boolean; onOpenChange: (open: boolean) => void; onClose: () => void; onEditServiceLine: (updatedPayment: PaymentWithExtras) => void; payment: PaymentWithExtras | null; }; export default function PaymentEditModal({ isOpen, onOpenChange, onClose, payment, onEditServiceLine, }: PaymentEditModalProps) { if (!payment) return null; const [expandedLineId, setExpandedLineId] = useState(null); const [updatedPaidAmounts, setUpdatedPaidAmounts] = useState< Record >({}); const [updatedAdjustedAmounts, setUpdatedAdjustedAmounts] = useState< Record >({}); const [updatedNotes, setUpdatedNotes] = useState>({}); const [updatedPaymentStatus, setUpdatedPaymentStatus] = useState(payment?.status ?? "PENDING"); const [updatedTransactions, setUpdatedTransactions] = useState( () => payment?.transactions ?? [] ); type DraftPaymentData = { paidAmount: number; adjustedAmount?: number; notes?: string; paymentStatus?: PaymentStatus; payerName?: string; method: PaymentMethod; receivedDate: string; }; const [serviceLineDrafts, setServiceLineDrafts] = useState>({}); const totalPaid = payment.transactions.reduce( (sum, tx) => sum + tx.serviceLinePayments.reduce((s, sp) => s + Number(sp.paidAmount), 0), 0 ); const totalBilled = payment.claim.serviceLines.reduce( (sum, line) => sum + line.billedAmount, 0 ); const totalDue = totalBilled - totalPaid; const handleEditServiceLine = (lineId: number) => { setExpandedLineId(lineId === expandedLineId ? null : lineId); }; const handleFieldChange = (lineId: number, field: string, value: any) => { setServiceLineDrafts((prev) => ({ ...prev, [lineId]: { ...prev[lineId], [field]: value, }, })); }; // const handleSavePayment = (lineId: number) => { // const newPaidAmount = updatedPaidAmounts[lineId]; // const newAdjustedAmount = updatedAdjustedAmounts[lineId] ?? 0; // const newNotes = updatedNotes[lineId] ?? ""; // if (newPaidAmount == null || isNaN(newPaidAmount)) return; // const updatedTxs = updatedTransactions.map((tx) => ({ // ...tx, // serviceLinePayments: tx.serviceLinePayments.map((sp) => // sp.serviceLineId === lineId // ? { // ...sp, // paidAmount: new Decimal(newPaidAmount), // adjustedAmount: new Decimal(newAdjustedAmount), // notes: newNotes, // } // : sp // ), // })); // const updatedPayment: PaymentWithExtras = { // ...payment, // transactions: updatedTxs, // status: updatedPaymentStatus, // }; // setUpdatedTransactions(updatedTxs); // onEditServiceLine(updatedPayment); // setExpandedLineId(null); // }; const handleSavePayment = async (lineId: number) => { const data = serviceLineDrafts[lineId]; if (!data || !data.paidAmount || !data.method || !data.receivedDate) { console.log("please fill al") return; } const transactionPayload = { paymentId: payment.id, amount: data.paidAmount + (data.adjustedAmount ?? 0), method: data.method, payerName: data.payerName, notes: data.notes, receivedDate: new Date(data.receivedDate), serviceLinePayments: [ { serviceLineId: lineId, paidAmount: data.paidAmount, adjustedAmount: data.adjustedAmount ?? 0, notes: data.notes, }, ], }; try { await onEditServiceLine(transactionPayload); setExpandedLineId(null); onClose(); } catch (err) { console.log(err) } }; const renderInput = (label: string, type: string, lineId: number, field: string, step?: string) => (
handleFieldChange(lineId, field, type === "number" ? parseFloat(e.target.value) : e.target.value) } />
); return ( Edit Payment View and manage payments applied to service lines.
{/* Claim + Patient Info */}

{payment.claim.patientName}

Claim ID: {payment.claimId.toString().padStart(4, "0")}

Service Date:{" "} {formatDateToHumanReadable(payment.claim.serviceDate)}

{/* Payment Summary */}

Payment Info

Total Billed: $ {totalBilled.toFixed(2)}

Total Paid: $ {totalPaid.toFixed(2)}

Total Due: $ {totalDue.toFixed(2)}

Metadata

Received Date:{" "} {payment.receivedDate ? formatDateToHumanReadable(payment.receivedDate) : "N/A"}

Method:{" "} {payment.paymentMethod ?? "N/A"}

Notes:{" "} {payment.notes || "N/A"}

{/* Service Lines Payments */}

Service Lines

{payment.claim.serviceLines.length > 0 ? ( <> {payment.claim.serviceLines.map((line) => { const linePayments = payment.transactions.flatMap((tx) => tx.serviceLinePayments.filter( (sp) => sp.serviceLineId === line.id ) ); const paidAmount = linePayments.reduce( (sum, sp) => sum + Number(sp.paidAmount), 0 ); const adjusted = linePayments.reduce( (sum, sp) => sum + Number(sp.adjustedAmount), 0 ); const due = line.billedAmount - paidAmount; return (

Procedure Code:{" "} {line.procedureCode}

Billed: $ {line.billedAmount.toFixed(2)}

Paid: $ {paidAmount.toFixed(2)}

Adjusted: $ {adjusted.toFixed(2)}

Due: $ {due.toFixed(2)}

{expandedLineId === line.id && (
setUpdatedPaidAmounts({ ...updatedPaidAmounts, [line.id]: parseFloat(e.target.value), }) } />
setUpdatedAdjustedAmounts({ ...updatedAdjustedAmounts, [line.id]: parseFloat(e.target.value), }) } />
setUpdatedNotes({ ...updatedNotes, [line.id]: e.target.value, }) } />
)}
); })} ) : (

No service lines available.

)}
{/* Transactions Overview */}

All Transactions

{payment.transactions.length > 0 ? ( payment.transactions.map((tx) => (

Date:{" "} {formatDateToHumanReadable(tx.receivedDate)}

Amount: $ {Number(tx.amount).toFixed(2)}

Method: {tx.method}

{tx.serviceLinePayments.map((sp) => (

• Applied ${Number(sp.paidAmount).toFixed(2)} to service line ID {sp.serviceLineId}

))}
)) ) : (

No transactions recorded.

)}
{/* Actions */}
); }