diff --git a/src/App.tsx b/src/App.tsx
index f1f5aa2..585b205 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,6 +3,7 @@ import './App.css';
import { LanguageManager } from './components/LanguageManager';
import { AuthenticationPage } from './features/authorization/routes/AuthenticationPage';
import { BrowserRouter, Navigate, Route, Routes } from 'react-router';
+import { ForgetPasswordPage } from './features/authorization/routes/ForgetPasswordPage';
function App() {
return (
@@ -13,6 +14,7 @@ function App() {
} />
} />
+ } />
,
diff --git a/src/features/authorization/api/authorizationAPI.ts b/src/features/authorization/api/authorizationAPI.ts
index 290a736..47a8786 100644
--- a/src/features/authorization/api/authorizationAPI.ts
+++ b/src/features/authorization/api/authorizationAPI.ts
@@ -77,7 +77,7 @@ export const sendForgetPassCode = async (body: SendForgetPassCodeRequest) => {
return fetchRequest('User/SendForgetPassCode', body);
};
-export const ConfirmForgetPassCode = async (
+export const confirmForgetPassCode = async (
body: ConfirmForgetPassCodeRequest,
) => {
return fetchRequest('User/ConfirmForgetPassCode', body);
diff --git a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx
index ccfc6c1..8d8d496 100644
--- a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx
+++ b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx
@@ -7,7 +7,7 @@ import { CompleteSignUp } from './CompleteSignUp';
import { EnterPasswordForm } from './EnterPasswordForm';
import { getUserStatusByPhoneNumberOrEmail } from '../../api/authorizationAPI';
import { UserStatus } from '../../types/userTypes';
-import type { CountryCode } from '@/types/commonTypes';
+import type { CountryCode, GUID } from '@/types/commonTypes';
import { VerifyPhoneNumber } from './VerifyPhoneNumber';
export const AuthenticationSteps = (): JSX.Element => {
@@ -48,7 +48,11 @@ export const AuthenticationSteps = (): JSX.Element => {
}
};
- const handleOTPVerfied = (registeredWithoutPhoneNumber: boolean = false) => {
+ const handleOTPVerfied = (
+ registeredWithoutPhoneNumber: boolean = false,
+ userId: GUID,
+ ) => {
+ localStorage.setItem('userID', userId);
// if (registeredWithoutPhoneNumber) {
// setCurrentStep('addPhoneNumber');
// }
diff --git a/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx b/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx
index 748f7e9..776f96b 100644
--- a/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx
+++ b/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx
@@ -13,7 +13,7 @@ import {
sendEmailOtp,
sendSmsOtp,
} from '../../api/authorizationAPI';
-import type { CountryCode } from '@/types/commonTypes';
+import type { CountryCode, GUID } from '@/types/commonTypes';
interface OtpVerifyFormProps {
value: string;
@@ -21,7 +21,7 @@ interface OtpVerifyFormProps {
authType: AuthType;
authMode: AuthMode;
onEditValue: () => void;
- onOTPVerified: (registeredWithoutPhoneNumber: boolean) => void;
+ onOTPVerified: (registeredWithoutPhoneNumber: boolean, userID: GUID) => void;
}
export function OtpVerifyForm({
@@ -104,7 +104,7 @@ export function OtpVerifyForm({
if (jsonRes.success) {
setVerifyStatus('success');
- onOTPVerified(jsonRes.registeredWithOutPhoneNumber);
+ onOTPVerified(jsonRes.registeredWithOutPhoneNumber, jsonRes.userId);
} else {
setVerifyStatus('failed');
setErrorMessage(jsonRes.message);
diff --git a/src/features/authorization/components/ForgetPassword/ChangePassword.tsx b/src/features/authorization/components/ForgetPassword/ChangePassword.tsx
index a83732b..27877a8 100644
--- a/src/features/authorization/components/ForgetPassword/ChangePassword.tsx
+++ b/src/features/authorization/components/ForgetPassword/ChangePassword.tsx
@@ -23,17 +23,25 @@ import { containsNumber } from '@/utils/regexes/containsNumber';
import { containsSymbol } from '@/utils/regexes/containsSymbol';
import { least8Chars } from '@/utils/regexes/least8Chars';
import { hasUpperAndLowerLetter } from '@/utils/regexes/hasUpperAndLowerLetter';
+import type { ResetPasswordRequest } from '../../types/userTypes';
+import type { AuthType } from '../../types/authTypes';
+import type { CountryCode } from '@/types/commonTypes';
+import { resetPassword } from '../../api/authorizationAPI';
export interface ChangePasswordProps {
onEditInfo: () => void;
onPasswordChanged: () => void;
forgettedPasswordInfo: string;
+ infoType: AuthType;
+ countryCode: CountryCode;
}
export const ChangePassword = ({
onEditInfo,
onPasswordChanged,
forgettedPasswordInfo,
+ infoType,
+ countryCode,
}: ChangePasswordProps) => {
const theme = useTheme();
const { t } = useTranslation('authentication');
@@ -75,7 +83,7 @@ export const ChangePassword = ({
setConfirmInputTouched(true);
};
- const handleSubmit = () => {
+ const handleSubmit = async () => {
if (!passValue || !isValidPassword(passValue)) {
setInputTouched(true);
inputRef.current?.focus();
@@ -85,15 +93,29 @@ export const ChangePassword = ({
} else {
setChangePasswordLoading(true);
- // Change setTimeout to api call
- setTimeout(() => {
- setChangePassAlertOpen(true);
- // setLoginStatus('success');
- // setLoginStatus('failed');
- // setLoginFailedMessage('رمز عبور اشتباه میباشد');
+ const apiRequest: ResetPasswordRequest = {
+ email: infoType === 'email' ? forgettedPasswordInfo : undefined,
+ phoneNumber:
+ infoType === 'phone'
+ ? countryCode + forgettedPasswordInfo
+ : undefined,
+ newPassword: passValue,
+ confirmNewPassword: confirmPassValue,
+ };
+
+ const result = await resetPassword(apiRequest);
+ const jsonRes = await result.json();
+
+ if (jsonRes.success) {
+ setChangePasswordStatus('success');
onPasswordChanged();
- setChangePasswordLoading(false);
- }, 1000);
+ } else {
+ setChangePasswordStatus('failed');
+ setChangePassFailedMessage(jsonRes.message);
+ }
+ setChangePassAlertOpen(true);
+
+ setChangePasswordLoading(false);
}
};
diff --git a/src/features/authorization/components/ForgetPassword/ForgetPasswordContainer.tsx b/src/features/authorization/components/ForgetPassword/ForgetPasswordContainer.tsx
index a8112fb..a980bed 100644
--- a/src/features/authorization/components/ForgetPassword/ForgetPasswordContainer.tsx
+++ b/src/features/authorization/components/ForgetPassword/ForgetPasswordContainer.tsx
@@ -3,6 +3,7 @@ import type { AuthType } from '../../types/authTypes';
import { ForgettedPasswordInfo } from './ForgettedPasswordInfo';
import { ForgetPasswordOtp } from './ForgetPasswordOtp';
import { ChangePassword } from './ChangePassword';
+import type { CountryCode } from '@/types/commonTypes';
export const ForgetPasswordContainer = () => {
const [forgetPassCurrentStep, setForgetPassCurrentStep] = useState<
@@ -10,10 +11,10 @@ export const ForgetPasswordContainer = () => {
>('enterInfo');
const [forgettedPasswordInfo, setForgettedPasswordInfo] =
useState('');
+ const [infoCountryCode, setInfoCountryCode] = useState('+98');
const [infoType, setInfoType] = useState('email');
- const handleSendForgetPassOtp = (value: string) => {
- console.log(value);
+ const handleVerifyOtp = (value: string) => {
setForgetPassCurrentStep('verifyOtp');
};
@@ -37,12 +38,15 @@ export const ForgetPasswordContainer = () => {
setInfoType={setInfoType}
forgettedPasswordInfo={forgettedPasswordInfo}
setForgettedPasswordInfo={setForgettedPasswordInfo}
- onSendOtp={handleSendForgetPassOtp}
+ onVerifyOtp={handleVerifyOtp}
+ countryCode={infoCountryCode}
+ setCountryCode={setInfoCountryCode}
/>
)}
{forgetPassCurrentStep === 'verifyOtp' && (
{
onEditInfo={handleEditInfo}
forgettedPasswordInfo={forgettedPasswordInfo}
onPasswordChanged={handlePasswordChanged}
+ infoType={infoType}
+ countryCode={infoCountryCode}
/>
)}
>
diff --git a/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx b/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx
index 62c81cb..275a79a 100644
--- a/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx
+++ b/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx
@@ -6,10 +6,14 @@ import type { AuthMode, AuthType } from '../../types/authTypes';
import { useEffect, useState } from 'react';
import { Toast } from '@/components/Toast';
import { AuthenticationCard } from '../AuthenticationCard';
+import type { ConfirmForgetPassCodeRequest } from '../../types/userTypes';
+import type { CountryCode } from '@/types/commonTypes';
+import { confirmForgetPassCode } from '../../api/authorizationAPI';
interface ForgetPasswordOtpProps {
forgettedPasswordInfo: string;
infoType: AuthType;
+ countryCode: CountryCode;
onEditInfo: () => void;
onOTPVerified: (otpCode: string) => void;
}
@@ -17,6 +21,7 @@ interface ForgetPasswordOtpProps {
export function ForgetPasswordOtp({
forgettedPasswordInfo,
infoType,
+ countryCode,
onEditInfo,
onOTPVerified,
}: ForgetPasswordOtpProps) {
@@ -25,7 +30,7 @@ export function ForgetPasswordOtp({
const [verifyStatus, setVerifyStatus] = useState<'failed' | 'success'>();
const [verifyStatusLoading, setVerifyStatusLoading] =
useState(false);
- const [verifyAlertOpen, setVerifyAlertOpen] = useState(false);
+ const [verifyAlertMessage, setVerifyAlertMessage] = useState();
const { t } = useTranslation('authentication');
const [resendTimer, setResendTimer] = useState(120);
const [canResend, setCanResend] = useState(false);
@@ -70,7 +75,7 @@ export function ForgetPasswordOtp({
setOtpCode(formattedValue);
};
- const handleVerifyOTP = () => {
+ const handleVerifyOTP = async () => {
if (!otpCode || otpCode.length < 4) {
setOtpDigitInvalid(true);
} else {
@@ -78,11 +83,25 @@ export function ForgetPasswordOtp({
setVerifyStatusLoading(true);
// Change setTimeout to api call
- setTimeout(() => {
- setVerifyAlertOpen(false);
+ const apiRequest: ConfirmForgetPassCodeRequest = {
+ email: infoType === 'email' ? forgettedPasswordInfo : undefined,
+ phoneNumber:
+ infoType === 'phone'
+ ? countryCode + forgettedPasswordInfo
+ : undefined,
+ code: otpCode,
+ };
+
+ const result = await confirmForgetPassCode(apiRequest);
+ const jsonRes = await result.json();
+
+ if (jsonRes.success) {
onOTPVerified(otpCode);
- setVerifyStatusLoading(false);
- }, 1000);
+ } else {
+ setVerifyAlertMessage(jsonRes.message);
+ }
+
+ setVerifyStatusLoading(false);
}
};
@@ -90,11 +109,11 @@ export function ForgetPasswordOtp({
setVerifyAlertOpen(false)}
+ open={!!verifyAlertMessage}
+ onClose={() => setVerifyAlertMessage(undefined)}
color={'error'}
>
- {t('verify.theVerificationCodeIsIncorrect')}
+ {verifyAlertMessage}
;
infoType: AuthType;
setInfoType: Dispatch;
- onSendOtp: (value: string) => void;
+ onVerifyOtp: (value: string) => void;
+ countryCode: CountryCode;
+ setCountryCode: Dispatch;
}
export function ForgettedPasswordInfo({
@@ -29,15 +35,18 @@ export function ForgettedPasswordInfo({
setForgettedPasswordInfo,
infoType,
setInfoType,
- onSendOtp,
+ onVerifyOtp,
+ countryCode,
+ setCountryCode,
}: ForgettedPasswordInfoProps) {
const { t, i18n } = useTranslation('authentication');
- const [countryCode, setCountryCode] = useState('+98');
const textFieldRef = useRef(null);
const inputRef = useRef(null);
const dir = i18n.dir();
const [error, setError] = useState();
const [touched, setTouched] = useState(false);
+ const [errorMessage, setErrorMessage] = useState();
+ const [sendCodeLoading, setSendCodeLoading] = useState(false);
const inputError: boolean = touched && !!error;
const handleInputChange = (event: React.ChangeEvent) => {
@@ -75,25 +84,42 @@ export function ForgettedPasswordInfo({
return phoneNumber && phoneNumber.isValid();
};
- const isInputValid = (value: string, authType: AuthType): boolean => {
+ const isInputValid = (value: string, infoType: AuthType): boolean => {
if (!value) {
return false;
}
- if (authType === 'email' && !isEmail(value)) {
+ if (infoType === 'email' && !isEmail(value)) {
return false;
}
- if (authType === 'phone' && !isPhoneValid(countryCode, value)) {
+ if (infoType === 'phone' && !isPhoneValid(countryCode, value)) {
return false;
}
return true;
};
- const handleSubmit = () => {
+ const handleSubmit = async () => {
if (isInputValid(forgettedPasswordInfo, infoType)) {
- onSendOtp(forgettedPasswordInfo);
+ setSendCodeLoading(true);
+
+ const sendCodeRequest: SendForgetPassCodeRequest = {
+ email: infoType === 'email' ? forgettedPasswordInfo : undefined,
+ phoneNumber:
+ infoType === 'phone'
+ ? countryCode + forgettedPasswordInfo
+ : undefined,
+ };
+ const result = await sendForgetPassCode(sendCodeRequest);
+ const jsonRes = await result.json();
+
+ if (!jsonRes.success) {
+ setErrorMessage(jsonRes.message);
+ }
+
+ setSendCodeLoading(false);
+ onVerifyOtp(forgettedPasswordInfo);
} else {
inputRef.current?.focus();
validateInput(forgettedPasswordInfo, infoType);
@@ -105,6 +131,14 @@ export function ForgettedPasswordInfo({
return (
+ setErrorMessage(undefined)}
+ open={!!errorMessage}
+ >
+ {errorMessage}
+
+
{t('forgetPassword.forgetPassword')}
@@ -144,7 +178,9 @@ export function ForgettedPasswordInfo({
/>
-
+
);
diff --git a/src/features/authorization/routes/ForgetPasswordPage.tsx b/src/features/authorization/routes/ForgetPasswordPage.tsx
new file mode 100644
index 0000000..d30290e
--- /dev/null
+++ b/src/features/authorization/routes/ForgetPasswordPage.tsx
@@ -0,0 +1,23 @@
+import { FlexBox } from '@/components/components/common/FlexBox';
+import Logo from '@/components/Logo';
+import { Paper } from '@mui/material';
+import { useState } from 'react';
+import { AuthenticationSteps } from '../components/AuthenticationSteps/AuthenticationSteps';
+import { ForgetPasswordContainer } from '../components/ForgetPassword/ForgetPasswordContainer';
+
+export function ForgetPasswordPage() {
+ return (
+
+
+
+
+ );
+}
diff --git a/src/features/authorization/types/userTypes.ts b/src/features/authorization/types/userTypes.ts
index 74b5e1d..4f0a8eb 100644
--- a/src/features/authorization/types/userTypes.ts
+++ b/src/features/authorization/types/userTypes.ts
@@ -86,8 +86,8 @@ export interface SendForgetPassCodeRequest {
// ConfirmForgetPassCode
export interface ConfirmForgetPassCodeRequest {
- email: string;
- phoneNumber: string;
+ email?: string;
+ phoneNumber?: string;
code: string;
}