feat: login with password apis added
This commit is contained in:
@@ -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<LoginResponse>('User/LoginOrSignUpWithOtp', body);
|
||||
};
|
||||
|
||||
export const loginWithPassword = async (body: LoginRequest) => {
|
||||
export const loginWithPassword = async (body: PasswordLoginRequest) => {
|
||||
return fetchRequest<LoginResponse>('User/LoginWithPassword', body);
|
||||
};
|
||||
|
||||
|
||||
@@ -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' && (
|
||||
<EnterPasswordForm
|
||||
loginRegisterValue={loginRegisterValue}
|
||||
countryCode={countryCode}
|
||||
authType={authType}
|
||||
onLoggedIn={handleLoggedInWithPassowrd}
|
||||
onEditValue={handleEditValue}
|
||||
onLoginWithOTP={() => setCurrentStep('verify')}
|
||||
onLoginWithOTP={handleLoginWithOtpInsteadOfPassword}
|
||||
emailOrPhone={loginRegisterValue}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -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<string>('');
|
||||
const [inputTouched, setInputTouched] = useState<boolean>(false);
|
||||
@@ -34,29 +51,53 @@ export const EnterPasswordForm = ({
|
||||
const [loginStatus, setLoginStatus] = useState<'success' | 'failed'>();
|
||||
const [loginAlertOpen, setLoginAlertOpen] = useState<boolean>(false);
|
||||
const [loginFailedMessage, setLoginFailedMessage] = useState<string>('');
|
||||
const [sendOtpLoading, setSendOtpLoading] = useState<boolean>(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 (
|
||||
<AuthenticationCard>
|
||||
<Toast
|
||||
@@ -127,9 +168,10 @@ export const EnterPasswordForm = ({
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={onLoginWithOTP}
|
||||
onClick={handleLoginWithOtp}
|
||||
sx={{ width: 'auto', mb: 2 }}
|
||||
variant="text"
|
||||
loading={sendOtpLoading}
|
||||
endIcon={<ArrowLeft />}
|
||||
>
|
||||
{t('enterPassword.loginWithOneTimeCode')}
|
||||
@@ -139,7 +181,9 @@ export const EnterPasswordForm = ({
|
||||
<Button loading={loginLoading} onClick={handleSubmit}>
|
||||
{t('verify.confirmAndLogin')}
|
||||
</Button>
|
||||
<Button variant="text">{t('enterPassword.iForgotMyPassword')}</Button>
|
||||
<Link to="/forget-password">
|
||||
<Button variant="text">{t('enterPassword.iForgotMyPassword')}</Button>
|
||||
</Link>
|
||||
</Stack>
|
||||
</AuthenticationCard>
|
||||
);
|
||||
|
||||
@@ -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<string>('');
|
||||
const [otpDigitInvalid, setOtpDigitInvalid] = useState<boolean>(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);
|
||||
|
||||
@@ -241,7 +241,7 @@ export const ChangePassword = ({
|
||||
color="primary"
|
||||
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
|
||||
>
|
||||
{showPassword ? <Eye /> : <EyeSlash />}
|
||||
{showConfirmPassword ? <Eye /> : <EyeSlash />}
|
||||
</IconButton>
|
||||
) : (
|
||||
''
|
||||
|
||||
@@ -137,7 +137,9 @@ export function ForgetPasswordOtp({
|
||||
endIcon={<Edit2 />}
|
||||
onClick={onEditInfo}
|
||||
>
|
||||
{forgettedPasswordInfo}
|
||||
{infoType === 'phone'
|
||||
? countryCode + forgettedPasswordInfo
|
||||
: forgettedPasswordInfo}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user