feat: complete sign up apis added

This commit is contained in:
مهرزاد قدرتی
2025-08-11 14:19:32 +03:30
parent 1584b7d7a8
commit b8f7221780
4 changed files with 102 additions and 55 deletions

View File

@@ -31,6 +31,8 @@ export const AuthenticationSteps = (): JSX.Element => {
>('emailOrPhone');
const [loginRegisterValue, setLoginRegisterValue] = useState<string>('');
const [countryCode, setCountryCode] = useState<CountryCode>('+98');
const [addPhoneCountryCode, setAddPhoneCountryCode] =
useState<CountryCode>('+98');
const [addedPhoneNumberValue, setAddedPhoneNumberValue] =
useState<string>('');
@@ -57,14 +59,7 @@ export const AuthenticationSteps = (): JSX.Element => {
}
};
const handleOTPVerfied = (
registeredWithoutPhoneNumber: boolean = false,
userId: GUID,
) => {
if (registeredWithoutPhoneNumber) {
setCurrentStep('addPhoneNumber');
}
const handleOTPVerfied = (userId: GUID) => {
handleUserLoggedIn(userId);
};
@@ -92,6 +87,7 @@ export const AuthenticationSteps = (): JSX.Element => {
{currentStep === 'verify' && (
<OtpVerifyForm
onVerifyPhoneNumber={() => setCurrentStep('addPhoneNumber')}
authReturnUrl={authReturnUrl}
countryCode={countryCode}
onOTPVerified={handleOTPVerfied}
@@ -117,6 +113,8 @@ export const AuthenticationSteps = (): JSX.Element => {
{currentStep === 'addPhoneNumber' && (
<CompleteSignUp
countryCode={addPhoneCountryCode}
setCountryCode={setAddPhoneCountryCode}
value={addedPhoneNumberValue}
setValue={setAddedPhoneNumberValue}
email={loginRegisterValue}
@@ -126,9 +124,11 @@ export const AuthenticationSteps = (): JSX.Element => {
{currentStep === 'addedPhoneNumberVerify' && (
<VerifyPhoneNumber
authReturnUrl={authReturnUrl}
countryCode={countryCode}
onEditValue={() => setCurrentStep('emailOrPhone')}
onEditValue={() => setCurrentStep('addPhoneNumber')}
value={addedPhoneNumberValue}
email={loginRegisterValue}
onPhoneNumberVerified={handleUserLoggedIn}
/>
)}

View File

@@ -4,11 +4,15 @@ import React, { useRef, useState, type Dispatch } from 'react';
import { useTranslation } from 'react-i18next';
import { AuthenticationCard } from '../AuthenticationCard';
import { CountryCodeSelector } from '../CountryCodeSelector';
import { sendSmsOtp } from '../../api/authorizationAPI';
import type { CountryCode } from '@/types/commonTypes';
export interface CompleteSignUpProps {
email: string;
value: string;
setValue: Dispatch<string>;
countryCode: CountryCode;
setCountryCode: Dispatch<CountryCode>;
onCompleteSignUp: (countryCode: string, value: string) => void;
}
@@ -16,15 +20,17 @@ export const CompleteSignUp = ({
email,
value,
setValue,
countryCode,
setCountryCode,
onCompleteSignUp,
}: CompleteSignUpProps) => {
const { t } = useTranslation('authentication');
const [countryCode, setCountryCode] = useState('+98');
const [error, setError] = useState<string>();
const textFieldRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const [touched, setTouched] = useState<boolean>(false);
const inputError: boolean = touched && !!error;
const [sendOtpLoading, setSendOtpLoading] = useState<boolean>(false);
const isPhoneValid = (code: string, phone: string) => {
const phoneNumber = parsePhoneNumberFromString(code + phone);
@@ -45,7 +51,7 @@ export const CompleteSignUp = ({
}
};
const handleCompleteSignUp = () => {
const handleCompleteSignUp = async () => {
if (!value) {
setError(t('loginForm.thisFieldIsRequired'));
inputRef.current?.focus();
@@ -55,7 +61,12 @@ export const CompleteSignUp = ({
inputRef.current?.focus();
} else {
setError(undefined);
setSendOtpLoading(true);
await sendSmsOtp({ phoneNumber: countryCode + value });
onCompleteSignUp(countryCode, value);
setSendOtpLoading(false);
}
};
@@ -99,7 +110,7 @@ export const CompleteSignUp = ({
sx={{ my: 4 }}
/>
<Button onClick={handleCompleteSignUp}>
<Button loading={sendOtpLoading} onClick={handleCompleteSignUp}>
{t('verify.confirmAndContinue')}
</Button>
</AuthenticationCard>

View File

@@ -6,9 +6,13 @@ import type { AuthMode, AuthType } from '../../types/authTypes';
import { useEffect, useState } from 'react';
import { Toast } from '@/components/Toast';
import { AuthenticationCard } from '../AuthenticationCard';
import type { LoginRequest } from '../../types/userTypes';
import type {
ConfirmEmailOtpRequest,
LoginRequest,
} from '../../types/userTypes';
import { useSearchParams } from 'react-router';
import {
confirmEmailOtp,
loginOrSignUpWithOtp,
sendEmailOtp,
sendSmsOtp,
@@ -21,7 +25,8 @@ interface OtpVerifyFormProps {
authType: AuthType;
authMode: AuthMode;
onEditValue: () => void;
onOTPVerified: (registeredWithoutPhoneNumber: boolean, userID: GUID) => void;
onOTPVerified: (userID: GUID) => void;
onVerifyPhoneNumber: () => void;
authReturnUrl: string;
}
@@ -32,6 +37,7 @@ export function OtpVerifyForm({
authMode,
onEditValue,
onOTPVerified,
onVerifyPhoneNumber,
authReturnUrl,
}: OtpVerifyFormProps) {
const [otpCode, setOtpCode] = useState<string>('');
@@ -85,37 +91,66 @@ export function OtpVerifyForm({
setOtpCode(formattedValue);
};
const handleVerifyOTP = async () => {
const handleVerifyOTP = () => {
if (!otpCode || otpCode.length < 4) {
setOtpDigitInvalid(true);
} else {
setOtpDigitInvalid(false);
setVerifyStatusLoading(true);
// Change setTimeout to api call
const loginRequest: LoginRequest = {
otpCode: otpCode,
phoneNumber: authType === 'phone' ? countryCode + value : undefined,
email: authType === 'email' ? value : undefined,
returnUrl: authReturnUrl,
};
const result = await loginOrSignUpWithOtp(loginRequest);
const jsonRes = await result.json();
if (jsonRes.success) {
setVerifyStatus('success');
onOTPVerified(jsonRes.registeredWithOutPhoneNumber, jsonRes.userId);
if (authMode === 'register' && authType === 'email') {
handleConfirmEmailAndAddPhone();
} else {
setVerifyStatus('failed');
setErrorMessage(jsonRes.message);
handleLoginRequestWithOtp();
}
setVerifyAlertOpen(true);
setVerifyStatusLoading(false);
}
};
const handleConfirmEmailAndAddPhone = async () => {
setOtpDigitInvalid(false);
setVerifyStatusLoading(true);
const confirmOtpRequest: ConfirmEmailOtpRequest = {
otpCode: otpCode,
email: value,
};
const result = await confirmEmailOtp(confirmOtpRequest);
const jsonRes = await result.json();
if (jsonRes.success) {
setVerifyStatus('success');
onVerifyPhoneNumber();
} else {
setVerifyStatus('failed');
setErrorMessage(jsonRes.message);
}
setVerifyAlertOpen(true);
setVerifyStatusLoading(false);
};
const handleLoginRequestWithOtp = async () => {
setOtpDigitInvalid(false);
setVerifyStatusLoading(true);
const loginRequest: LoginRequest = {
otpCode: otpCode,
phoneNumber: authType === 'phone' ? countryCode + value : undefined,
email: authType === 'email' ? value : undefined,
returnUrl: authReturnUrl,
};
const result = await loginOrSignUpWithOtp(loginRequest);
const jsonRes = await result.json();
if (jsonRes.success) {
setVerifyStatus('success');
onOTPVerified(jsonRes.userId);
} else {
setVerifyStatus('failed');
setErrorMessage(jsonRes.message);
}
setVerifyAlertOpen(true);
setVerifyStatusLoading(false);
};
const otpMessage = (): string => {
if (authType === 'phone' && authMode === 'login') {
return t(

View File

@@ -16,19 +16,22 @@ import {
import type { CountryCode, GUID } from '@/types/commonTypes';
interface VerifyPhoneNumberProps {
authReturnUrl: string;
value: string;
email: string;
countryCode: CountryCode;
onEditValue: () => void;
onPhoneNumberVerified: (userId: GUID) => void;
}
export function VerifyPhoneNumber({
authReturnUrl,
email,
value,
countryCode,
onEditValue,
onPhoneNumberVerified,
}: VerifyPhoneNumberProps) {
const [searchParams] = useSearchParams();
const [otpCode, setOtpCode] = useState<string>('');
const [otpDigitInvalid, setOtpDigitInvalid] = useState<boolean>(false);
const [verifyStatus, setVerifyStatus] = useState<'success' | 'failed'>();
@@ -83,24 +86,22 @@ export function VerifyPhoneNumber({
setOtpDigitInvalid(false);
setVerifyStatusLoading(true);
// Change setTimeout to api call
const loginRequest: LoginRequest = {
otpCode: otpCode,
phoneNumber: countryCode + value,
email: email,
returnUrl: authReturnUrl,
};
const result = await loginOrSignUpWithOtp(loginRequest);
const jsonRes = await result.json();
// const loginRequest: LoginRequest = {
// otpCode: otpCode,
// phoneNumber: authType === 'phone' ? countryCode + value : undefined,
// email: authType === 'email' ? value : undefined,
// returnUrl: searchParams.get('returnUrl') ?? '/',
// };
// const result = await loginOrSignUpWithOtp(loginRequest);
// const jsonRes = await result.json();
// if (jsonRes.success) {
// setVerifyStatus('success');
// onOTPVerified(jsonRes.registeredWithOutPhoneNumber);
// } else {
// setVerifyStatus('failed');
// setErrorMessage(jsonRes.message);
// }
if (jsonRes.success) {
setVerifyStatus('success');
onPhoneNumberVerified(jsonRes.userId);
} else {
setVerifyStatus('failed');
setErrorMessage(jsonRes.message);
}
setVerifyAlertOpen(true);
setVerifyStatusLoading(false);