setup of IB
This commit is contained in:
195
src/app/login/otp/page.tsx
Normal file
195
src/app/login/otp/page.tsx
Normal file
@@ -0,0 +1,195 @@
|
||||
"use client"
|
||||
|
||||
import classes from '../page.module.css';
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { TextInput, Button, Container, Title, Image, SimpleGrid, LoadingOverlay, Avatar, Paper, Text, Group, Center } from "@mantine/core";
|
||||
import image from '../helpdesk.png';
|
||||
import { useForm, SubmitHandler } from "react-hook-form";
|
||||
import axios, { AxiosError } from "axios";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
|
||||
|
||||
type OtpInput = {
|
||||
OTP: number
|
||||
}
|
||||
|
||||
type Result = {
|
||||
ok?: boolean
|
||||
message?: string
|
||||
}
|
||||
|
||||
async function handleResendOTP() {
|
||||
let otp;
|
||||
try {
|
||||
const response = await axios.get("/api/otp");
|
||||
otp = response.data;
|
||||
console.log('OTP resent successfully:', response.data);
|
||||
// Object.assign(response.data);
|
||||
// alert(response.data.message);
|
||||
notifications.show({
|
||||
color: 'green',
|
||||
// title: error.code,
|
||||
message: response.data.message
|
||||
})
|
||||
} catch (error: AxiosError | any) {
|
||||
notifications.show({
|
||||
color: 'red',
|
||||
title: error.code,
|
||||
message: error.message
|
||||
})
|
||||
}
|
||||
return otp;
|
||||
}
|
||||
|
||||
|
||||
async function handleValidateOTP(OtpInput: OtpInput) {
|
||||
let Result: Result = { ok: false }
|
||||
try {
|
||||
const response = await axios.post("/api/otp", OtpInput);
|
||||
{
|
||||
window.location.href = '/home'
|
||||
}
|
||||
Object.assign(Result, response.data);
|
||||
} catch (error: AxiosError | any) {
|
||||
// alert(error.response.data.error);
|
||||
notifications.show({
|
||||
withBorder: true,
|
||||
color: 'red',
|
||||
title: error.response.status,
|
||||
message: error.response.data.error,
|
||||
autoClose: 4000,
|
||||
})
|
||||
}
|
||||
// For countdown reset every time after successful verification
|
||||
sessionStorage.removeItem('countdown');
|
||||
sessionStorage.removeItem('timerStart');
|
||||
return Result;
|
||||
}
|
||||
|
||||
export default function CheckOTP() {
|
||||
const queryClient = useQueryClient();
|
||||
const { register, handleSubmit, formState: { errors } } = useForm<OtpInput>();
|
||||
const [countdown, setCountdown] = useState<number>(90);
|
||||
const [timerActive, setTimerActive] = useState<boolean>(true);
|
||||
|
||||
const validateOTPMutation = useMutation<Result, AxiosError, OtpInput>({
|
||||
mutationKey: ['validateOtp'],
|
||||
mutationFn: handleValidateOTP,
|
||||
})
|
||||
const resendOTPMutation = useQuery({
|
||||
queryKey: ['resendOTP'],
|
||||
queryFn: handleResendOTP,
|
||||
enabled: false,
|
||||
})
|
||||
////
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const savedCountdown = sessionStorage.getItem('countdown');
|
||||
const savedStartTime = sessionStorage.getItem('timerStart');
|
||||
|
||||
if (savedCountdown && savedStartTime) {
|
||||
const elapsedTime = Math.floor((Date.now() - parseInt(savedStartTime, 10)) / 1000);
|
||||
const remainingTime = parseInt(savedCountdown, 10) - elapsedTime;
|
||||
|
||||
if (remainingTime > 0) {
|
||||
setCountdown(remainingTime);
|
||||
setTimerActive(true);
|
||||
}
|
||||
else {
|
||||
setCountdown(0);
|
||||
setTimerActive(false);
|
||||
sessionStorage.removeItem('countdown');
|
||||
sessionStorage.removeItem('timerStart');
|
||||
}
|
||||
} else {
|
||||
sessionStorage.setItem('countdown', '90');
|
||||
sessionStorage.setItem('timerStart', Date.now().toString());
|
||||
setCountdown(90);
|
||||
setTimerActive(true);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Effect to manage the countdown timer
|
||||
useEffect(() => {
|
||||
if (!timerActive) return;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setCountdown((prev) => {
|
||||
if (prev <= 1) {
|
||||
clearInterval(interval);
|
||||
setTimerActive(false);
|
||||
sessionStorage.removeItem('countdown');
|
||||
sessionStorage.removeItem('timerStart');
|
||||
return 0;
|
||||
}
|
||||
return prev - 1;
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval); // Cleanup interval on unmount
|
||||
}, [timerActive]);
|
||||
/////
|
||||
const onSubmit: SubmitHandler<OtpInput> = async (OtpInput) => {
|
||||
const Result = await validateOTPMutation.mutateAsync(OtpInput);
|
||||
if (Result.ok)
|
||||
await queryClient.refetchQueries({ queryKey: ['OTP'] });
|
||||
};
|
||||
|
||||
const handleResend = async () => {
|
||||
resendOTPMutation.refetch();
|
||||
setCountdown(90);
|
||||
setTimerActive(true);
|
||||
sessionStorage.setItem('countdown', '90');
|
||||
sessionStorage.setItem('timerStart', Date.now().toString());
|
||||
}
|
||||
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
|
||||
return (
|
||||
<Container className={classes.root}>
|
||||
<SimpleGrid spacing={{ base: 40, sm: 80 }} cols={{ base: 1, sm: 2 }}>
|
||||
<Image src={image.src} className={classes.mobileImage} />
|
||||
<div>
|
||||
<LoadingOverlay visible={validateOTPMutation.isPending || validateOTPMutation.data?.ok || resendOTPMutation.isLoading} />
|
||||
<Paper component='form' className={classes.form} radius={0} p={30} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Avatar
|
||||
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-ZljkQXsXUP1-EwnIPZtVq_JWhwGUW7b0_eSMno-bag&s"
|
||||
alt="Jacob Warnhalter"
|
||||
radius="xxxl"
|
||||
/>
|
||||
<Title order={2} className={classes.title} ta="center" mt="md" mb={50}>
|
||||
Customer Request Management
|
||||
</Title>
|
||||
<TextInput label="Enter One-time password(OTP) *"
|
||||
placeholder="e.g. XXXXX"
|
||||
size="md"
|
||||
maxLength={6}
|
||||
{...register('OTP', { required: true })} />
|
||||
{errors.OTP && <Text c='red'>*Required</Text>}
|
||||
<Center mt="lg">
|
||||
<Text >{timerActive ? `Resend OTP in ${countdown}s` : 'Resend OTP Available'} </Text>
|
||||
</Center>
|
||||
<Group justify="center">
|
||||
<Button mt="xl" size="md" type='submit' >
|
||||
Validate OTP
|
||||
</Button>
|
||||
{validateOTPMutation.data?.message && <Text c='red' ta='center' pt={30}>{validateOTPMutation.data.message}</Text>}
|
||||
<Button mt="xl" size="md" type='submit' color='blue' onClick={handleResend} disabled={timerActive} >
|
||||
Resend OTP
|
||||
</Button>
|
||||
{/* {resendOTPMutation?.data?.message && <Text c='red' ta='center' pt={30}>{resendOTPMutation.data.message}</Text>} */}
|
||||
</Group>
|
||||
</Paper>
|
||||
</div>
|
||||
<Image src={image.src} className={classes.desktopImage} />
|
||||
</SimpleGrid>
|
||||
<footer justify-content='center' color='green'>Copyright © 2025 Tata Consultancy Services, All rights reserved.</footer>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user