"use client"; import React, { useEffect, useState } from "react"; import { Center, Group, Loader, Paper, ScrollArea, Table, Text, Title, TextInput, Button, Modal } from "@mantine/core"; import { notifications } from "@mantine/notifications"; import { useRouter } from "next/navigation"; import Image from "next/image"; import { getBankLogo } from "@/app/_util/getBankLogo"; import { IconRefresh, IconTrash } from "@tabler/icons-react"; import { sendOtp, verifyOtp } from "@/app/_util/otp"; interface Beneficiary { accountNo: string; name: string; accountType: string; ifscCode: string; bankName: string; branchName: string; } export default function ViewBeneficiary() { const router = useRouter(); const [authorized, setAuthorized] = useState(null); const [beneficiaries, setBeneficiaries] = useState([]); const [loading, setLoading] = useState(true); const [opened, setOpened] = useState(false); const [otpStep, setOtpStep] = useState(false); const [otp, setOtp] = useState(""); const [selectedAccount, setSelectedAccount] = useState(null); const [countdown, setCountdown] = useState(180); const [timerActive, setTimerActive] = useState(false); const maskAccount = (account: string) => { if (!account) return undefined; const length = account.length; if (length <= 4) return account; const masked = "X".repeat(length - 4) + account.slice(length - 4); return masked; }; async function handleSendOtp() { const mobileNumber = localStorage.getItem('remitter_mobile_no'); if (!mobileNumber) { notifications.show({ title: 'Error', message: 'Mobile number not found.Contact to administrator', color: 'red', }); return; } try { await sendOtp({ type: 'BENEFICIARY_DELETE', beneficiary: selectedAccount ? maskAccount(selectedAccount) : undefined }); setCountdown(180); setTimerActive(true); } catch (err: any) { console.error('Send OTP failed', err); notifications.show({ title: 'Error', message: err.message || 'Send OTP failed.Please try again later.', color: 'red', }); } } async function handleVerifyOtp() { try { await verifyOtp(otp); return true; } catch { return false; } } const openDeleteModal = (accountNo: string) => { setSelectedAccount(accountNo); setOpened(true); setOtpStep(false); // Reset modal to confirmation step setOtp(""); }; const handleModalConfirm = async () => { if (!selectedAccount) return; try { await handleSendOtp(); // send OTP to user's mobile setOtpStep(true); // move modal to OTP input step } catch (err) { notifications.show({ title: "Error", message: "Failed to send OTP. Please try again.", color: "red", }); } }; // Step 3: Handle OTP verification & delete const handleVerifyOtpAndDelete = async () => { if (!otp || !selectedAccount) return; try { const isOtpValid = await handleVerifyOtp(); // verify OTP if (!isOtpValid) { notifications.show({ title: "Invalid OTP", message: "Please enter the correct OTP.", color: "red", }); return; } // OTP is valid → delete beneficiary const token = localStorage.getItem("access_token"); const res = await fetch(`/api/beneficiary/${selectedAccount}`, { method: "DELETE", headers: { "Content-Type": "application/json", "X-Login-Type": "IB", Authorization: `Bearer ${token}` }, }); if (res.ok) { setBeneficiaries((prev) => prev.filter((b) => b.accountNo !== selectedAccount)); notifications.show({ title: "Deleted", message: "Beneficiary deleted successfully.", color: "green", }); setOpened(false); setOtpStep(false); setOtp(""); } else { notifications.show({ title: "Error", message: "Failed to delete beneficiary.", color: "red", }); } } catch (err) { notifications.show({ title: "Error", message: "Something went wrong.", color: "red", }); } }; useEffect(() => { const token = localStorage.getItem("access_token"); if (!token) { setAuthorized(false); router.push("/login"); } else { setAuthorized(true); } }, []); useEffect(() => { const fetchBeneficiaries = async () => { try { const token = localStorage.getItem("access_token"); const response = await fetch(`/api/beneficiary`, { method: "GET", headers: { "Content-Type": "application/json", "X-Login-Type": "IB", Authorization: `Bearer ${token}`, }, }); if (!response.ok) throw new Error("Failed to fetch beneficiaries"); const data = await response.json(); setBeneficiaries(data); } catch (error) { notifications.show({ title: "Error", message: "Unable to fetch beneficiaries. Please try again later.", color: "red", }); } finally { setLoading(false); } }; fetchBeneficiaries(); }, []); //new use effect useEffect(() => { let interval: NodeJS.Timeout | null = null; if (timerActive && countdown > 0) { interval = setInterval(() => { setCountdown((prev) => prev - 1); }, 1000); } else if (countdown === 0) { setTimerActive(false); } return () => { if (interval) clearInterval(interval); }; }, [timerActive, countdown]); if (loading) { return (
); } if (!authorized) return null; return ( My Beneficiaries {beneficiaries.length === 0 ? ( No beneficiaries found. ) : ( <> BankAccount NoNameTypeIFSCAction Icon {beneficiaries.map((b, i) => ( {b.bankName} {b.accountNo} {b.name} {b.accountType} {b.ifscCode} {/* */} openDeleteModal(b.accountNo)} /> ))}
{ setOpened(false); setOtpStep(false); setOtp(""); }} title="Delete Beneficiary" centered > {!otpStep ? ( <> Are you sure you want to delete this beneficiary? ) : ( <> Enter OTP sent to your registered number: setOtp(e.currentTarget.value)} placeholder="Enter OTP" maxLength={6} /> {/* Resend OTP Timer or Icon */} {timerActive ? ( Resend OTP will be enabled in{" "} {String(Math.floor(countdown / 60)).padStart(2, "0")}: {String(countdown % 60).padStart(2, "0")} ) : ( )} )} )}
); }