feat: layout padding and scroll added
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Box, Button, Stack, Typography } from '@mui/material';
|
||||
import { Edit2 } from 'iconsax-react';
|
||||
import DigitInput from '@/components/DigitsInput';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { AuthenticationCard } from '../AuthenticationCard';
|
||||
import type { ConfirmSmsOtpRequest } from '../../types/userTypes';
|
||||
import { confirmSmsOtp, sendSmsOtp } from '../../api/authorizationAPI';
|
||||
import type { CountryCode } from '@/types/commonTypes';
|
||||
import { Icon, useToast } from '@rkheftan/harmony-ui';
|
||||
import { useApi } from '@/hooks/useApi';
|
||||
|
||||
interface VerifyPhoneNumberProps {
|
||||
value: string;
|
||||
countryCode: CountryCode;
|
||||
onEditValue: () => void;
|
||||
onPhoneNumberVerified: () => void;
|
||||
}
|
||||
|
||||
export function VerifyPhoneNumber({
|
||||
value,
|
||||
countryCode,
|
||||
onEditValue,
|
||||
onPhoneNumberVerified,
|
||||
}: VerifyPhoneNumberProps) {
|
||||
const [otpCode, setOtpCode] = useState<string>('');
|
||||
const [otpDigitInvalid, setOtpDigitInvalid] = useState<boolean>(false);
|
||||
const [isStatusSuccess, setIsStatusSuccess] = useState<boolean>();
|
||||
const { t } = useTranslation('authentication');
|
||||
const [resendTimer, setResendTimer] = useState<number>(120);
|
||||
const [canResend, setCanResend] = useState(false);
|
||||
const toast = useToast();
|
||||
const { loading: smsResendLoading, execute: smsResendCall } =
|
||||
useApi(sendSmsOtp);
|
||||
const { loading: confirmSmsOtpLoading, execute: confirmSmsOtpCall } =
|
||||
useApi(confirmSmsOtp);
|
||||
|
||||
useEffect(() => {
|
||||
let interval: NodeJS.Timeout;
|
||||
if (resendTimer > 0) {
|
||||
interval = setInterval(() => {
|
||||
setResendTimer((prev) => prev - 1);
|
||||
}, 1000);
|
||||
} else {
|
||||
setCanResend(true);
|
||||
}
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [resendTimer]);
|
||||
|
||||
const handleResendOTPCode = async () => {
|
||||
await smsResendCall({ phoneNumber: countryCode + value });
|
||||
|
||||
setResendTimer(120);
|
||||
setCanResend(false);
|
||||
};
|
||||
|
||||
const formatTime = (seconds: number) => {
|
||||
const min = Math.floor(seconds / 60);
|
||||
const sec = seconds % 60;
|
||||
return `${min}:${sec.toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const handleVerifyOTP = async () => {
|
||||
if (!otpCode || otpCode.length < 4) {
|
||||
setOtpDigitInvalid(true);
|
||||
} else {
|
||||
setOtpDigitInvalid(false);
|
||||
|
||||
const confirmSmsOtpRequest: ConfirmSmsOtpRequest = {
|
||||
otpCode: otpCode,
|
||||
phoneNumber: countryCode + value,
|
||||
};
|
||||
const res = await confirmSmsOtpCall(confirmSmsOtpRequest);
|
||||
|
||||
if (!res) return;
|
||||
|
||||
if (res.success) {
|
||||
setIsStatusSuccess(true);
|
||||
toast({
|
||||
message: t('verify.youHaveSuccessfullyLoggedIn'),
|
||||
severity: 'success',
|
||||
});
|
||||
onPhoneNumberVerified();
|
||||
} else {
|
||||
setIsStatusSuccess(false);
|
||||
toast({
|
||||
message: res.message ?? t('verify.theVerificationCodeIsIncorrect'),
|
||||
severity: 'error',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack alignItems="center">
|
||||
<AuthenticationCard>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: 4,
|
||||
mb: 0.5,
|
||||
}}
|
||||
>
|
||||
<Typography variant="h5">{t('verify.verify')}</Typography>
|
||||
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="large"
|
||||
sx={{ textTransform: 'lowercase', width: 'auto' }}
|
||||
endIcon={<Icon Component={Edit2} />}
|
||||
onClick={onEditValue}
|
||||
>
|
||||
{countryCode + value}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Typography variant="body2" color="textSecondary" sx={{ mt: 1 }}>
|
||||
{t(
|
||||
'verify.a4DigitVerificationCodeHasBeenSentToYourBobileNumberPleaseEnterIt',
|
||||
)}
|
||||
</Typography>
|
||||
|
||||
<DigitInput
|
||||
error={otpDigitInvalid || isStatusSuccess === false}
|
||||
success={isStatusSuccess === true}
|
||||
onChange={(value) => setOtpCode(value)}
|
||||
/>
|
||||
|
||||
<Button onClick={handleVerifyOTP} loading={confirmSmsOtpLoading}>
|
||||
{t('verify.confirmAndLogin')}
|
||||
</Button>
|
||||
</AuthenticationCard>
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
mt: 1.5,
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1">{t('verify.resendCodeIn')}</Typography>
|
||||
|
||||
<Button
|
||||
variant="text"
|
||||
loading={smsResendLoading}
|
||||
sx={{ width: 'auto' }}
|
||||
onClick={canResend ? handleResendOTPCode : undefined}
|
||||
>
|
||||
{canResend && t('verify.resendCode')}
|
||||
{!canResend && `${formatTime(resendTimer)} ${t('verify.moreMinute')}`}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user