Files
IB/src/app/(main)/funds_transfer/add_beneficiary/addBeneficiaryOthers.tsx

426 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useEffect, useState } from 'react';
import {
TextInput,
Button,
Select,
Title,
Paper,
Grid,
Group,
Radio,
Text,
PasswordInput,
} from '@mantine/core';
import { notifications } from '@mantine/notifications';
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<string | null>(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();
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 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 (1017 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 (
<Grid gutter="md">
<Grid.Col span={4}>
<TextInput
label="IFSC Code"
placeholder="e.g.,ABCD0123456"
//data={bankOptions}
value={ifsccode}
// onChange={(e) => 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
/>
</Grid.Col>
<Grid.Col span={4}>
<TextInput
label="Bank Name"
placeholder="Enter bank"
value={bankName}
disabled
onChange={(e) => {
let val = e.currentTarget.value.replace(/[^A-Za-z ]/g, "");
setBankName(val.slice(0, 100));
}}
required
/>
</Grid.Col>
<Grid.Col span={4}>
<TextInput
label="Branch Name"
value={branchName}
disabled
maxLength={100}
required
/>
</Grid.Col>
<Grid.Col span={4}>
<TextInput
label="Beneficiary Account Number"
placeholder="Enter account number"
value={showPayeeAcc ? accountNo : getFullMaskedAccount(accountNo)}
onChange={(e) => {
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
/>
</Grid.Col>
<Grid.Col span={4}>
<TextInput
label="Confirm Beneficiary Account Number"
placeholder="Re-enter account number"
value={confirmAccountNo}
onChange={(e) => {
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" && (
<Text c="red" size="sm" style={{ marginLeft: '1rem', whiteSpace: 'nowrap' }}>
{beneficiaryName}
</Text>
)}
</Grid.Col>
<Grid.Col span={4}>
<TextInput
label="Nick Name (Optional)"
placeholder="Enter nickname (optional)"
value={nickName}
onChange={(e) => setNickName(e.currentTarget.value)}
/>
</Grid.Col>
<Grid.Col span={4}>
<TextInput
label="Beneficiary Name"
value={validationStatus === "success" && beneficiaryName ? beneficiaryName : ""}
disabled
maxLength={100}
required
/>
</Grid.Col>
{!otpSent && (
<Grid.Col>
<Button onClick={validateAndSendOtp}>Validate</Button>
</Grid.Col>
)}
{otpSent && (
<>
<Grid.Col span={3}>
<PasswordInput
label="Enter OTP"
placeholder="Enter OTP"
value={otp}
onChange={(e) => setOtp(e.currentTarget.value)}
maxLength={6}
disabled={otpVerified} // ✅ Disable after verified
/>
</Grid.Col >
<Grid.Col >
{!otpVerified ? (
<Button onClick={verifyOtp}>Validate OTP</Button>
) : (
<Button color="blue" size="sm" onClick={AddBen}>
Add
</Button>
)}
</Grid.Col>
</>
)}
</Grid>
);
};
export default AddBeneficiaryOthers;