updated forget password functionality with backend

This commit is contained in:
2025-08-23 14:29:25 +05:30
parent c86509e812
commit 1018c42500
10 changed files with 519 additions and 247 deletions

View File

@@ -38,11 +38,13 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
const handleCreateNewProject = async () => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken")
console.log('refreshToken: ', refreshToken);
const refreshToken = localStorage.getItem("refreshToken");
console.log("refreshToken: ", refreshToken);
try {
const projectId = generateProjectId();
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
useSocketStore
.getState()
.initializeSocket(email, organization, token, refreshToken);
//API for creating new Project
// const project = await createProject(
@@ -59,12 +61,12 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
projectUuid: projectId,
};
console.log('projectSocket: ', projectSocket);
console.log("projectSocket: ", projectSocket);
if (projectSocket) {
const handleResponse = (data: any) => {
if (data.message === "Project created successfully") {
setLoadingProgress(1)
navigate(`/${data.data.projectId}`);
setLoadingProgress(1);
navigate(`/projects/${data.data.projectId}`);
}
projectSocket.off("v1-project:response:add", handleResponse); // Clean up
};
@@ -88,7 +90,8 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
</div>
<div className="user-name">
{userName
? userName.charAt(0).toUpperCase() + userName.slice(1).toLowerCase()
? userName.charAt(0).toUpperCase() +
userName.slice(1).toLowerCase()
: "Anonymous"}
</div>
</div>
@@ -162,10 +165,14 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
<SettingsIcon />
Settings
</div>
<div className="option-list" style={{ cursor: "pointer" }} onClick={() => {
localStorage.clear();
navigate("/");
}}>
<div
className="option-list"
style={{ cursor: "pointer" }}
onClick={() => {
localStorage.clear();
navigate("/");
}}
>
<LogoutIcon />
Log out
</div>
@@ -179,4 +186,4 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
);
};
export default SidePannel;
export default SidePannel;

View File

@@ -1,30 +1,39 @@
import React from 'react';
import React from "react";
interface Props {
email: string;
setEmail: (value: string) => void;
onSubmit: () => void;
email: string;
setEmail: (value: string) => void;
onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
}
const EmailInput: React.FC<Props> = ({ email, setEmail, onSubmit }) => {
return (
<div className='request-container'>
<h1 className='header'>Forgot password</h1>
<p className='sub-header'>
Enter your email for the verification process, we will send a 4-digit code to your email.
</p>
<form className='auth-form' onSubmit={(e) => { e.preventDefault(); onSubmit(); }}>
<input
type='email'
placeholder='Email'
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<button type='submit' className='continue-button'>Continue</button>
</form>
</div>
);
return (
<div className="request-container">
<h1 className="header">Forgot password</h1>
<p className="sub-header">
Enter your email for the verification process, we will send a 4-digit
code to your email.
</p>
<form
className="auth-form"
onSubmit={(e) => {
e.preventDefault();
onSubmit(e);
}}
>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<button type="submit" className="continue-button">
Continue
</button>
</form>
</div>
);
};
export default EmailInput;

View File

@@ -1,10 +1,95 @@
import React, { useState, useRef, useEffect } from 'react';
// import React, { useState, useRef, useEffect } from "react";
const OTPInput: React.FC<{ length?: number; onComplete: (otp: string) => void }> = ({ length = 4, onComplete }) => {
const [otpValues, setOtpValues] = useState<string[]>(Array(length).fill(''));
// const OTPInput: React.FC<{
// length?: number;
// onComplete: (otp: string) => void;
// code: string;
// }> = ({ length = 4, onComplete, code }) => {
// const [otpValues, setOtpValues] = useState<string[]>(Array(length).fill(""));
// const inputsRef = useRef<(HTMLInputElement | null)[]>([]);
// useEffect(() => {
// if (code) {
// console.log("code: ", code);
// const codeString = String(code); // convert number → string
// setOtpValues(codeString.split(""));
// onComplete(codeString);
// }
// }, [code, length]);
// // Auto focus first input on mount
// useEffect(() => {
// inputsRef.current[0]?.focus();
// }, []);
// const handleChange = (value: string, index: number) => {
// if (/^[0-9]?$/.test(value)) {
// const newOtp = [...otpValues];
// newOtp[index] = value;
// setOtpValues(newOtp);
// if (value && index < length - 1) {
// inputsRef.current[index + 1]?.focus();
// }
// if (newOtp.every((digit) => digit !== "")) {
// console.log('newOtp.join(""): ', newOtp.join(""));
// onComplete(newOtp.join(""));
// }
// }
// };
// const handleKeyDown = (
// e: React.KeyboardEvent<HTMLInputElement>,
// index: number
// ) => {
// if (e.key === "Backspace" && !otpValues[index] && index > 0) {
// inputsRef.current[index - 1]?.focus();
// }
// };
// return (
// <div className="otp-container">
// {otpValues.map((value, index) => (
// <input
// key={index}
// type="text"
// className="otp-input"
// maxLength={1}
// value={value}
// onChange={(e) => handleChange(e.target.value, index)}
// onKeyDown={(e) => handleKeyDown(e, index)}
// ref={(el) => (inputsRef.current[index] = el)}
// />
// ))}
// </div>
// );
// };
// export default OTPInput;
import React, { useState, useRef, useEffect } from "react";
const OTPInput: React.FC<{
length?: number;
onComplete: (otp: string) => void;
code: string | number;
}> = ({ length = 4, onComplete, code }) => {
const [otpValues, setOtpValues] = useState<string[]>(Array(length).fill(""));
const inputsRef = useRef<(HTMLInputElement | null)[]>([]);
// Auto focus first input on mount
// ✅ Pre-fill inputs if code is passed
useEffect(() => {
if (code) {
const codeString = String(code);
const filled = codeString.split("").slice(0, length);
const padded = filled.concat(Array(length - filled.length).fill(""));
setOtpValues(padded);
if (filled.length === length) {
onComplete(filled.join(""));
}
}
}, [code, length, onComplete]);
// ✅ Focus first input on mount
useEffect(() => {
inputsRef.current[0]?.focus();
}, []);
@@ -19,14 +104,18 @@ const OTPInput: React.FC<{ length?: number; onComplete: (otp: string) => void }>
inputsRef.current[index + 1]?.focus();
}
if (newOtp.every((digit) => digit !== '')) {
onComplete(newOtp.join(''));
// ✅ Only trigger onComplete when all digits are filled
if (newOtp.every((digit) => digit !== "")) {
onComplete(newOtp.join(""));
}
}
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => {
if (e.key === 'Backspace' && !otpValues[index] && index > 0) {
const handleKeyDown = (
e: React.KeyboardEvent<HTMLInputElement>,
index: number
) => {
if (e.key === "Backspace" && !otpValues[index] && index > 0) {
inputsRef.current[index - 1]?.focus();
}
};
@@ -39,7 +128,7 @@ const OTPInput: React.FC<{ length?: number; onComplete: (otp: string) => void }>
type="text"
className="otp-input"
maxLength={1}
value={value}
value={value ?? ""}
onChange={(e) => handleChange(e.target.value, index)}
onKeyDown={(e) => handleKeyDown(e, index)}
ref={(el) => (inputsRef.current[index] = el)}

View File

@@ -1,57 +1,77 @@
import React, { useState } from 'react';
import OTPInput from './OTPInput';
import React, { FormEvent, useState } from "react";
import OTPInput from "./OTPInput";
interface Props {
email: string;
timer: number;
setCode: (value: string) => void;
onSubmit: () => void;
resendCode: () => void;
email: string;
code: string;
timer: number;
setCode: (value: string) => void;
onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
resendCode: () => void;
}
const OTPVerification: React.FC<Props> = ({ email, timer, setCode, onSubmit, resendCode }) => {
const [otp, setOtp] = useState('');
const OTPVerification: React.FC<Props> = ({
email,
timer,
setCode,
onSubmit,
resendCode,
code,
}) => {
const [otp, setOtp] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log('otp.length: ', otp.length);
if (otp.length === 4) {
onSubmit();
} else {
alert('Please enter the 4-digit code');
}
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
return (
<div className='request-container'>
<h1 className='header'>Verification</h1>
<p className='sub-header'>
Enter the 4-digit code sent to <strong>{email}</strong>.
</p>
<form className='auth-form' onSubmit={handleSubmit}>
<OTPInput length={4} onComplete={(code) => { setOtp(code); setCode(code); }} />
<div className="timing">
{timer > 0
? `${String(Math.floor(timer / 60)).padStart(2, '0')}:${String(timer % 60).padStart(2, '0')}`
: ''}
</div>
<button
type='submit'
className='continue-button'
disabled={otp.length < 4} // prevent clicking if not complete
>
Verify
</button>
</form>
<div
className={`resend ${timer > 0 ? 'disabled' : ''}`}
onClick={timer === 0 ? resendCode : undefined}
style={{ cursor: timer === 0 ? 'pointer' : 'not-allowed', opacity: timer === 0 ? 1 : 0.5 }}
>
If you didnt receive a code, <span>Resend</span>
</div>
if (otp.length === 4) {
onSubmit(e);
} else {
alert("Please enter the 4-digit code");
}
};
return (
<div className="request-container">
<h1 className="header">Verification</h1>
<p className="sub-header">
Enter the 4-digit code sent to <strong>{email}</strong>.
</p>
<form className="auth-form" onSubmit={handleSubmit}>
<OTPInput
length={4}
onComplete={(codes) => {
setOtp(code);
setCode(codes);
}}
code={code}
/>
<div className="timing">
{timer > 0
? `${String(Math.floor(timer / 60)).padStart(2, "0")}:${String(
timer % 60
).padStart(2, "0")}`
: ""}
</div>
);
<button
type="submit"
className="continue-button"
// disabled={otp.length < 4} // prevent clicking if not complete
>
Verify
</button>
</form>
<div
className={`resend ${timer > 0 ? "disabled" : ""}`}
onClick={timer === 0 ? resendCode : undefined}
style={{
cursor: timer === 0 ? "pointer" : "not-allowed",
opacity: timer === 0 ? 1 : 0.5,
}}
>
If you didnt receive a code, <span>Resend</span>
</div>
</div>
);
};
export default OTPVerification;

View File

@@ -1,77 +1,82 @@
import React, { useState } from 'react';
import { EyeIcon } from '../icons/ExportCommonIcons';
import React, { useState } from "react";
import { EyeIcon } from "../icons/ExportCommonIcons";
interface Props {
newPassword: string;
confirmPassword: string;
setNewPassword: (value: string) => void;
setConfirmPassword: (value: string) => void;
onSubmit: () => void;
newPassword: string;
confirmPassword: string;
setNewPassword: (value: string) => void;
setConfirmPassword: (value: string) => void;
onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
}
const PasswordSetup: React.FC<Props> = ({
newPassword,
confirmPassword,
setNewPassword,
setConfirmPassword,
onSubmit
newPassword,
confirmPassword,
setNewPassword,
setConfirmPassword,
onSubmit,
}) => {
const [showNewPassword, setShowNewPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [showNewPassword, setShowNewPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
return (
<div className='request-container'>
<h1 className='header'>New Password</h1>
<p className='sub-header'>Set the new password for your account so you can login and access all features.</p>
<form
className='auth-form'
onSubmit={(e) => {
e.preventDefault();
if (newPassword !== confirmPassword) {
alert('Passwords do not match');
return;
}
onSubmit();
}}
>
<div className="password-container">
<input
type={showNewPassword ? 'text' : 'password'}
placeholder='Enter new password'
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
required
/>
<button
type="button"
className="toggle-password"
onClick={() => setShowNewPassword(prev => !prev)}
>
<EyeIcon isClosed={!showNewPassword} />
</button>
</div>
<div className="password-container">
<input
type={showConfirmPassword ? 'text' : 'password'}
placeholder='Confirm password'
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
/>
<button
type="button"
className="toggle-password"
onClick={() => setShowConfirmPassword(prev => !prev)}
>
<EyeIcon isClosed={!showConfirmPassword} />
</button>
</div>
<button type='submit' className='continue-button'>Update password</button>
</form>
return (
<div className="request-container">
<h1 className="header">New Password</h1>
<p className="sub-header">
Set the new password for your account so you can login and access all
features.
</p>
<form
className="auth-form"
onSubmit={(e) => {
e.preventDefault();
if (newPassword !== confirmPassword) {
alert("Passwords do not match");
return;
}
onSubmit(e);
}}
>
<div className="password-container">
<input
type={showNewPassword ? "text" : "password"}
placeholder="Enter new password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
required
/>
<button
type="button"
className="toggle-password"
onClick={() => setShowNewPassword((prev) => !prev)}
>
<EyeIcon isClosed={!showNewPassword} />
</button>
</div>
);
<div className="password-container">
<input
type={showConfirmPassword ? "text" : "password"}
placeholder="Confirm password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
/>
<button
type="button"
className="toggle-password"
onClick={() => setShowConfirmPassword((prev) => !prev)}
>
<EyeIcon isClosed={!showConfirmPassword} />
</button>
</div>
<button type="submit" className="continue-button">
Update password
</button>
</form>
</div>
);
};
export default PasswordSetup;

View File

@@ -1,92 +1,134 @@
import React, { useState, useEffect } from 'react';
import { LogoIconLarge } from '../components/icons/Logo';
import EmailInput from '../components/forgotPassword/EmailInput';
import OTPVerification from '../components/forgotPassword/OTP_Verification';
import PasswordSetup from '../components/forgotPassword/PasswordSetup';
import ConfirmationMessage from '../components/forgotPassword/ConfirmationMessgae';
import React, { useState, useEffect, FormEvent } from "react";
import { LogoIconLarge } from "../components/icons/Logo";
import EmailInput from "../components/forgotPassword/EmailInput";
import OTPVerification from "../components/forgotPassword/OTP_Verification";
import PasswordSetup from "../components/forgotPassword/PasswordSetup";
import ConfirmationMessage from "../components/forgotPassword/ConfirmationMessgae";
import { changePasswordApi } from "../services/factoryBuilder/signInSignUp/changePasswordApi";
import { checkEmailApi } from "../services/factoryBuilder/signInSignUp/checkEmailApi";
import { verifyOtpApi } from "../services/factoryBuilder/signInSignUp/verifyOtpApi";
const ForgotPassword: React.FC = () => {
const [step, setStep] = useState(1);
const [email, setEmail] = useState('');
const [code, setCode] = useState('');
const [newPassword, setNewPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [timer, setTimer] = useState(30);
const [step, setStep] = useState(1);
const [email, setEmail] = useState("");
const [code, setCode] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [timer, setTimer] = useState(30);
const [resetToken, setResetToken] = useState("");
useEffect(() => {
let countdown: NodeJS.Timeout;
if (step === 2 && timer > 0) {
countdown = setTimeout(() => setTimer(prev => prev - 1), 1000);
}
return () => clearTimeout(countdown);
}, [step, timer]);
const handleSubmitEmail = () => {
setStep(2);
setTimer(30);
useEffect(() => {
let countdown: NodeJS.Timeout;
if (step === 2 && timer > 0) {
countdown = setTimeout(() => setTimer((prev) => prev - 1), 1000);
}
const resendCode = () => {
// TODO: call API to resend code
setTimer(30);
};
return () => clearTimeout(countdown);
}, [step, timer]);
return (
<div className='forgot-password-page auth-container'>
<div className='forgot-password-wrapper'>
<div className='logo-icon'>
<LogoIconLarge />
</div>
const resendCode = async () => {
// TODO: call API to resend code
setTimer(30);
try {
const emailResponse = await checkEmailApi(email);
if (emailResponse.message == "OTP sent Successfully") {
setCode(emailResponse.OTP);
}
} catch {}
};
const handleEmailSubmit = async (e: FormEvent<HTMLFormElement>) => {
setTimer(30);
try {
const emailResponse = await checkEmailApi(email);
{step === 1 && (
<>
<EmailInput
email={email}
setEmail={setEmail}
onSubmit={handleSubmitEmail}
/>
<a href='/' className='login continue-button'>Login</a>
</>
if (emailResponse.message == "OTP sent Successfully") {
setStep(2);
setCode(emailResponse.OTP);
}
} catch {}
};
)}
const handleOTPSubmit = async (e: FormEvent<HTMLFormElement>) => {
try {
const otpResponse = await verifyOtpApi(email, Number(code));
if (otpResponse.message == "OTP verified successfully") {
setResetToken(otpResponse.resetToken);
setStep(3);
} else {
alert(otpResponse.message);
}
} catch {}
};
{step === 2 && (
<>
<OTPVerification
email={email}
timer={timer}
setCode={setCode}
onSubmit={() => setStep(3)}
resendCode={resendCode}
/>
<a href='/' className='login'>Login</a>
</>
const handlePasswordSubmit = async (e: FormEvent<HTMLFormElement>) => {
try {
const passwordResponse = await changePasswordApi(
resetToken,
newPassword,
confirmPassword
);
if (passwordResponse.message === "Password reset successfull!!") {
setStep(4);
}
} catch {}
};
)}
{step === 3 && (
<>
<PasswordSetup
newPassword={newPassword}
confirmPassword={confirmPassword}
setNewPassword={setNewPassword}
setConfirmPassword={setConfirmPassword}
onSubmit={() => setStep(4)}
/>
<a href='/' className='login'>Login</a>
</>
)}
{step === 4 && <ConfirmationMessage />}
</div>
return (
<div className="forgot-password-page auth-container">
<div className="forgot-password-wrapper">
<div className="logo-icon">
<LogoIconLarge />
</div>
);
{step === 1 && (
<>
<EmailInput
email={email}
setEmail={setEmail}
onSubmit={handleEmailSubmit}
/>
<a href="/" className="login continue-button">
Login
</a>
</>
)}
{step === 2 && (
<>
<OTPVerification
code={code}
email={email}
timer={timer}
setCode={setCode}
onSubmit={handleOTPSubmit}
resendCode={resendCode}
/>
<a href="/" className="login">
Login
</a>
</>
)}
{step === 3 && (
<>
<PasswordSetup
newPassword={newPassword}
confirmPassword={confirmPassword}
setNewPassword={setNewPassword}
setConfirmPassword={setConfirmPassword}
onSubmit={handlePasswordSubmit}
/>
<a href="/" className="login">
Login
</a>
</>
)}
{step === 4 && <ConfirmationMessage />}
</div>
</div>
);
};
export default ForgotPassword;

View File

@@ -34,7 +34,7 @@ const UserAuth: React.FC = () => {
useEffect(() => {
initializeFingerprint();
}, [])
}, []);
const { userId, organization } = getUserData();
@@ -47,7 +47,6 @@ const UserAuth: React.FC = () => {
setError("");
setOrganization(organization);
setUserName(res.message.name);
// console.log(' res.userId: ', res.message.userId);
localStorage.setItem("userId", res.message.userId);
localStorage.setItem("email", res.message.email);
localStorage.setItem("userName", res.message.name);
@@ -55,33 +54,46 @@ const UserAuth: React.FC = () => {
localStorage.setItem("refreshToken", res.message.refreshToken);
try {
const projects = await recentlyViewed(organization, res.message.userId);
const projects = await recentlyViewed(
organization,
res.message.userId
);
if (res.message.isShare) {
if (Object.values(projects.RecentlyViewed).length > 0) {
const recent_opend_projectID = (Object.values(projects?.RecentlyViewed || {})[0] as any)?._id;
if (Object.values(projects?.RecentlyViewed).filter((val: any) => val._id == recent_opend_projectID)) {
setLoadingProgress(1)
navigate(`/projects/${recent_opend_projectID}`)
const recent_opend_projectID = (
Object.values(projects?.RecentlyViewed || {})[0] as any
)?._id;
if (
Object.values(projects?.RecentlyViewed).filter(
(val: any) => val._id == recent_opend_projectID
)
) {
setLoadingProgress(1);
navigate(`/projects/${recent_opend_projectID}`);
} else {
navigate("/Dashboard")
navigate("/Dashboard");
}
} else {
setLoadingProgress(1);
navigate("/Dashboard");
}
}
} catch (error) {
console.error("Error fetching recent projects:", error);
}
} else if (res.message === "User Not Found!!! Kindly signup...") {
setError("Account not found");
} else if (res.message === "Email & Password is invalid...Check the credentials") {
setError(res.message)
} else if (res.message === "Already LoggedIn on another browser....Please logout!!!") {
} else if (
res.message === "Email & Password is invalid...Check the credentials"
) {
setError(res.message);
} else if (
res.message ===
"Already LoggedIn on another browser....Please logout!!!"
) {
setError("Already logged in on another browser. Please logout first.");
navigate("/");
setError("")
setError("");
// setError("");
// setOrganization(organization);
// setUserName(res.ForceLogoutData.userName);
@@ -179,6 +191,7 @@ const UserAuth: React.FC = () => {
name="email"
value={email}
placeholder="Email"
autoComplete="email"
onChange={(e) => setEmail(e.target.value)}
required
/>
@@ -188,6 +201,7 @@ const UserAuth: React.FC = () => {
type={showPassword ? "text" : "password"}
value={password}
placeholder="Password"
autoComplete="current-password"
onChange={(e) => setPassword(e.target.value)}
required
/>
@@ -201,7 +215,11 @@ const UserAuth: React.FC = () => {
</button>
</div>
{isSignIn && <a href="forgot" className="forgot-password">Forgot password ?</a>}
{isSignIn && (
<a href="forgot" className="forgot-password">
Forgot password ?
</a>
)}
{!isSignIn && (
<div className="policy-checkbox">

View File

@@ -0,0 +1,29 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const changePasswordApi = async (
resetToken: string,
newPassword: string,
confirmPassword: string
) => {
try {
const response = await fetch(
`${url_Backend_dwinzo}/api/V1/Auth/reset-password/${resetToken}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ newPassword, confirmPassword }),
}
);
const result = await response.json();
return result;
} catch (error) {
echo.error("Failed to create password");
if (error instanceof Error) {
return { error: error.message };
} else {
return { error: "An unknown error occurred" };
}
}
};

View File

@@ -0,0 +1,25 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const checkEmailApi = async (Email: string) => {
try {
const response = await fetch(
`${url_Backend_dwinzo}/api/V1/Auth/forgetPassword`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ Email }),
}
);
const result = await response.json();
return result;
} catch (error) {
echo.error("Failed to create password");
if (error instanceof Error) {
return { error: error.message };
} else {
return { error: "An unknown error occurred" };
}
}
};

View File

@@ -0,0 +1,28 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const verifyOtpApi = async (Email: string, Otp: number) => {
try {
const response = await fetch(
`${url_Backend_dwinzo}/api/V1/Auth/validate-otp`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
Email,
otp: Number(Otp),
}),
}
);
const result = await response.json();
return result;
} catch (error) {
echo.error("Failed to create password");
if (error instanceof Error) {
return { error: error.message };
} else {
return { error: "An unknown error occurred" };
}
}
};