"use client"; import React, { useEffect, useState } from 'react'; import { TextInput, Button, Grid, Text, PasswordInput, Loader, Group, Select, Stack } from '@mantine/core'; import { notifications } from '@mantine/notifications'; import { useRouter } from "next/navigation"; import { IconRefresh } from '@tabler/icons-react'; import { sendOtp, verifyOtp } from '@/app/_util/otp'; export default function AddBeneficiaryOthers() { const router = useRouter(); const [authorized, setAuthorized] = useState(null); const [loading, setLoading] = useState(false); const [bankName, setBankName] = useState(''); const [ifsccode, setIfsccode] = useState(''); const [branchName, setBranchName] = useState(''); const [accountNo, setAccountNo] = useState(''); const [confirmAccountNo, setConfirmAccountNo] = useState(''); const [beneficiaryType, setBeneficiaryType] = useState(null); const [nickName, setNickName] = useState(''); const [beneficiaryName, setBeneficiaryName] = useState(null); const [otp, setOtp] = useState(''); const [otpSent, setOtpSent] = useState(false); const [otpVerified, setOtpVerified] = useState(false); const [countdown, setCountdown] = useState(180); const [timerActive, setTimerActive] = useState(false); const [validationStatus, setValidationStatus] = useState<'success' | 'error' | null>(null); const [isVisibilityLocked, setIsVisibilityLocked] = useState(false); const [showPayeeAcc, setShowPayeeAcc] = useState(true); const getFullMaskedAccount = (acc: string) => { return "X".repeat(acc.length); }; 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_ADD', beneficiary: beneficiaryName || undefined, ifsc: ifsccode }); 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; } } // Countdown effect useEffect(() => { let interval: number | undefined; if (timerActive && countdown > 0) { interval = window.setInterval(() => { setCountdown((prev) => prev - 1); }, 1000); } if (countdown === 0) { if (interval) clearInterval(interval); setTimerActive(false); } return () => { if (interval) clearInterval(interval); }; }, [timerActive, countdown]); useEffect(() => { const token = localStorage.getItem("access_token"); if (!token) { setAuthorized(false); router.push("/login"); } else { setAuthorized(true); } }, []); useEffect(() => { const ifscTrimmed = ifsccode.trim(); if (ifscTrimmed.length === 11) { // Only call API when IFSC is valid length const fetchIfscDetails = async () => { try { const token = localStorage.getItem("access_token"); const response = await fetch( `http://localhost:8080/api/beneficiary/ifsc-details?ifscCode=${ifscTrimmed}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, } ); if (!response.ok) { throw new Error("Failed to fetch IFSC details"); } const data = await response.json(); if (data && data.bank_name && data.branch_name) { setBankName(data.bank_name); setBranchName(data.branch_name); } else { setBranchName("No result found"); setBankName(""); } } catch (error) { console.error("Error fetching IFSC details:", error); setBranchName("No result found"); setBankName(""); } }; fetchIfscDetails(); } }, [ifsccode]); const validateAndSendOtp = async () => { if (!bankName || !ifsccode || !branchName || !accountNo || !confirmAccountNo || !beneficiaryType) { notifications.show({ withBorder: true, color: "red", title: "Missing Field", message: "All fields must be completed.", autoClose: 5000, }); return; } const trimmedIfsc = ifsccode.trim().toUpperCase(); const isValidIfscCode = (code: string) => { return /^[A-Z]{4}0[0-9]{6}$/.test(code); }; if (!isValidIfscCode(trimmedIfsc)) { notifications.show({ title: "Invalid IFSC Code", message: "Must be 11 characters: 4 uppercase letters, 0, then 6 digits (e.g., HDFC0123456)", color: "red", }); return; } if (accountNo.length < 10 || accountNo.length > 17) { notifications.show({ withBorder: true, color: "red", title: "Invalid Account Number", message: "Enter a valid account number (10–17 digits).", autoClose: 5000, }); return; } if (accountNo !== confirmAccountNo) { notifications.show({ withBorder: true, color: "red", title: "Mismatch", message: "Account numbers do not match.", autoClose: 5000, }); return; } // Validation for now try { setLoading(true); const token = localStorage.getItem("access_token"); const response = await fetch(`/api/beneficiary/validate/outside-bank?accountNo=${accountNo}&ifscCode=${ifsccode}&remitterName=""`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, } ); const data = await response.json(); if (response.ok && data?.name) { setBeneficiaryName(data.name); setValidationStatus("success"); setIsVisibilityLocked(true); setOtpSent(true); const otp = await handleSendOtp(); notifications.show({ withBorder: true, color: "green", title: "OTP Sent", message: "OTP has been sent to your registered mobile number.", autoClose: 5000, }); } else { setBeneficiaryName("Invalid beneficiary account number"); setValidationStatus("error"); setAccountNo(""); setConfirmAccountNo(""); } } catch (error) { console.error("Validation error:", error); setBeneficiaryName("Something went wrong"); setValidationStatus("error"); } finally { setLoading(false); } }; const verify_otp = async () => { if (!otp) { notifications.show({ withBorder: true, color: "Red", title: "Null Field", message: "Please Enter Valid OTP", autoClose: 5000, }); return; } const verified = await handleVerifyOtp(); if (!verified) { notifications.show({ title: "Invalid OTP", message: "The OTP entered does not match", color: "red", }); return; } setOtpVerified(true); notifications.show({ title: "OTP Verified", message: "OTP successfully verified.", color: "green", }); }; const AddBen = async () => { try { const token = localStorage.getItem("access_token"); const response = await fetch(`/api/beneficiary`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ accountNo: accountNo, ifscCode: ifsccode, accountType: beneficiaryType, name: beneficiaryName }), } ); const data = await response.json(); if (response.ok) { notifications.show({ withBorder: true, color: "green", title: "Added", message: "Beneficiary Added successfully", autoClose: 5000, }); return; } else { notifications.show({ withBorder: true, color: "Red", title: "Error", message: data?.error, autoClose: 5000, }); return; } } catch { notifications.show({ title: "Error", message: "Something went wrong", color: "red", }); } finally { setBankName(''); setBranchName(''); setIfsccode(''); setAccountNo(''); setConfirmAccountNo(''); setBeneficiaryName(''); setNickName(''); setBeneficiaryType(null); setIsVisibilityLocked(false); setOtpSent(false); } }; if (!authorized) return null; return ( { let val = e.currentTarget.value.toUpperCase(); val = val.replace(/[^A-Z0-9]/g, ""); // block special chars setIfsccode(val); }} maxLength={11} withAsterisk /> { let val = e.currentTarget.value.replace(/[^A-Za-z ]/g, ""); setBankName(val.slice(0, 100)); }} withAsterisk /> { const value = e.currentTarget.value; if (/^\d*$/.test(value) && value.length <= 17) { setAccountNo(value); setShowPayeeAcc(true); } }} onBlur={() => setShowPayeeAcc(false)} onFocus={() => setShowPayeeAcc(true)} readOnly={isVisibilityLocked} maxLength={17} withAsterisk /> { const value = e.currentTarget.value; if (/^\d*$/.test(value) && value.length <= 17) { setConfirmAccountNo(value); } }} maxLength={17} readOnly={isVisibilityLocked} withAsterisk onCopy={(e) => e.preventDefault()} onPaste={(e) => e.preventDefault()} onCut={(e) => e.preventDefault()} /> {validationStatus === "error" && ( {beneficiaryName} )}