Files
Account/src/features/authentication/components/AuthenticationSteps/CompleteSignUp.tsx
Sajad Mirjalili 2a6dd67cb4 fix: ui bugs
2025-11-28 16:15:43 +03:30

167 lines
4.9 KiB
TypeScript

import { Box, Button, TextField, Typography } from '@mui/material';
import parsePhoneNumberFromString from 'libphonenumber-js';
import { useRef, useState, type ChangeEvent, type Dispatch } from 'react';
import { useTranslation } from 'react-i18next';
import { AuthenticationCard } from '../AuthenticationCard';
import { CountryCodeSelector } from '../../../../components/CountryCodeSelector';
import {
sendSmsCodeCompleteUserInforamation,
sendSmsOtp,
} from '../../api/authorizationAPI';
import type { CountryCode } from '@/types/commonTypes';
import { useApi } from '@/hooks/useApi';
import { replacePersianWithRealNumbers } from '@/utils/replacePersianWithRealNumbers';
import { useToast } from '@rkheftan/harmony-ui';
export interface CompleteSignUpProps {
email: string;
value: string;
setValue: Dispatch<string>;
countryCode: CountryCode;
setCountryCode: Dispatch<CountryCode>;
onCompleteSignUp: (countryCode: string, value: string) => void;
setTimerValue: Dispatch<number>;
}
export const CompleteSignUp = ({
email,
value,
setValue,
countryCode,
setCountryCode,
onCompleteSignUp,
setTimerValue,
}: CompleteSignUpProps) => {
const { t, i18n } = useTranslation('authentication');
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 { loading: sendSmsLoading, execute: sendSmsCall } = useApi(
sendSmsCodeCompleteUserInforamation,
);
const toast = useToast();
const isPhoneValid = (code: string, phone: string) => {
const phoneNumber = parsePhoneNumberFromString(code + phone);
return phoneNumber && phoneNumber.isValid();
};
const handleBlur = () => {
setTouched(true);
handleValueError();
};
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const value = replacePersianWithRealNumbers(event.target.value);
setValue(value);
};
const handleValueError = () => {
if (!value) {
setError(t('loginForm.thisFieldIsRequired'));
}
if (!isPhoneValid(countryCode, value)) {
setError(t('loginForm.phoneNumberIsInvalid'));
} else {
setError(undefined);
}
};
const handleCompleteSignUp = async () => {
handleValueError();
if (!value || !isPhoneValid(countryCode, value)) {
inputRef.current?.focus();
} else {
let newValue = value;
if (countryCode === '+98' && newValue.startsWith('09')) {
newValue = newValue.substring(1);
setValue(newValue);
}
const res = await sendSmsCall({ phoneNumber: countryCode + newValue });
if (!res) return;
if (res.success) {
onCompleteSignUp(countryCode, newValue);
setTimerValue(res.totalSecondForCodeToExpire);
} else {
toast({
message: res.message,
severity: 'error',
});
setError(res.message);
}
}
};
return (
<AuthenticationCard>
<Box
component="form"
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
if (!sendSmsLoading) void handleCompleteSignUp();
}}
>
<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={handleChange}
onBlur={handleBlur}
error={inputError}
helperText={inputError ? error : ''}
autoFocus
slotProps={{
htmlInput: { dir: 'auto', sx: { lineHeight: 1.5 } },
input: {
endAdornment: i18n.dir() === 'rtl' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={true}
menuAnchor={textFieldRef.current}
onCloseFocusRef={inputRef}
/>
),
startAdornment: i18n.dir() === 'ltr' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={true}
menuAnchor={textFieldRef.current}
onCloseFocusRef={inputRef}
/>
),
},
}}
sx={{ my: 4 }}
/>
<Button loading={sendSmsLoading} type="submit">
{t('verify.confirmAndContinue')}
</Button>
</Box>
</AuthenticationCard>
);
};