diff --git a/src/app/(main)/funds_transfer/add_beneficiary/addBeneficiaryOthers.tsx b/src/app/(main)/funds_transfer/add_beneficiary/addBeneficiaryOthers.tsx new file mode 100644 index 0000000..30ab2e3 --- /dev/null +++ b/src/app/(main)/funds_transfer/add_beneficiary/addBeneficiaryOthers.tsx @@ -0,0 +1,411 @@ +"use client"; + +import React, { useEffect, useState } from 'react'; +import { + TextInput, + Button, + Select, + Title, + Paper, + Grid, + Group, + Radio, + Text, +} from '@mantine/core'; +import { notifications } from '@mantine/notifications'; + +type IfscDataType = { + [key: string]: { + bank: string; + branch: string; + }; +}; + +const mockIfscData: IfscDataType = { + + 'SBIN0004567': { + 'bank': 'State Bank of India', + 'branch': 'Connaught Place', + }, + 'ICIC0007347': { + 'bank': 'ICICI', + 'branch': 'Ghatal', + }, + 'ICIC0001608': { + 'bank': 'ICICI', + 'branch': 'ICICI Bank Ltd.,Serampore' + }, +}; + +const MockOthersAccountValidation = + [ + { + 'stBenAccountNo': '50077736834', + 'stBenName': 'Ram Patnayak', + }, + { + 'stBenAccountNo': '50088836834', + 'stBenName': 'Sumit Ghosh', + }, + { + 'stBenAccountNo': '21112076570', + 'stBenName': 'Mr Sumit Ghosh', + }, + ] + + +const AddBeneficiaryOthers: React.FC = () => { + const [bankName, setBankName] = useState(''); + const [ifsccode, setIfsccode] = useState(''); + const [branchName, setBranchName] = useState(''); + const [accountNo, setAccountNo] = useState(''); + const [confirmAccountNo, setConfirmAccountNo] = useState(''); + const [nickName, setNickName] = useState(''); + const [beneficiaryName, setBeneficiaryName] = useState(null); + + const [otp, setOtp] = useState(''); + const [generatedOtp, setGeneratedOtp] = useState(''); + const [otpSent, setOtpSent] = useState(false); + const [otpVerified, setOtpVerified] = 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); }; + + useEffect(() => { + const ifscTrimmed = ifsccode.trim(); + const match = mockIfscData[ifscTrimmed]; + + if (match && match.bank.toLowerCase() === bankName.trim().toLowerCase()) { + setBranchName(match.branch); + } else { + setBranchName("No result found"); + } + }, [bankName, ifsccode]); + + const handleGenerateOtp = async () => { + const value = "123456"; // Or generate a random OTP + setGeneratedOtp(value); + return value; + }; + + const validateAndSendOtp = async () => { + if (!bankName || !ifsccode || !branchName || !accountNo || !confirmAccountNo) { + notifications.show({ + withBorder: true, + color: "red", + title: "Missing Field", + message: "All fields must be completed.", + autoClose: 5000, + }); + return; + } + + // if ( !/^[A-Za-z ]{1,5}$/.test(bankName)) { + // notifications.show({ + // color: "red", + // title: "Invalid Bank Name", + // message: "Use only alphabets/spaces, max 100 characters.", + // }); + // 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 { + const matched = MockOthersAccountValidation.find( + (entry) => entry.stBenAccountNo === accountNo + ); + + if (matched) { + setBeneficiaryName(matched.stBenName); + setValidationStatus("success"); + setIsVisibilityLocked(true); + setOtpSent(true); + await handleGenerateOtp(); + + 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"); + } + + // Later need to add api + // try { + // // API will be changed + // const token = localStorage.getItem("access_token"); + // const response = await fetch(`/api/beneficiary/validate/within-bank?accountNumber=${accountNo}`, { + // 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); + // await handleGenerateOtp(); + + // 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) { + // setBeneficiaryName("Invalid beneficiary account number"); + // setValidationStatus("error"); + + + // notifications.show({ + // withBorder: true, + // color: "red", + // title: "Error", + // message: "Could not validate account number.", + // autoClose: 5000, + // }); + // } + }; + + const verifyOtp = () => { + if (otp === generatedOtp) { + setOtpVerified(true); + notifications.show({ + withBorder: true, + color: "green", + title: "OTP Verified", + message: "OTP validated successfully.", + autoClose: 5000, + }); + } else { + notifications.show({ + withBorder: true, + color: "red", + title: "OTP Error", + message: "OTP does not match.", + autoClose: 5000, + }); + } + }; + const AddBen = () => { + notifications.show({ + withBorder: true, + color: "green", + title: "Beneficiary Added", + message: "Beneficiary added successfully.", + autoClose: 5000, + }); + }; + + return ( + + + { + let val = e.currentTarget.value.replace(/[^A-Za-z ]/g, ""); + setBankName(val.slice(0, 100)); + }} + required + /> + + + + setIfsccode(e.currentTarget.value)} + onChange={(e) => { + let val = e.currentTarget.value.toUpperCase(); + val = val.replace(/[^A-Z0-9]/g, ""); // block special chars + setIfsccode(val); + }} + maxLength={11} + required + /> + + + + + + + + { + 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} + // disabled={isVisibilityLocked} + required + /> + + + + { + const value = e.currentTarget.value; + if (/^\d*$/.test(value) && value.length <= 17) { + setConfirmAccountNo(value); + } + }} + maxLength={17} + // disabled={isVisibilityLocked} + readOnly={isVisibilityLocked} + required + // onCopy={(e) => e.preventDefault()} + // onPaste={(e) => e.preventDefault()} + // onCut={(e) => e.preventDefault()} + /> + + {validationStatus === "error" && ( + + {beneficiaryName} + + )} + + + + setNickName(e.currentTarget.value)} + /> + + + + + + + + {!otpSent && ( + + + + )} + + {otpSent && ( + <> + + setOtp(e.currentTarget.value)} + maxLength={6} + disabled={otpVerified} // ✅ Disable after verified + /> + + + {!otpVerified ? ( + + ) : ( + + + + )} + + + )} + + + + ); +}; + +export default AddBeneficiaryOthers; diff --git a/src/app/(main)/funds_transfer/add_beneficiary/page.tsx b/src/app/(main)/funds_transfer/add_beneficiary/page.tsx index bf6eed6..12e88d1 100644 --- a/src/app/(main)/funds_transfer/add_beneficiary/page.tsx +++ b/src/app/(main)/funds_transfer/add_beneficiary/page.tsx @@ -13,6 +13,7 @@ import { Text, } from '@mantine/core'; import { notifications } from '@mantine/notifications'; +import AddBeneficiaryOthers from './addBeneficiaryOthers'; const bankOptions = [ { value: 'KCCB', label: 'KCCB - The Kangra Central Co-Operative Bank' }, @@ -23,7 +24,6 @@ const AddBeneficiary: React.FC = () => { const [bankType, setBankType] = useState('own'); const [accountNo, setAccountNo] = useState(''); const [confirmAccountNo, setConfirmAccountNo] = useState(''); - const [payeeName, setPayeeName] = useState(''); const [nickName, setNickName] = useState(''); const [otp, setOtp] = useState(''); const [generatedOtp, setGeneratedOtp] = useState(''); @@ -33,7 +33,6 @@ const AddBeneficiary: React.FC = () => { const [beneficiaryName, setBeneficiaryName] = useState(null); const [isVisibilityLocked, setIsVisibilityLocked] = useState(false); const [showPayeeAcc, setShowPayeeAcc] = useState(true); - const getFullMaskedAccount = (acc: string) => { return "X".repeat(acc.length); }; const handleGenerateOtp = async () => { @@ -42,6 +41,17 @@ const AddBeneficiary: React.FC = () => { return value; }; + // const isValidBankName = (name: string) => { + // const regex = /^[A-Za-z\s]{3,5}$/; + // return regex.test(name.trim()); + // }; + + // const isValidIfscCode = (code: string) => { + // return /^[A-Z]{4}0[0-9]{6}$/.test(code); + // }; + + + const validateAndSendOtp = async () => { if (!bankName || !accountNo || !confirmAccountNo) { notifications.show({ @@ -54,6 +64,31 @@ const AddBeneficiary: React.FC = () => { return; } + + // if (bankType === "outside" && !/^[A-Za-z ]{1,5}$/.test(bankName)) { + // notifications.show({ + // color: "red", + // title: "Invalid Bank Name", + // message: "Use only alphabets/spaces, max 100 characters.", + // }); + // return; + // } + + // const trimmedIfsc = ifsccode.trim().toUpperCase(); + + // 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, @@ -65,6 +100,9 @@ const AddBeneficiary: React.FC = () => { return; } + + + if (accountNo !== confirmAccountNo) { notifications.show({ withBorder: true, @@ -112,6 +150,7 @@ const AddBeneficiary: React.FC = () => { setBeneficiaryName("Invalid beneficiary account number"); setValidationStatus("error"); + notifications.show({ withBorder: true, color: "red", @@ -143,8 +182,19 @@ const AddBeneficiary: React.FC = () => { } }; + const AddBen = () => { + notifications.show({ + withBorder: true, + color: "green", + title: "Beneficiary Added", + message: "Beneficiary added successfully.", + autoClose: 5000, + }); + }; + + return ( - + Add Beneficiary @@ -183,7 +233,7 @@ const AddBeneficiary: React.FC = () => { onFocus={() => setShowPayeeAcc(true)} readOnly={isVisibilityLocked} maxLength={17} - // disabled={isVisibilityLocked} + // disabled={isVisibilityLocked} required /> @@ -200,12 +250,12 @@ const AddBeneficiary: React.FC = () => { } }} maxLength={17} - // disabled={isVisibilityLocked} + // disabled={isVisibilityLocked} readOnly={isVisibilityLocked} required - onCopy={(e) => e.preventDefault()} - onPaste={(e) => e.preventDefault()} - onCut={(e) => e.preventDefault()} + // onCopy={(e) => e.preventDefault()} + // onPaste={(e) => e.preventDefault()} + // onCut={(e) => e.preventDefault()} /> {validationStatus === "error" && ( @@ -257,9 +307,7 @@ const AddBeneficiary: React.FC = () => { {!otpVerified ? ( ) : ( - - - )} @@ -268,9 +316,9 @@ const AddBeneficiary: React.FC = () => { )} ) : ( - - Outside Bank feature coming soon. - + + + )} );