"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { processPayment, markPaid } from "./actions"; import type { POStatus } from "@prisma/client"; interface Props { poId: string; poStatus: POStatus; totalAmount?: number; paidAmount?: number; } export function PaymentActions({ poId, poStatus, totalAmount = 0, paidAmount = 0 }: Props) { const router = useRouter(); const [ref, setRef] = useState(""); const [amount, setAmount] = useState(""); const [pending, setPending] = useState(false); const [error, setError] = useState(""); const remaining = totalAmount - paidAmount; async function handleProcessPayment() { setPending(true); setError(""); const result = await processPayment({ poId }); if ("error" in result) { setError(result.error); setPending(false); } else { router.refresh(); } } async function handleMarkPaid(e: React.FormEvent, forceFullPayment = false) { e.preventDefault(); if (!ref.trim()) { setError("Payment reference is required."); return; } const paymentAmount = forceFullPayment ? remaining : (parseFloat(amount) || undefined); if (paymentAmount !== undefined && paymentAmount <= 0) { setError("Payment amount must be greater than 0."); return; } if (paymentAmount !== undefined && paymentAmount > remaining) { setError(`Payment amount cannot exceed the remaining balance of ${remaining.toFixed(2)}.`); return; } setPending(true); setError(""); const result = await markPaid({ poId, paymentRef: ref, paymentAmount }); if ("error" in result) { setError(result.error); setPending(false); } else { router.refresh(); } } if (poStatus === "MGR_APPROVED") { return (
{error && {error}}
); } if ( poStatus === "SENT_FOR_PAYMENT" || poStatus === "PARTIALLY_PAID" || poStatus === "PARTIALLY_CLOSED" ) { const parsedAmount = parseFloat(amount); const isPartialPayment = !isNaN(parsedAmount) && parsedAmount > 0 && parsedAmount < remaining; return (
handleMarkPaid(e)} className="flex flex-col gap-2 w-full sm:w-auto" >
setRef(e.target.value)} className="flex-1 rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" /> setAmount(e.target.value)} min={0.01} max={remaining} step="0.01" className="w-full sm:w-36 rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" />
{error && {error}}
{isPartialPayment && ( )}
); } return null; }