added icon
This commit is contained in:
parent
a58b4a2535
commit
d76f59284b
@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="" href="/assets/images/image.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>IIP Survey Platform</title>
|
<title>IIP Survey Platform</title>
|
||||||
<style>
|
<style>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
if (self === top) {
|
if (self === top) {
|
||||||
document.documentElement.style.display = 'block';
|
document.documentElement.style.display = 'block';
|
||||||
@ -23,4 +23,4 @@
|
|||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.jsx"></script>
|
<script type="module" src="/src/main.jsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
BIN
ipi-survey-platform/public/assets/images/image.png
Normal file
BIN
ipi-survey-platform/public/assets/images/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 803 B |
@ -4,28 +4,28 @@ import { useNavigate, useLocation } from 'react-router-dom';
|
|||||||
import { AlertCircle, Clock, CheckCircle } from "lucide-react";
|
import { AlertCircle, Clock, CheckCircle } from "lucide-react";
|
||||||
|
|
||||||
const logoSrc = '/assets/images/FCSCLogo.svg';
|
const logoSrc = '/assets/images/FCSCLogo.svg';
|
||||||
|
|
||||||
const OTPVerification = () => {
|
const OTPVerification = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const [otp, setOtp] = useState(['', '', '', '', '', '']);
|
const [otp, setOtp] = useState(['', '', '', '', '', '']);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [toast, setToast] = useState(null);
|
const [toast, setToast] = useState(null);
|
||||||
const [resendDisabled, setResendDisabled] = useState(false);
|
const [resendDisabled, setResendDisabled] = useState(false);
|
||||||
const [countdown, setCountdown] = useState(600);
|
const [countdown, setCountdown] = useState(600);
|
||||||
const [attemptsRemaining, setAttemptsRemaining] = useState(3);
|
const [attemptsRemaining, setAttemptsRemaining] = useState(3);
|
||||||
|
|
||||||
const inputRefs = useRef(Array(6).fill(null).map(() => React.createRef()));
|
const inputRefs = useRef(Array(6).fill(null).map(() => React.createRef()));
|
||||||
const toastTimeoutRef = useRef(null);
|
const toastTimeoutRef = useRef(null);
|
||||||
const countdownRef = useRef(null);
|
const countdownRef = useRef(null);
|
||||||
|
|
||||||
// Get email from location state or use a default
|
// Get email from location state or use a default
|
||||||
const maskedEmail = location.state?.email ?
|
const maskedEmail = location.state?.email ?
|
||||||
`${location.state.email.split('@')[0].substring(0, 2)}***@${location.state.email.split('@')[1]}` :
|
`${location.state.email.split('@')[0].substring(0, 2)}***@${location.state.email.split('@')[1]}` :
|
||||||
'na***@company.com';
|
'na***@company.com';
|
||||||
|
|
||||||
// Toast handling
|
// Toast handling
|
||||||
const closeToast = useCallback(() => {
|
const closeToast = useCallback(() => {
|
||||||
if (toastTimeoutRef.current) {
|
if (toastTimeoutRef.current) {
|
||||||
@ -34,7 +34,7 @@ const OTPVerification = () => {
|
|||||||
}
|
}
|
||||||
setToast(null);
|
setToast(null);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const showToast = useCallback((type, message) => {
|
const showToast = useCallback((type, message) => {
|
||||||
if (!message) return;
|
if (!message) return;
|
||||||
if (toastTimeoutRef.current) {
|
if (toastTimeoutRef.current) {
|
||||||
@ -47,24 +47,24 @@ const OTPVerification = () => {
|
|||||||
toastTimeoutRef.current = null;
|
toastTimeoutRef.current = null;
|
||||||
}, 4000);
|
}, 4000);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Handle OTP input change
|
// Handle OTP input change
|
||||||
const handleOtpChange = (e, index) => {
|
const handleOtpChange = (e, index) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
|
|
||||||
// Only allow numbers and limit to 1 character
|
// Only allow numbers and limit to 1 character
|
||||||
if (value && !/^\d*$/.test(value)) return;
|
if (value && !/^\d*$/.test(value)) return;
|
||||||
|
|
||||||
const newOtp = [...otp];
|
const newOtp = [...otp];
|
||||||
newOtp[index] = value.slice(-1);
|
newOtp[index] = value.slice(-1);
|
||||||
setOtp(newOtp);
|
setOtp(newOtp);
|
||||||
|
|
||||||
// Move to next input if there's a value and we're not on the last input
|
// Move to next input if there's a value and we're not on the last input
|
||||||
if (value && index < 5 && inputRefs.current[index + 1]?.current) {
|
if (value && index < 5 && inputRefs.current[index + 1]?.current) {
|
||||||
inputRefs.current[index + 1].current.focus();
|
inputRefs.current[index + 1].current.focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle backspace
|
// Handle backspace
|
||||||
const handleKeyDown = (e, index) => {
|
const handleKeyDown = (e, index) => {
|
||||||
if (e.key === 'Backspace' && !otp[index] && index > 0 && inputRefs.current[index - 1]?.current) {
|
if (e.key === 'Backspace' && !otp[index] && index > 0 && inputRefs.current[index - 1]?.current) {
|
||||||
@ -72,7 +72,7 @@ const OTPVerification = () => {
|
|||||||
inputRefs.current[index - 1].current.focus();
|
inputRefs.current[index - 1].current.focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle paste
|
// Handle paste
|
||||||
const handlePaste = (e) => {
|
const handlePaste = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -82,40 +82,40 @@ const OTPVerification = () => {
|
|||||||
setOtp([...newOtp, ...Array(6 - newOtp.length).fill('')]);
|
setOtp([...newOtp, ...Array(6 - newOtp.length).fill('')]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle verify OTP
|
// Handle verify OTP
|
||||||
const handleVerify = async (e) => {
|
const handleVerify = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const otpValue = otp.join('');
|
const otpValue = otp.join('');
|
||||||
|
|
||||||
if (otpValue.length !== 6) {
|
if (otpValue.length !== 6) {
|
||||||
setError('Please enter a valid 6-digit code');
|
setError('Please enter a valid 6-digit code');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError('');
|
setError('');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await verifyOtp({
|
const response = await verifyOtp({
|
||||||
registered_email: location.state?.email,
|
registered_email: location.state?.email,
|
||||||
otp: otpValue
|
otp: otpValue
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response?.status === 'success') {
|
if (response?.status === 'success') {
|
||||||
// Show success message immediately
|
// Show success message immediately
|
||||||
showToast('success', 'Verified! You are signed in. Redirecting to your dashboard.');
|
showToast('success', 'Verified! You are signed in. Redirecting to your dashboard.');
|
||||||
|
|
||||||
// Get the user role from the most reliable source
|
// Get the user role from the most reliable source
|
||||||
const userRole = response?.data?.user?.role ||
|
const userRole = response?.data?.user?.role ||
|
||||||
response?.data?.role ||
|
response?.data?.role ||
|
||||||
localStorage.getItem('user_role');
|
localStorage.getItem('user_role');
|
||||||
|
|
||||||
// Set the role in localStorage if not already set
|
// Set the role in localStorage if not already set
|
||||||
if (userRole && !localStorage.getItem('user_role')) {
|
if (userRole && !localStorage.getItem('user_role')) {
|
||||||
localStorage.setItem('user_role', userRole);
|
localStorage.setItem('user_role', userRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update user profile in local storage with OTP verification status
|
// Update user profile in local storage with OTP verification status
|
||||||
try {
|
try {
|
||||||
const userProfile = JSON.parse(localStorage.getItem('user_profile') || '{}');
|
const userProfile = JSON.parse(localStorage.getItem('user_profile') || '{}');
|
||||||
@ -128,22 +128,22 @@ const OTPVerification = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to update user profile:', error);
|
console.error('Failed to update user profile:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the appropriate dashboard based on user role
|
// Determine the appropriate dashboard based on user role
|
||||||
let redirectPath = '/dashboard';
|
let redirectPath = '/dashboard';
|
||||||
|
|
||||||
// Check if user is admin (case-insensitive check)
|
// Check if user is admin (case-insensitive check)
|
||||||
if (userRole && userRole.toLowerCase() === 'admin') {
|
if (userRole && userRole.toLowerCase() === 'admin') {
|
||||||
redirectPath = '/admin/dashboard';
|
redirectPath = '/admin/dashboard';
|
||||||
console.log('Admin user detected, redirecting to admin dashboard');
|
console.log('Admin user detected, redirecting to admin dashboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's a saved path from before login, use that
|
// If there's a saved path from before login, use that
|
||||||
const savedPath = location.state?.from?.pathname;
|
const savedPath = location.state?.from?.pathname;
|
||||||
if (savedPath) {
|
if (savedPath) {
|
||||||
redirectPath = savedPath;
|
redirectPath = savedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect after a short delay
|
// Redirect after a short delay
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -152,20 +152,20 @@ const OTPVerification = () => {
|
|||||||
} else {
|
} else {
|
||||||
throw new Error(response?.message || 'Invalid OTP');
|
throw new Error(response?.message || 'Invalid OTP');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('OTP verification failed', err);
|
console.error('OTP verification failed', err);
|
||||||
const errorMessage = err.response?.data?.message ||
|
const errorMessage = err.response?.data?.message ||
|
||||||
err.message ||
|
err.message ||
|
||||||
'An error occurred during OTP verification. Please try again.';
|
'An error occurred during OTP verification. Please try again.';
|
||||||
|
|
||||||
const newAttempts = attemptsRemaining - 1;
|
const newAttempts = attemptsRemaining - 1;
|
||||||
setAttemptsRemaining(newAttempts);
|
setAttemptsRemaining(newAttempts);
|
||||||
|
|
||||||
// Set the error message for incorrect OTP
|
// Set the error message for incorrect OTP
|
||||||
const displayError = errorMessage || 'Invalid verification code';
|
const displayError = errorMessage || 'Invalid verification code';
|
||||||
setError(displayError);
|
setError(displayError);
|
||||||
|
|
||||||
if (newAttempts <= 0) {
|
if (newAttempts <= 0) {
|
||||||
setOtp(Array(6).fill(''));
|
setOtp(Array(6).fill(''));
|
||||||
// Show error message and redirect to login after a short delay
|
// Show error message and redirect to login after a short delay
|
||||||
@ -184,76 +184,76 @@ const OTPVerification = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle resend OTP
|
// Handle resend OTP
|
||||||
const handleResend = async () => {
|
const handleResend = async () => {
|
||||||
if (resendDisabled) return;
|
if (resendDisabled) return;
|
||||||
|
|
||||||
// Show loading state immediately
|
// Show loading state immediately
|
||||||
setResendDisabled(true);
|
setResendDisabled(true);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Call the API to resend OTP
|
// Call the API to resend OTP
|
||||||
const response = await requestOtp(location.state?.email);
|
const response = await requestOtp(location.state?.email);
|
||||||
|
|
||||||
// Update state and show success toast immediately
|
// Update state and show success toast immediately
|
||||||
const tenMinutesInSeconds = 10 * 60;
|
const tenMinutesInSeconds = 10 * 60;
|
||||||
setCountdown(tenMinutesInSeconds);
|
setCountdown(tenMinutesInSeconds);
|
||||||
setAttemptsRemaining(3);
|
setAttemptsRemaining(3);
|
||||||
setError('');
|
setError('');
|
||||||
setOtp(Array(6).fill(''));
|
setOtp(Array(6).fill(''));
|
||||||
|
|
||||||
// Use setTimeout to ensure the toast shows up in the next tick
|
// Use setTimeout to ensure the toast shows up in the next tick
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showToast('success', response.message || 'A new OTP has been sent to your email.');
|
showToast('success', response.message || 'A new OTP has been sent to your email.');
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error resending OTP:', error);
|
console.error('Error resending OTP:', error);
|
||||||
showToast('error', 'An error occurred while sending OTP. Please try again.');
|
showToast('error', 'An error occurred while sending OTP. Please try again.');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
// Re-enable resend after 60 seconds
|
// Re-enable resend after 60 seconds
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
setResendDisabled(false);
|
setResendDisabled(false);
|
||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
// Cleanup timer on component unmount
|
// Cleanup timer on component unmount
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start countdown on component mount
|
// Start countdown on component mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Always use 10 minutes for the countdown
|
// Always use 10 minutes for the countdown
|
||||||
const tenMinutesInMs = 10 * 60 * 1000;
|
const tenMinutesInMs = 10 * 60 * 1000;
|
||||||
const expiryTime = Date.now() + tenMinutesInMs;
|
const expiryTime = Date.now() + tenMinutesInMs;
|
||||||
|
|
||||||
const updateCountdown = () => {
|
const updateCountdown = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const remainingSeconds = Math.max(0, Math.floor((expiryTime - now) / 1000));
|
const remainingSeconds = Math.max(0, Math.floor((expiryTime - now) / 1000));
|
||||||
|
|
||||||
setCountdown(remainingSeconds);
|
setCountdown(remainingSeconds);
|
||||||
|
|
||||||
if (remainingSeconds <= 0) {
|
if (remainingSeconds <= 0) {
|
||||||
clearInterval(countdownRef.current);
|
clearInterval(countdownRef.current);
|
||||||
setResendDisabled(false);
|
setResendDisabled(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initial update
|
// Initial update
|
||||||
updateCountdown();
|
updateCountdown();
|
||||||
|
|
||||||
// Set up interval for countdown updates
|
// Set up interval for countdown updates
|
||||||
countdownRef.current = setInterval(updateCountdown, 1000);
|
countdownRef.current = setInterval(updateCountdown, 1000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (countdownRef.current) clearInterval(countdownRef.current);
|
if (countdownRef.current) clearInterval(countdownRef.current);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Cleanup on unmount
|
// Cleanup on unmount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@ -261,10 +261,10 @@ const OTPVerification = () => {
|
|||||||
if (countdownRef.current) clearInterval(countdownRef.current);
|
if (countdownRef.current) clearInterval(countdownRef.current);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const minutes = Math.floor(countdown / 60);
|
const minutes = Math.floor(countdown / 60);
|
||||||
const seconds = countdown % 60;
|
const seconds = countdown % 60;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#F7F7F7] flex items-center justify-center px-4">
|
<div className="min-h-screen bg-[#F7F7F7] flex items-center justify-center px-4">
|
||||||
{/* Toast Notification */}
|
{/* Toast Notification */}
|
||||||
@ -297,7 +297,7 @@ const OTPVerification = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="w-full max-w-md">
|
<div className="w-full max-w-md">
|
||||||
<div className="bg-white rounded-lg shadow-sm ring-1 ring-gray-200 overflow-hidden">
|
<div className="bg-white rounded-lg shadow-sm ring-1 ring-gray-200 overflow-hidden">
|
||||||
{/* Logo Section */}
|
{/* Logo Section */}
|
||||||
@ -309,13 +309,13 @@ const OTPVerification = () => {
|
|||||||
IIP (Index of Industrial Production)
|
IIP (Index of Industrial Production)
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-7">
|
<div className="p-7">
|
||||||
{/* <div className="text-center mb-6">
|
{/* <div className="text-center mb-6">
|
||||||
<h2 className="text-xl font-bold text-gray-800">Email OTP</h2>
|
<h2 className="text-xl font-bold text-gray-800">Email OTP</h2>
|
||||||
<p className="text-gray-600 mt-1">Step 2 of 2</p>
|
<p className="text-gray-600 mt-1">Step 2 of 2</p>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
<form onSubmit={handleVerify}>
|
<form onSubmit={handleVerify}>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
@ -324,7 +324,7 @@ const OTPVerification = () => {
|
|||||||
We sent a 6-digit authentication code to <span className="font-medium">{maskedEmail}</span>
|
We sent a 6-digit authentication code to <span className="font-medium">{maskedEmail}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* OTP Inputs */}
|
{/* OTP Inputs */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-center space-x-3">
|
<div className="flex justify-center space-x-3">
|
||||||
@ -341,8 +341,8 @@ const OTPVerification = () => {
|
|||||||
onKeyDown={(e) => handleKeyDown(e, index)}
|
onKeyDown={(e) => handleKeyDown(e, index)}
|
||||||
onPaste={handlePaste}
|
onPaste={handlePaste}
|
||||||
className={`w-12 h-12 text-center text-xl bg-transparent border-2 rounded focus:outline-none focus:ring-0 ${
|
className={`w-12 h-12 text-center text-xl bg-transparent border-2 rounded focus:outline-none focus:ring-0 ${
|
||||||
error ? 'border-red-500' :
|
error ? 'border-red-500' :
|
||||||
digit ? 'border-[#92722A]' :
|
digit ? 'border-[#92722A]' :
|
||||||
'border-gray-300 hover:border-gray-400 focus:border-[#92722A] focus:border-b-2 focus:border-b-[#92722A]'
|
'border-gray-300 hover:border-gray-400 focus:border-[#92722A] focus:border-b-2 focus:border-b-[#92722A]'
|
||||||
}`}
|
}`}
|
||||||
autoFocus={index === 0}
|
autoFocus={index === 0}
|
||||||
@ -350,14 +350,14 @@ const OTPVerification = () => {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
<div className="text-red-600 text-sm flex items-center justify-center">
|
<div className="text-red-600 text-sm flex items-center justify-center">
|
||||||
<AlertCircle className="h-4 w-4 mr-1" />
|
<AlertCircle className="h-4 w-4 mr-1" />
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex justify-between items-center text-sm text-gray-600">
|
<div className="flex justify-between items-center text-sm text-gray-600">
|
||||||
<div className="flex items-center space-x-2 leading-none">
|
<div className="flex items-center space-x-2 leading-none">
|
||||||
<Clock className="h-4 w-4 flex-shrink-0 -mt-0.5" />
|
<Clock className="h-4 w-4 flex-shrink-0 -mt-0.5" />
|
||||||
@ -365,10 +365,10 @@ const OTPVerification = () => {
|
|||||||
Code expires in {minutes}:{seconds < 10 ? `0${seconds}` : seconds}
|
Code expires in {minutes}:{seconds < 10 ? `0${seconds}` : seconds}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span>Attempts: {attemptsRemaining}/3</span>
|
<span>Attempts: {attemptsRemaining} of 3</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
@ -388,7 +388,7 @@ const OTPVerification = () => {
|
|||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -404,12 +404,12 @@ const OTPVerification = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div className="mt-6 pt-6 border-t border-gray-200 text-center">
|
<div className="mt-6 pt-6 border-t border-gray-200 text-center">
|
||||||
|
|
||||||
<p className="mt-2 text-sm text-gray-600">
|
<p className="mt-2 text-sm text-gray-600">
|
||||||
Having trouble?{' '}
|
Having trouble?{' '}
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate('/')}
|
onClick={() => navigate('/')}
|
||||||
className="text-[#92722A] hover:text-[#7a5e23] font-medium focus:outline-none"
|
className="text-[#92722A] hover:text-[#7a5e23] font-medium focus:outline-none"
|
||||||
>
|
>
|
||||||
@ -423,5 +423,5 @@ const OTPVerification = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OTPVerification;
|
export default OTPVerification;
|
||||||
Loading…
Reference in New Issue
Block a user