feat: complete sign up form added
This commit is contained in:
@@ -17,7 +17,11 @@
|
||||
"theVerificationCodeIsIncorrect": "The verification code is incorrect.",
|
||||
"youHaveSuccessfullyLoggedIn": "You have successfully logged in",
|
||||
"youHaveSuccessfullySignedIn": "You have successfully signed in"
|
||||
},
|
||||
"completeSignUp": {
|
||||
"completeSignUp": "Complete Sign Up",
|
||||
"emailHasBeenSuccessfullyVerifiedPleaseEnterYourContactNumberToContinue": "Email {{ email }} has been successfully verified. Please enter your contact number to continue.",
|
||||
"phoneNumber": "Phone number"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,5 +20,10 @@
|
||||
"theVerificationCodeIsIncorrect": "کد تایید اشتباه می باشد",
|
||||
"youHaveSuccessfullyLoggedIn": "با موفقیت وارد شدید",
|
||||
"youHaveSuccessfullySignedIn": "ثبت نام با موفقیت انجام شد"
|
||||
},
|
||||
"completeSignUp": {
|
||||
"completeSignUp": "تکمیل ثبت نام",
|
||||
"emailHasBeenSuccessfullyVerifiedPleaseEnterYourContactNumberToContinue": "ایمیل {{ email }} با موفقیت تایید شد. برای ادامه لطفا شماره تماس خود را وارد کنید",
|
||||
"phoneNumber": "شماره تماس"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,21 @@ import { LoginRegisterForm } from './LoginRegiserForm';
|
||||
import type { AuthMode, AuthType } from '../types/auth-types';
|
||||
import { OtpVerifyForm } from './OtpVerifyForm';
|
||||
import { isNumeric } from '@/utils/regexes/isNumeric';
|
||||
import { CompleteSignUp } from './CompleteSignUp';
|
||||
|
||||
export const AuthenticationContainer = (): JSX.Element => {
|
||||
const [authMode, setAuthMode] = useState<AuthMode>('login');
|
||||
const [authMode, setAuthMode] = useState<AuthMode>('register');
|
||||
const [authType, setAuthType] = useState<AuthType>('phone');
|
||||
const [currentStep, setCurrentStep] = useState<
|
||||
'emailOrPassword' | 'verify' | 'enterPassword' | 'addPhoneNumber'
|
||||
| 'emailOrPassword'
|
||||
| 'verify'
|
||||
| 'enterPassword'
|
||||
| 'addPhoneNumber'
|
||||
| 'addedPhoneNumberVerify'
|
||||
>('emailOrPassword');
|
||||
const [loginRegisterValue, setLoginRegisterValue] = useState<string>('');
|
||||
const [addedPhoneNumberValue, setAddedPhoneNumberValue] =
|
||||
useState<string>('');
|
||||
|
||||
const handleLoginRegister = (value: string) => {
|
||||
setLoginRegisterValue(value);
|
||||
@@ -19,8 +26,6 @@ export const AuthenticationContainer = (): JSX.Element => {
|
||||
};
|
||||
|
||||
const handleOTPVerfied = (otpCode: string) => {
|
||||
console.log(otpCode);
|
||||
|
||||
if (authMode === 'register' && authType === 'email') {
|
||||
setAuthType('phone');
|
||||
setCurrentStep('addPhoneNumber');
|
||||
@@ -31,6 +36,18 @@ export const AuthenticationContainer = (): JSX.Element => {
|
||||
setCurrentStep('emailOrPassword');
|
||||
};
|
||||
|
||||
const handleCompleteSignUp = (countryCode: string, value: string) => {
|
||||
setCurrentStep('addedPhoneNumberVerify');
|
||||
};
|
||||
|
||||
const handleCompleteSignUpOTPVerified = (otpCode: string) => {
|
||||
console.log(otpCode);
|
||||
};
|
||||
|
||||
const handleCompleteSignUpEditValue = () => {
|
||||
setCurrentStep('addPhoneNumber');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{currentStep === 'emailOrPassword' && (
|
||||
@@ -52,6 +69,25 @@ export const AuthenticationContainer = (): JSX.Element => {
|
||||
value={loginRegisterValue}
|
||||
/>
|
||||
)}
|
||||
|
||||
{currentStep === 'addPhoneNumber' && (
|
||||
<CompleteSignUp
|
||||
value={addedPhoneNumberValue}
|
||||
setValue={setAddedPhoneNumberValue}
|
||||
email={loginRegisterValue}
|
||||
onCompleteSignUp={handleCompleteSignUp}
|
||||
/>
|
||||
)}
|
||||
|
||||
{currentStep === 'addedPhoneNumberVerify' && (
|
||||
<OtpVerifyForm
|
||||
onOTPVerified={handleCompleteSignUpOTPVerified}
|
||||
onEditValue={handleCompleteSignUpEditValue}
|
||||
authMode="register"
|
||||
authType="phone"
|
||||
value={addedPhoneNumberValue}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
106
src/features/authentication/components/CompleteSignUp.tsx
Normal file
106
src/features/authentication/components/CompleteSignUp.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Box, Button, TextField, Typography } from '@mui/material';
|
||||
import parsePhoneNumberFromString from 'libphonenumber-js';
|
||||
import React, { useRef, useState, type Dispatch } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CountryCodeSelector } from './CountryCodeSelector';
|
||||
|
||||
export interface CompleteSignUpProps {
|
||||
email: string;
|
||||
value: string;
|
||||
setValue: Dispatch<string>;
|
||||
onCompleteSignUp: (countryCode: string, value: string) => void;
|
||||
}
|
||||
|
||||
export const CompleteSignUp = ({
|
||||
email,
|
||||
value,
|
||||
setValue,
|
||||
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 isPhoneValid = (code: string, phone: string) => {
|
||||
const phoneNumber = parsePhoneNumberFromString(code + phone);
|
||||
|
||||
return phoneNumber && phoneNumber.isValid();
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
setTouched(true);
|
||||
|
||||
if (!value) {
|
||||
setError(t('loginForm.thisFieldIsRequired'));
|
||||
}
|
||||
if (!isPhoneValid(countryCode, value)) {
|
||||
setError(t('loginForm.phoneNumberIsInvalid'));
|
||||
} else {
|
||||
setError(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCompleteSignUp = () => {
|
||||
if (!value) {
|
||||
setError(t('loginForm.thisFieldIsRequired'));
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
if (!isPhoneValid(countryCode, value)) {
|
||||
setError(t('loginForm.phoneNumberIsInvalid'));
|
||||
inputRef.current?.focus();
|
||||
} else {
|
||||
setError(undefined);
|
||||
onCompleteSignUp(countryCode, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<Typography variant="h5" sx={{ mb: 0.5 }}>
|
||||
{t('completeSignUp.completeSignUp')}
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body2" color="textSecondary" sx={{ mt: 1, mb: 2 }}>
|
||||
{t(
|
||||
'completeSignUp.emailHasBeenSuccessfullyVerifiedPleaseEnterYourContactNumberToContinue',
|
||||
{ email },
|
||||
)}
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
ref={textFieldRef}
|
||||
inputRef={inputRef}
|
||||
label={t('completeSignUp.phoneNumber')}
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
onBlur={handleBlur}
|
||||
error={inputError}
|
||||
helperText={inputError ? error : ''}
|
||||
autoFocus
|
||||
slotProps={{
|
||||
htmlInput: { dir: 'auto', sx: { lineHeight: 1.5, paddingX: 0 } },
|
||||
input: {
|
||||
endAdornment: (
|
||||
<CountryCodeSelector
|
||||
value={countryCode}
|
||||
onChange={setCountryCode}
|
||||
show={true}
|
||||
menuAnchor={textFieldRef.current}
|
||||
onCloseFocusRef={inputRef}
|
||||
/>
|
||||
),
|
||||
},
|
||||
}}
|
||||
sx={{ my: 4 }}
|
||||
/>
|
||||
|
||||
<Button onClick={handleCompleteSignUp}>
|
||||
{t('verify.confirmAndContinue')}
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -46,7 +46,7 @@ export const CustomThemeProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
}, [i18n]);
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme} defaultMode="system">
|
||||
<ThemeProvider theme={theme} defaultMode="light">
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user