diff --git a/src/App.tsx b/src/App.tsx index 585b205..a463dc1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,8 +12,8 @@ function App() { - } /> - } /> + } /> + } /> } /> diff --git a/src/features/authorization/api/authorizationAPI.ts b/src/features/authorization/api/authorizationAPI.ts index 47a8786..25175e7 100644 --- a/src/features/authorization/api/authorizationAPI.ts +++ b/src/features/authorization/api/authorizationAPI.ts @@ -12,6 +12,7 @@ import type { LoginOrSignUpWithGoogleResponse, LoginRequest, LoginResponse, + PasswordLoginRequest, ResetPasswordRequest, ResetPasswordResponse, SendEmailOtpRequest, @@ -49,7 +50,7 @@ export const loginOrSignUpWithOtp = async (body: LoginRequest) => { return fetchRequest('User/LoginOrSignUpWithOtp', body); }; -export const loginWithPassword = async (body: LoginRequest) => { +export const loginWithPassword = async (body: PasswordLoginRequest) => { return fetchRequest('User/LoginWithPassword', body); }; diff --git a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx index 8d8d496..c61f104 100644 --- a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx +++ b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx @@ -5,7 +5,11 @@ import { OtpVerifyForm } from './OtpVerifyForm'; import { isNumeric } from '@/utils/regexes/isNumeric'; import { CompleteSignUp } from './CompleteSignUp'; import { EnterPasswordForm } from './EnterPasswordForm'; -import { getUserStatusByPhoneNumberOrEmail } from '../../api/authorizationAPI'; +import { + getUserStatusByPhoneNumberOrEmail, + sendEmailOtp, + sendSmsOtp, +} from '../../api/authorizationAPI'; import { UserStatus } from '../../types/userTypes'; import type { CountryCode, GUID } from '@/types/commonTypes'; import { VerifyPhoneNumber } from './VerifyPhoneNumber'; @@ -51,11 +55,16 @@ export const AuthenticationSteps = (): JSX.Element => { const handleOTPVerfied = ( registeredWithoutPhoneNumber: boolean = false, userId: GUID, + returnUrl?: string, ) => { localStorage.setItem('userID', userId); // if (registeredWithoutPhoneNumber) { // setCurrentStep('addPhoneNumber'); // } + + if (returnUrl) { + location.href = returnUrl; + } }; const handleEditValue = () => { @@ -74,7 +83,17 @@ export const AuthenticationSteps = (): JSX.Element => { setCurrentStep('emailOrPhone'); }; - const handleLoggedInWithPassowrd = () => {}; + const handleLoggedInWithPassowrd = (userId: GUID, returnUrl?: string) => { + localStorage.setItem('userID', userId); + + if (returnUrl) { + location.href = returnUrl; + } + }; + + const handleLoginWithOtpInsteadOfPassword = async () => { + setCurrentStep('verify'); + }; return ( <> @@ -103,9 +122,12 @@ export const AuthenticationSteps = (): JSX.Element => { {currentStep === 'enterPassword' && ( setCurrentStep('verify')} + onLoginWithOTP={handleLoginWithOtpInsteadOfPassword} emailOrPhone={loginRegisterValue} /> )} diff --git a/src/features/authorization/components/AuthenticationSteps/EnterPasswordForm.tsx b/src/features/authorization/components/AuthenticationSteps/EnterPasswordForm.tsx index 579a551..d7418ac 100644 --- a/src/features/authorization/components/AuthenticationSteps/EnterPasswordForm.tsx +++ b/src/features/authorization/components/AuthenticationSteps/EnterPasswordForm.tsx @@ -11,12 +11,24 @@ import { } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { Toast } from '@/components/Toast'; +import { Link, Navigate, useSearchParams } from 'react-router'; +import type { AuthType } from '../../types/authTypes'; +import type { CountryCode, GUID } from '@/types/commonTypes'; +import { + loginWithPassword, + sendEmailOtp, + sendSmsOtp, +} from '../../api/authorizationAPI'; +import type { LoginRequest, PasswordLoginRequest } from '../../types/userTypes'; export interface EnterPasswordFormProps { onEditValue: () => void; onLoginWithOTP: () => void; - onLoggedIn: () => void; + onLoggedIn: (userId: GUID, returnUrl?: string) => void; emailOrPhone: string; + authType: AuthType; + loginRegisterValue: string; + countryCode: CountryCode; } export const EnterPasswordForm = ({ @@ -24,7 +36,12 @@ export const EnterPasswordForm = ({ onLoginWithOTP, onLoggedIn, emailOrPhone, + authType, + loginRegisterValue, + countryCode, }: EnterPasswordFormProps) => { + const DEFAULT_RETURN_URL = 'https://account.business-harmony.com/'; + const [searchParams] = useSearchParams(); const { t } = useTranslation('authentication'); const [passValue, setPassValue] = useState(''); const [inputTouched, setInputTouched] = useState(false); @@ -34,29 +51,53 @@ export const EnterPasswordForm = ({ const [loginStatus, setLoginStatus] = useState<'success' | 'failed'>(); const [loginAlertOpen, setLoginAlertOpen] = useState(false); const [loginFailedMessage, setLoginFailedMessage] = useState(''); + const [sendOtpLoading, setSendOtpLoading] = useState(false); const handleBlur = () => { setInputTouched(true); }; - const handleSubmit = () => { + const handleSubmit = async () => { if (!passValue) { inputRef.current?.focus(); } else { setLoginLoading(true); - // Change setTimeout to api call - setTimeout(() => { - setLoginAlertOpen(true); - // setLoginStatus('success'); + const apiRequest: PasswordLoginRequest = { + phoneNumber: + authType === 'phone' ? countryCode + loginRegisterValue : undefined, + email: authType === 'email' ? loginRegisterValue : undefined, + password: passValue, + returnUrl: searchParams.get('returnUrl') ?? DEFAULT_RETURN_URL, + }; + const result = await loginWithPassword(apiRequest); + const jsonRes = await result.json(); + + if (jsonRes.success) { + setLoginStatus('success'); + onLoggedIn(jsonRes.userId, jsonRes.returnUrl); + } else { setLoginStatus('failed'); - setLoginFailedMessage('رمز عبور اشتباه میباشد'); - onLoggedIn(); - setLoginLoading(false); - }, 1000); + setLoginFailedMessage(jsonRes.message); + } + setLoginAlertOpen(true); + setLoginLoading(false); } }; + const handleLoginWithOtp = async () => { + setSendOtpLoading(true); + + if (authType === 'phone') { + await sendSmsOtp({ phoneNumber: countryCode + loginRegisterValue }); + } else { + await sendEmailOtp({ email: loginRegisterValue }); + } + + setSendOtpLoading(false); + onLoginWithOTP(); + }; + return ( - + + + ); diff --git a/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx b/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx index 776f96b..3c37714 100644 --- a/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx +++ b/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx @@ -21,7 +21,11 @@ interface OtpVerifyFormProps { authType: AuthType; authMode: AuthMode; onEditValue: () => void; - onOTPVerified: (registeredWithoutPhoneNumber: boolean, userID: GUID) => void; + onOTPVerified: ( + registeredWithoutPhoneNumber: boolean, + userID: GUID, + returnUrl?: string, + ) => void; } export function OtpVerifyForm({ @@ -32,6 +36,7 @@ export function OtpVerifyForm({ onEditValue, onOTPVerified, }: OtpVerifyFormProps) { + const DEFAULT_RETURN_URL = 'https://account.business-harmony.com/'; const [searchParams] = useSearchParams(); const [otpCode, setOtpCode] = useState(''); const [otpDigitInvalid, setOtpDigitInvalid] = useState(false); @@ -97,14 +102,18 @@ export function OtpVerifyForm({ otpCode: otpCode, phoneNumber: authType === 'phone' ? countryCode + value : undefined, email: authType === 'email' ? value : undefined, - returnUrl: searchParams.get('returnUrl') ?? '/', + returnUrl: searchParams.get('returnUrl') ?? DEFAULT_RETURN_URL, }; const result = await loginOrSignUpWithOtp(loginRequest); const jsonRes = await result.json(); if (jsonRes.success) { setVerifyStatus('success'); - onOTPVerified(jsonRes.registeredWithOutPhoneNumber, jsonRes.userId); + onOTPVerified( + jsonRes.registeredWithOutPhoneNumber, + jsonRes.userId, + jsonRes.returnUrl, + ); } 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 27877a8..b4b35dd 100644 --- a/src/features/authorization/components/ForgetPassword/ChangePassword.tsx +++ b/src/features/authorization/components/ForgetPassword/ChangePassword.tsx @@ -241,7 +241,7 @@ export const ChangePassword = ({ color="primary" onClick={() => setShowConfirmPassword(!showConfirmPassword)} > - {showPassword ? : } + {showConfirmPassword ? : } ) : ( '' diff --git a/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx b/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx index 275a79a..5f50a7f 100644 --- a/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx +++ b/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx @@ -137,7 +137,9 @@ export function ForgetPasswordOtp({ endIcon={} onClick={onEditInfo} > - {forgettedPasswordInfo} + {infoType === 'phone' + ? countryCode + forgettedPasswordInfo + : forgettedPasswordInfo} diff --git a/src/features/authorization/types/userTypes.ts b/src/features/authorization/types/userTypes.ts index 4f0a8eb..22d974d 100644 --- a/src/features/authorization/types/userTypes.ts +++ b/src/features/authorization/types/userTypes.ts @@ -28,6 +28,13 @@ export interface LoginRequest { returnUrl: string; } +export interface PasswordLoginRequest { + phoneNumber?: string; + email?: string; + password: string; + returnUrl: string; +} + export interface LoginResponse extends ApiResponse { returnUrl: string; userId: GUID;