mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-07-07 06:36:30 +00:00
183 lines
5.1 KiB
TypeScript
183 lines
5.1 KiB
TypeScript
"use client";
|
|
import {
|
|
BadgeDollarSign,
|
|
Clipboard,
|
|
ClipboardCheck,
|
|
Loader2,
|
|
} from "lucide-react";
|
|
import { useActionState, useEffect, useState } from "react";
|
|
import { toast } from "sonner";
|
|
import { type VerifyTopupPaymentState, verifyTopupPayment } from "@/actions/payment";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCaption,
|
|
TableCell,
|
|
TableFooter,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import type { Topup } from "@/lib/backend-types";
|
|
import { Button } from "./ui/button";
|
|
|
|
|
|
|
|
const initialState: VerifyTopupPaymentState = {
|
|
message: "",
|
|
success: false,
|
|
fieldErrors: {},
|
|
};
|
|
export default function TopupToPay({ topup, disabled }: { topup?: Topup, disabled?: boolean }) {
|
|
const [state, formAction, isPending] = useActionState(verifyTopupPayment, initialState);
|
|
|
|
// Handle toast notifications based on state changes
|
|
useEffect(() => {
|
|
if (state.success && state.message) {
|
|
toast.success("Topup successful!", {
|
|
closeButton: true,
|
|
description: state.transaction
|
|
? `Your topup payment has been verified successfully using ${state.transaction.sourceBank} bank transfer on ${state.transaction.trxDate}.`
|
|
: state.message,
|
|
});
|
|
} else if (!state.success && state.message && state.message !== initialState.message) {
|
|
toast.error("Topup Payment Verification Failed", {
|
|
closeButton: true,
|
|
description: state.message,
|
|
});
|
|
}
|
|
}, [state]);
|
|
|
|
return (
|
|
<div className="w-full">
|
|
<div className="m-2 flex items-end justify-end p-2 text-sm text-foreground border rounded">
|
|
<Table>
|
|
<TableCaption>
|
|
<div className="max-w-sm mx-auto">
|
|
<p>Please send the following amount to the payment address</p>
|
|
<AccountInfomation
|
|
accName="Baraveli Dev"
|
|
accountNo="90101400028321000"
|
|
/>
|
|
{topup?.paid ? (
|
|
<Button
|
|
size={"lg"}
|
|
variant={"secondary"}
|
|
disabled
|
|
className="dark:text-green-200 text-green-900 bg-green-500/20 uppercase font-semibold"
|
|
>
|
|
Topup Payment Verified
|
|
</Button>
|
|
) : (
|
|
<div className="flex flex-col gap-2">
|
|
<form action={formAction}>
|
|
<input type="hidden" name="topupId" value={topup?.id ?? ""} />
|
|
<Button
|
|
disabled={disabled || isPending}
|
|
type="submit"
|
|
size={"lg"}
|
|
className="mb-4"
|
|
>
|
|
{isPending
|
|
? "Processing payment..."
|
|
: "I have paid"}
|
|
{isPending ? (
|
|
<Loader2 className="animate-spin" />
|
|
) : (
|
|
<BadgeDollarSign />
|
|
)}
|
|
</Button>
|
|
</form>
|
|
|
|
</div>
|
|
)}
|
|
</div>
|
|
</TableCaption>
|
|
<TableBody className="">
|
|
<TableRow>
|
|
<TableCell>Topup created</TableCell>
|
|
<TableCell className="text-right text-muted-foreground">
|
|
{new Date(topup?.created_at ?? "").toLocaleDateString("en-US", {
|
|
month: "short",
|
|
day: "2-digit",
|
|
year: "numeric",
|
|
minute: "2-digit",
|
|
hour: "2-digit",
|
|
second: "2-digit",
|
|
})}
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell>Payment received</TableCell>
|
|
<TableCell className="text-right text-sarLinkOrange">
|
|
{topup?.paid_at
|
|
? new Date(topup.paid_at).toLocaleDateString("en-US", {
|
|
month: "short",
|
|
day: "2-digit",
|
|
year: "numeric",
|
|
minute: "2-digit",
|
|
hour: "2-digit",
|
|
second: "2-digit",
|
|
})
|
|
: "-"}
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell>MIB Reference</TableCell>
|
|
<TableCell className="text-right">
|
|
{topup?.mib_reference ? topup.mib_reference : "-"}
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
<TableFooter>
|
|
<TableRow className="">
|
|
<TableCell colSpan={1}>Total Due</TableCell>
|
|
<TableCell className="text-right text-3xl font-bold">
|
|
{topup?.amount?.toFixed(2)}
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableFooter>
|
|
</Table>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function AccountInfomation({
|
|
accountNo,
|
|
accName,
|
|
}: {
|
|
accountNo: string;
|
|
accName: string;
|
|
}) {
|
|
const [accNo, setAccNo] = useState(false);
|
|
return (
|
|
<div className="justify-start items-start border my-4 flex flex-col gap-2 p-2 rounded-md">
|
|
<h6 className="title-bg uppercase p-2 border rounded w-full font-semibold">
|
|
Account Information
|
|
</h6>
|
|
<div className="border justify-start flex flex-col items-start bg-white/10 w-full p-2 rounded">
|
|
<div className="text-sm font-semibold">Account Name</div>
|
|
<span>{accName}</span>
|
|
</div>
|
|
<div className="border flex justify-between items-start gap-2 bg-white/10 w-full p-2 rounded">
|
|
<div className="flex flex-col items-start justify-start">
|
|
<p className="text-sm font-semibold">Account No</p>
|
|
<span>{accountNo}</span>
|
|
</div>
|
|
<Button
|
|
onClick={() => {
|
|
setTimeout(() => {
|
|
setAccNo(true);
|
|
navigator.clipboard.writeText(accountNo);
|
|
}, 2000);
|
|
toast.success("Account number copied!");
|
|
setAccNo((prev) => !prev);
|
|
}}
|
|
variant={"link"}
|
|
>
|
|
{accNo ? <Clipboard /> : <ClipboardCheck color="green" />}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|