Files
Account/src/features/authentication/components/AuthenticationSteps/AuthenticationSteps.tsx
2025-09-29 17:26:04 +03:30

211 lines
6.7 KiB
TypeScript

import { useMemo, useState, type JSX } from 'react';
import { LoginRegisterForm } from './LoginRegiserForm';
import type {
AuthFactory,
AuthMode,
AuthStep,
AuthType,
} from '../../types/authTypes';
import { OtpVerifyForm } from './OtpVerifyForm';
import { isNumeric } from '@/utils/regexes/isNumeric';
import { CompleteSignUp } from './CompleteSignUp';
import { EnterPasswordForm } from './EnterPasswordForm';
import { UserStatus, type LoginResult } from '../../types/userTypes';
import type { CountryCode } from '@/types/commonTypes';
import { VerifyPhoneNumber } from './VerifyPhoneNumber';
import { useNavigate, useSearchParams } from 'react-router-dom';
import type { GenerateTokenResponse } from '../../api/identityAPI';
import { useAuth } from '@/hooks/useAuth';
export const AuthenticationSteps = (): JSX.Element => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const [authMode, setAuthMode] = useState<AuthMode>('register');
const [authType, setAuthType] = useState<AuthType>('phone');
const [currentStep, setCurrentStep] = useState<AuthStep>('emailOrPhone');
const [loginRegisterValue, setLoginRegisterValue] = useState<string>('');
const [countryCode, setCountryCode] = useState<CountryCode>('+98');
const [addPhoneCountryCode, setAddPhoneCountryCode] =
useState<CountryCode>('+98');
const [addedPhoneNumberValue, setAddedPhoneNumberValue] =
useState<string>('');
const [memoryTokenRes, setMemoryTokenRes] = useState<GenerateTokenResponse>();
const [hasPassword, setHasPassword] = useState(false);
const { login } = useAuth();
const authFactory: AuthFactory = useMemo(() => {
const redirectUrl = searchParams.get('redirect_url');
const clientId = searchParams.get('client_id');
if (!clientId) {
const defaultFactory: AuthFactory = {
clientId: import.meta.env.VITE_IDENTITY_CLIENT_ID,
redirectUrl: import.meta.env.VITE_APP_URL,
isCurrentApplication: function () {
return this.clientId === import.meta.env.VITE_IDENTITY_CLIENT_ID;
},
getFullRedirectUrl: function (token: string) {
return this.redirectUrl + '?token=' + token;
},
};
return defaultFactory;
}
const resFactory: AuthFactory = {
clientId: clientId,
redirectUrl: redirectUrl as string,
isCurrentApplication: function () {
return this.clientId === import.meta.env.VITE_IDENTITY_CLIENT_ID;
},
getFullRedirectUrl: function (token: string) {
return this.redirectUrl + '?token=' + token;
},
};
return resFactory;
}, [searchParams]);
const handleLoginRegister = (value: string, userStatus: UserStatus) => {
setAuthType(isNumeric(value) ? 'phone' : 'email');
switch (userStatus) {
case UserStatus.NotRegistered:
setAuthMode('register');
setCurrentStep('verify');
break;
case UserStatus.RegisteredWithoutPassword:
setAuthMode('login');
setCurrentStep('verify');
break;
case UserStatus.RegisteredWithPassword:
setAuthMode('login');
setCurrentStep('enterPassword');
setHasPassword(true);
break;
}
};
const handleUserLoggedIn = (
loginResult: LoginResult,
tokenResponse: GenerateTokenResponse,
) => {
setMemoryTokenRes(tokenResponse);
// TODO: For now both application scopes can have their tokens
// later we need to discuss this base on business plan and change it
// if (authFactory.isCurrentApplication()) {}
login(tokenResponse);
if (loginResult.registeredWithOutPhoneNumber) {
setCurrentStep('addPhoneNumber');
return;
}
if (!loginResult.completedUserInformation) {
if (!authFactory.isCurrentApplication()) {
navigate(
`/signup?returnUrl=${authFactory.getFullRedirectUrl(tokenResponse.refresh_token)}`,
);
} else {
navigate(`/signup`);
}
return;
}
redirectToReturnUrl(tokenResponse.refresh_token);
};
const handlePhoneNumberVerified = () => {
if (!authFactory.isCurrentApplication()) {
navigate(
`/signup?returnUrl=${authFactory.getFullRedirectUrl(memoryTokenRes?.refresh_token as string)}`,
);
} else {
navigate(`/signup`);
}
};
const redirectToReturnUrl = (refreshToken: string) => {
if (authFactory.isCurrentApplication()) {
navigate(import.meta.env.VITE_DEFUALT_AUTH_RETURN_URL);
} else {
if (authMode === 'register') {
navigate(
`/account-created?returnUrl=${authFactory.getFullRedirectUrl(refreshToken)}`,
);
} else {
location.href = authFactory.getFullRedirectUrl(refreshToken);
}
}
};
return (
<>
{currentStep === 'emailOrPhone' && (
<LoginRegisterForm
authFactory={authFactory}
onGoogleAuthenticated={handleUserLoggedIn}
countryCode={countryCode}
setCountryCode={setCountryCode}
loginRegisterValue={loginRegisterValue}
setLoginRegisterValue={setLoginRegisterValue}
authType={authType}
setAuthType={setAuthType}
onLoginRegisterSubmit={handleLoginRegister}
/>
)}
{currentStep === 'verify' && (
<OtpVerifyForm
authFactory={authFactory}
countryCode={countryCode}
onOTPVerified={handleUserLoggedIn}
onEditValue={() => setCurrentStep('emailOrPhone')}
authMode={authMode}
authType={authType}
value={loginRegisterValue}
hasPassword={hasPassword}
onLoginWithPassword={() => setCurrentStep('enterPassword')}
/>
)}
{currentStep === 'enterPassword' && (
<EnterPasswordForm
authFactory={authFactory}
loginRegisterValue={loginRegisterValue}
countryCode={countryCode}
authType={authType}
onLoggedIn={handleUserLoggedIn}
onEditValue={() => setCurrentStep('emailOrPhone')}
onLoginWithOTP={() => setCurrentStep('verify')}
emailOrPhone={loginRegisterValue}
/>
)}
{currentStep === 'addPhoneNumber' && (
<CompleteSignUp
countryCode={addPhoneCountryCode}
setCountryCode={setAddPhoneCountryCode}
value={addedPhoneNumberValue}
setValue={setAddedPhoneNumberValue}
email={loginRegisterValue}
onCompleteSignUp={() => setCurrentStep('addedPhoneNumberVerify')}
/>
)}
{currentStep === 'addedPhoneNumberVerify' && (
<VerifyPhoneNumber
countryCode={countryCode}
onEditValue={() => setCurrentStep('addPhoneNumber')}
value={addedPhoneNumberValue}
onPhoneNumberVerified={handlePhoneNumberVerified}
/>
)}
</>
);
};