Wip: update the login page,
feat: update Otp in set login and transaction page. Feat: Add validation for external account in add beneficiary.
This commit is contained in:
@@ -37,8 +37,8 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
<Stack style={{ background: '#228be6', height: '10%', alignItems: 'center' }}>
|
||||
<Text fw={700} fs="italic" c='white' style={{ textAlign: 'center', marginTop: '10px' }}>
|
||||
Accounts
|
||||
<Text fw={700} c='white' style={{ textAlign: 'center', marginTop: '10px' }}>
|
||||
My Accounts
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
|
@@ -1,19 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
TextInput,
|
||||
Button,
|
||||
Select,
|
||||
Title,
|
||||
Paper,
|
||||
Grid,
|
||||
Group,
|
||||
Radio,
|
||||
Text,
|
||||
PasswordInput,
|
||||
} from '@mantine/core';
|
||||
import { TextInput, Button, Grid, Text, PasswordInput } from '@mantine/core';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
const MockOthersAccountValidation =
|
||||
[
|
||||
@@ -31,8 +21,9 @@ const MockOthersAccountValidation =
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
const AddBeneficiaryOthers: React.FC = () => {
|
||||
export default function AddBeneficiaryOthers() {
|
||||
const router = useRouter();
|
||||
const [authorized, setAuthorized] = useState<boolean | null>(null);
|
||||
const [bankName, setBankName] = useState('');
|
||||
const [ifsccode, setIfsccode] = useState('');
|
||||
const [branchName, setBranchName] = useState('');
|
||||
@@ -40,24 +31,28 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
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 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 {
|
||||
@@ -115,15 +110,6 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
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);
|
||||
@@ -161,12 +147,25 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
}
|
||||
// Validation for now
|
||||
try {
|
||||
const matched = MockOthersAccountValidation.find(
|
||||
(entry) => entry.stBenAccountNo === accountNo
|
||||
);
|
||||
// const matched = MockOthersAccountValidation.find(
|
||||
// (entry) => entry.stBenAccountNo === accountNo
|
||||
// );
|
||||
|
||||
if (matched) {
|
||||
setBeneficiaryName(matched.stBenName);
|
||||
const token = localStorage.getItem("access_token");
|
||||
const response = await fetch(
|
||||
`http://localhost:8080/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);
|
||||
@@ -190,55 +189,6 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
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 = () => {
|
||||
@@ -271,6 +221,7 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
});
|
||||
};
|
||||
|
||||
if (!authorized) return null;
|
||||
return (
|
||||
<Grid gutter="md">
|
||||
|
||||
@@ -278,9 +229,7 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
<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
|
||||
@@ -305,8 +254,6 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
|
||||
|
||||
<Grid.Col span={4}>
|
||||
<TextInput
|
||||
label="Branch Name"
|
||||
@@ -422,4 +369,4 @@ const AddBeneficiaryOthers: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default AddBeneficiaryOthers;
|
||||
|
||||
|
@@ -1,27 +1,20 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
TextInput,
|
||||
Button,
|
||||
Select,
|
||||
Title,
|
||||
Paper,
|
||||
Grid,
|
||||
Group,
|
||||
Radio,
|
||||
Text,
|
||||
PasswordInput,
|
||||
} from '@mantine/core';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {TextInput,Button,Select,Title,Paper,Grid,Group,Radio,Text,PasswordInput} from '@mantine/core';
|
||||
import { useRouter } from "next/navigation";
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import AddBeneficiaryOthers from './addBeneficiaryOthers';
|
||||
import { generateOTP } from '@/app/OTPGenerator';
|
||||
|
||||
const bankOptions = [
|
||||
{ value: 'KCCB', label: 'KCCB - The Kangra Central Co-Operative Bank' },
|
||||
];
|
||||
|
||||
const AddBeneficiary: React.FC = () => {
|
||||
const router = useRouter();
|
||||
const [bankName, setBankName] = useState('');
|
||||
const [authorized, setAuthorized] = useState<boolean | null>(null);
|
||||
const [bankType, setBankType] = useState('own');
|
||||
const [accountNo, setAccountNo] = useState('');
|
||||
const [confirmAccountNo, setConfirmAccountNo] = useState('');
|
||||
@@ -37,11 +30,20 @@ const AddBeneficiary: React.FC = () => {
|
||||
const getFullMaskedAccount = (acc: string) => { return "X".repeat(acc.length); };
|
||||
|
||||
const handleGenerateOtp = async () => {
|
||||
// const value = await generateOTP(6);
|
||||
const value = "123456"; // Or generate a random OTP
|
||||
setGeneratedOtp(value);
|
||||
return value;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem("access_token");
|
||||
if (!token) {
|
||||
setAuthorized(false);
|
||||
router.push("/login");
|
||||
} else {
|
||||
setAuthorized(true);
|
||||
}
|
||||
}, []);
|
||||
// const isValidBankName = (name: string) => {
|
||||
// const regex = /^[A-Za-z\s]{3,5}$/;
|
||||
// return regex.test(name.trim());
|
||||
@@ -51,8 +53,6 @@ const AddBeneficiary: React.FC = () => {
|
||||
// return /^[A-Z]{4}0[0-9]{6}$/.test(code);
|
||||
// };
|
||||
|
||||
|
||||
|
||||
const validateAndSendOtp = async () => {
|
||||
if (!bankName || !accountNo || !confirmAccountNo) {
|
||||
notifications.show({
|
||||
@@ -86,10 +86,6 @@ const AddBeneficiary: React.FC = () => {
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (accountNo.length < 10 || accountNo.length > 17) {
|
||||
notifications.show({
|
||||
withBorder: true,
|
||||
@@ -101,9 +97,6 @@ const AddBeneficiary: React.FC = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (accountNo !== confirmAccountNo) {
|
||||
notifications.show({
|
||||
withBorder: true,
|
||||
@@ -193,6 +186,7 @@ const AddBeneficiary: React.FC = () => {
|
||||
});
|
||||
};
|
||||
|
||||
if (!authorized) return null;
|
||||
|
||||
return (
|
||||
<Paper shadow="sm" radius="md" p="md" withBorder h={400}>
|
||||
@@ -254,9 +248,9 @@ const AddBeneficiary: React.FC = () => {
|
||||
// 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" && (
|
||||
|
@@ -38,7 +38,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
<Stack style={{ background: '#228be6', height: '10%', alignItems: 'center' }}>
|
||||
<Text fw={700} fs="italic" c='white' style={{ textAlign: 'center', marginTop: '10px' }}>
|
||||
<Text fw={700} c='white' style={{ textAlign: 'center', marginTop: '10px' }}>
|
||||
Send Money
|
||||
</Text>
|
||||
</Stack>
|
||||
|
@@ -6,6 +6,7 @@ import { notifications } from "@mantine/notifications";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { generateOTP } from '@/app/OTPGenerator';
|
||||
import OutsideQuickPay from "./outside_quick_pay";
|
||||
import { IconRefresh } from "@tabler/icons-react";
|
||||
|
||||
interface accountData {
|
||||
stAccountNo: string;
|
||||
@@ -34,6 +35,8 @@ export default function QuickPay() {
|
||||
const [validationStatus, setValidationStatus] = useState<"success" | "error" | null>(null);
|
||||
const [beneficiaryName, setBeneficiaryName] = useState<string | null>(null);
|
||||
const [showOtpField, setShowOtpField] = useState(false);
|
||||
const [countdown, setCountdown] = useState(60);
|
||||
const [timerActive, setTimerActive] = useState(false);
|
||||
const [otp, setOtp] = useState("");
|
||||
const [generateOtp, setGenerateOtp] = useState("");
|
||||
|
||||
@@ -41,6 +44,8 @@ export default function QuickPay() {
|
||||
// const value = await generateOTP(6);
|
||||
const value = "123456";
|
||||
setGenerateOtp(value);
|
||||
setCountdown(60);
|
||||
setTimerActive(true);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -94,6 +99,22 @@ export default function QuickPay() {
|
||||
}
|
||||
}, [authorized]);
|
||||
|
||||
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]);
|
||||
|
||||
async function handleValidate() {
|
||||
if (!selectedAccNo || !beneficiaryAcc ||
|
||||
!confirmBeneficiaryAcc
|
||||
@@ -257,6 +278,7 @@ export default function QuickPay() {
|
||||
color: "red",
|
||||
});
|
||||
} finally {
|
||||
setValidationStatus(null);
|
||||
setSelectedAccNo(null);
|
||||
setBeneficiaryAcc('');
|
||||
setBeneficiaryName('');
|
||||
@@ -313,142 +335,161 @@ export default function QuickPay() {
|
||||
{/* main content */}
|
||||
<Paper shadow="sm" radius="md" p="md" withBorder h={400}>
|
||||
<Title order={3} mb="md">
|
||||
Quick Pay
|
||||
Quick Pay - Own Bank
|
||||
</Title>
|
||||
|
||||
<div style={{ maxHeight: "320px", overflowY: "auto" }}>
|
||||
<Stack gap="xs">
|
||||
<Group grow>
|
||||
<Select
|
||||
label="Select Debit Account Number"
|
||||
placeholder="Choose account number"
|
||||
data={accountOptions}
|
||||
value={selectedAccNo}
|
||||
onChange={setSelectedAccNo}
|
||||
withAsterisk
|
||||
readOnly={isVisibilityLocked}
|
||||
/>
|
||||
<TextInput
|
||||
label="Payee Account No"
|
||||
value={showPayeeAcc ? beneficiaryAcc : getFullMaskedAccount(beneficiaryAcc)}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
if (/^\d*$/.test(value)) {
|
||||
setBeneficiaryAcc(value);
|
||||
setShowPayeeAcc(true);
|
||||
}
|
||||
}}
|
||||
onBlur={() => setShowPayeeAcc(false)}
|
||||
onFocus={() => setShowPayeeAcc(true)}
|
||||
withAsterisk
|
||||
readOnly={isVisibilityLocked}
|
||||
/>
|
||||
<div style={{ maxHeight: "320px", overflowY: "auto" }}>
|
||||
<Stack gap="xs">
|
||||
<Group grow>
|
||||
<Select
|
||||
label="Select Debit Account Number"
|
||||
placeholder="Choose account number"
|
||||
data={accountOptions}
|
||||
value={selectedAccNo}
|
||||
onChange={setSelectedAccNo}
|
||||
withAsterisk
|
||||
readOnly={isVisibilityLocked}
|
||||
/>
|
||||
<TextInput
|
||||
label="Payee Account No"
|
||||
value={showPayeeAcc ? beneficiaryAcc : getFullMaskedAccount(beneficiaryAcc)}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
if (/^\d*$/.test(value)) {
|
||||
setBeneficiaryAcc(value);
|
||||
setShowPayeeAcc(true);
|
||||
}
|
||||
}}
|
||||
onBlur={() => setShowPayeeAcc(false)}
|
||||
onFocus={() => setShowPayeeAcc(true)}
|
||||
withAsterisk
|
||||
readOnly={isVisibilityLocked}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
label="Confirm Payee Account No"
|
||||
value={confirmBeneficiaryAcc}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
if (/^\d*$/.test(value)) {
|
||||
setConfirmBeneficiaryAcc(value);
|
||||
}
|
||||
}}
|
||||
onCopy={(e) => e.preventDefault()}
|
||||
onPaste={(e) => e.preventDefault()}
|
||||
onCut={(e) => e.preventDefault()}
|
||||
withAsterisk
|
||||
readOnly={isVisibilityLocked}
|
||||
/>
|
||||
<TextInput
|
||||
label="Confirm Payee Account No"
|
||||
value={confirmBeneficiaryAcc}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
if (/^\d*$/.test(value)) {
|
||||
setConfirmBeneficiaryAcc(value);
|
||||
}
|
||||
}}
|
||||
onCopy={(e) => e.preventDefault()}
|
||||
onPaste={(e) => e.preventDefault()}
|
||||
onCut={(e) => e.preventDefault()}
|
||||
withAsterisk
|
||||
readOnly={isVisibilityLocked}
|
||||
/>
|
||||
</Group>
|
||||
<Group justify="space-between" >
|
||||
<Text size="xs" c="green" style={{ visibility: selectedAccount ? "visible" : "hidden" }}>Available Balance :
|
||||
{selectedAccount ? selectedAccount.stAvailableBalance : 0}
|
||||
</Text>
|
||||
<Group justify="center">
|
||||
{validationStatus === "error" && <Text size="sm" fw={700} ta="right" c="red">{beneficiaryName}</Text>}
|
||||
</Group>
|
||||
<Group justify="space-between" >
|
||||
<Text size="xs" c="green" style={{ visibility: selectedAccount ? "visible" : "hidden" }}>Available Balance :
|
||||
{selectedAccount ? selectedAccount.stAvailableBalance : 0}
|
||||
</Text>
|
||||
<Group justify="center">
|
||||
{validationStatus === "error" && <Text size="sm" fw={700} ta="right" c="red">{beneficiaryName}</Text>}
|
||||
</Group>
|
||||
</Group>
|
||||
<Group grow>
|
||||
<TextInput
|
||||
label="Payee Name"
|
||||
value={validationStatus === "success" && beneficiaryName ? beneficiaryName : ""}
|
||||
disabled
|
||||
readOnly
|
||||
withAsterisk
|
||||
/>
|
||||
</Group>
|
||||
<Group grow>
|
||||
<TextInput
|
||||
label="Payee Name"
|
||||
value={validationStatus === "success" && beneficiaryName ? beneficiaryName : ""}
|
||||
disabled
|
||||
readOnly
|
||||
withAsterisk
|
||||
/>
|
||||
|
||||
<Select
|
||||
label="Payee Account Type"
|
||||
placeholder="Select type"
|
||||
data={["Savings", "Current"]}
|
||||
value={beneficiaryType}
|
||||
onChange={setBeneficiaryType}
|
||||
withAsterisk
|
||||
readOnly={showOtpField}
|
||||
/>
|
||||
<Select
|
||||
label="Payee Account Type"
|
||||
placeholder="Select type"
|
||||
data={["Savings", "Current"]}
|
||||
value={beneficiaryType}
|
||||
onChange={setBeneficiaryType}
|
||||
withAsterisk
|
||||
readOnly={showOtpField}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
label="Amount"
|
||||
type="number"
|
||||
value={amount}
|
||||
onChange={(e) => setAmount(e.currentTarget.value)}
|
||||
error={
|
||||
selectedAccount && Number(amount) > Number(selectedAccount.stAvailableBalance) ?
|
||||
"Amount exceeds available balance" : false}
|
||||
withAsterisk
|
||||
readOnly={showOtpField}
|
||||
/>
|
||||
<TextInput
|
||||
label="Amount"
|
||||
type="number"
|
||||
value={amount}
|
||||
onChange={(e) => setAmount(e.currentTarget.value)}
|
||||
error={
|
||||
selectedAccount && Number(amount) > Number(selectedAccount.stAvailableBalance) ?
|
||||
"Amount exceeds available balance" : false}
|
||||
withAsterisk
|
||||
readOnly={showOtpField}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
label="Remarks"
|
||||
placeholder="Enter remarks"
|
||||
value={remarks}
|
||||
onChange={(e) => setRemarks(e.currentTarget.value)}
|
||||
// withAsterisk
|
||||
readOnly={showOtpField}
|
||||
withAsterisk
|
||||
/>
|
||||
</Group>
|
||||
<Group grow>
|
||||
{showOtpField && (
|
||||
<TextInput
|
||||
label="Remarks"
|
||||
placeholder="Enter remarks"
|
||||
value={remarks}
|
||||
onChange={(e) => setRemarks(e.currentTarget.value)}
|
||||
// withAsterisk
|
||||
readOnly={showOtpField}
|
||||
withAsterisk
|
||||
/>
|
||||
</Group>
|
||||
<Group grow>
|
||||
{showOtpField && (
|
||||
<>
|
||||
<PasswordInput
|
||||
label="OTP"
|
||||
placeholder="Enter OTP"
|
||||
type="otp"
|
||||
value={otp}
|
||||
maxLength={6}
|
||||
onChange={(e) => setOtp(e.currentTarget.value)}
|
||||
withAsterisk
|
||||
disabled={showTxnPassword}
|
||||
/>
|
||||
)}
|
||||
{showTxnPassword && (
|
||||
<TextInput
|
||||
label="Transaction Password"
|
||||
placeholder="Enter transaction password"
|
||||
type="password"
|
||||
value={txnPassword}
|
||||
onChange={(e) => setTxnPassword(e.currentTarget.value)}
|
||||
withAsterisk
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
{!showTxnPassword && (
|
||||
timerActive ? (
|
||||
<Text size="xs" c="dimmed">
|
||||
Resend OTP will be enabled in 00:{countdown < 10 ? `0${countdown}` : countdown} min
|
||||
</Text>
|
||||
) : (
|
||||
<Button
|
||||
variant="subtle"
|
||||
px={8}
|
||||
onClick={handleGenerateOtp}
|
||||
leftSection={<IconRefresh size={16} />}
|
||||
>
|
||||
Resend
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{showTxnPassword && (
|
||||
<TextInput
|
||||
label="Transaction Password"
|
||||
placeholder="Enter transaction password"
|
||||
type="password"
|
||||
value={txnPassword}
|
||||
onChange={(e) => setTxnPassword(e.currentTarget.value)}
|
||||
withAsterisk
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<Group justify="flex-start">
|
||||
<Button variant="filled" color="blue" onClick={handleValidate} disabled={validationStatus === "success"}>
|
||||
Validate
|
||||
</Button>
|
||||
<Button
|
||||
variant="filled"
|
||||
color="blue"
|
||||
onClick={handleProceed}
|
||||
loading={isSubmitting}
|
||||
disabled={validationStatus !== "success"}
|
||||
>
|
||||
{!showTxnPassword && showOtpField ? "Validate the OTP" : showTxnPassword ? "Proceed to Pay" : "Proceed"}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</div>
|
||||
<Group justify="flex-start">
|
||||
<Button variant="filled" color="blue" onClick={handleValidate} disabled={validationStatus === "success"}>
|
||||
Validate
|
||||
</Button>
|
||||
<Button
|
||||
variant="filled"
|
||||
color="blue"
|
||||
onClick={handleProceed}
|
||||
loading={isSubmitting}
|
||||
disabled={validationStatus !== "success"}
|
||||
>
|
||||
{!showTxnPassword && showOtpField ? "Validate the OTP" : showTxnPassword ? "Proceed to Pay" : "Proceed"}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</div>
|
||||
{/* ) : (
|
||||
<div>
|
||||
<OutsideQuickPay />
|
||||
|
@@ -143,7 +143,7 @@ export default function Home() {
|
||||
|
||||
{/* Loan Account Card */}
|
||||
<Paper p="md" radius="md" style={{
|
||||
backgroundColor: '#c1e0f0', width: 350, height: 195, display: 'flex',
|
||||
backgroundColor: '#c1e0f0', width: 355, height: 195, display: 'flex',
|
||||
flexDirection: 'column', justifyContent: 'space-between'
|
||||
}}
|
||||
>
|
||||
|
@@ -5,7 +5,7 @@ import { IconBook, IconCurrencyRupee, IconHome, IconLogout, IconPhoneFilled, Ico
|
||||
import Link from 'next/link';
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
import { Providers } from '../providers';
|
||||
import logo from '@/app/image/logo.jpg';
|
||||
import logo from '@/app/image/logo1.jpg';
|
||||
import NextImage from 'next/image';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
async function handleFetchUserName() {
|
||||
try {
|
||||
const token = localStorage.getItem("access_token");
|
||||
const response = await fetch('api/customer', {
|
||||
const response = await fetch('/api/customer', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -67,7 +67,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
async function handleFetchUserDetails(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
const token = localStorage.getItem("access_token");
|
||||
const response = await fetch('api/auth/user_details', {
|
||||
const response = await fetch('/api/auth/user_details', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -124,7 +124,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
width: '100%',
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
background: "linear-gradient(15deg,rgba(2, 163, 85, 1) 55%, rgba(101, 101, 184, 1) 100%)",
|
||||
background: "linear-gradient(15deg,rgba(10, 114, 40, 1) 55%, rgba(101, 101, 184, 1) 100%)",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
@@ -134,6 +134,19 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
alt="ebanking"
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
/>
|
||||
<Title
|
||||
order={2}
|
||||
style={{
|
||||
fontFamily: 'Roboto',
|
||||
position: 'absolute',
|
||||
top: '30%',
|
||||
left: '6%',
|
||||
color: 'White',
|
||||
transition: "opacity 0.5s ease-in-out",
|
||||
}}
|
||||
>
|
||||
THE KANGRA CENTRAL CO-OPERATIVE BANK LTD.
|
||||
</Title>
|
||||
<Text
|
||||
style={{
|
||||
position: 'absolute',
|
||||
@@ -173,7 +186,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
<Link key={item.href} href={item.href}>
|
||||
<Button
|
||||
leftSection={<Icon size={20} />}
|
||||
variant={isActive ? "light" : "subtle"}
|
||||
variant={isActive ? "dark" : "subtle"}
|
||||
color={isActive ? "blue" : undefined}
|
||||
>
|
||||
{item.label}
|
||||
@@ -213,7 +226,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
}}
|
||||
>
|
||||
<Text c="dimmed" size="xs">
|
||||
© 2025 Kangra Central Co-Operative Bank
|
||||
© 2025 The Kangra Central Co-Operative Bank
|
||||
</Text>
|
||||
</Box>
|
||||
</div>
|
||||
|
@@ -14,7 +14,7 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { IconEye, IconEyeOff, IconLock } from "@tabler/icons-react";
|
||||
import CaptchaImage from "@/app/SetPassword/CaptchaImage";
|
||||
// import CaptchaImage from "@/app/SetPassword/CaptchaImage";
|
||||
import { generateCaptcha } from "@/app/captcha";
|
||||
|
||||
const ChangePassword: React.FC = () => {
|
||||
@@ -193,7 +193,7 @@ const ChangePassword: React.FC = () => {
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 5 }}>
|
||||
{/* CAPTCHA Image */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', height: 30 }}>
|
||||
<CaptchaImage text={captcha} />
|
||||
{/* <CaptchaImage text={captcha} /> */}
|
||||
</div>
|
||||
|
||||
{/* Refresh Button */}
|
||||
|
@@ -38,7 +38,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
<Stack style={{ background: '#228be6', height: '10%', alignItems: 'center' }}>
|
||||
<Text fw={700} fs="italic" c='white' style={{ textAlign: 'center', marginTop: '10px' }}>
|
||||
<Text fw={700} c='white' style={{ textAlign: 'center', marginTop: '10px' }}>
|
||||
Settings
|
||||
</Text>
|
||||
</Stack>
|
||||
|
Reference in New Issue
Block a user