fix: api calls

This commit is contained in:
Koosha Lahouti
2025-08-09 14:08:02 -07:00
parent fb9d691f6a
commit ca0680c78f
7 changed files with 398 additions and 53 deletions

View File

@@ -163,6 +163,7 @@ export function EmailSection({
{!isVerifyingCode && !emailVerified && (
<Button
type="button"
variant="text"
onClick={onSendCodeClick}
sx={{

View File

@@ -74,15 +74,6 @@ export function SubmitSection({ onSubmit, loading, error, success }: Props) {
{t('completion.agreementPart2')}
</Typography>
{/* <Button
variant="contained"
sx={{
width: { xs: '100%', sm: '247px' },
alignSelf: { xs: 'stretch', sm: 'center' },
}}
>
{t('completion.registerButton')}
</Button> */}
<Button
variant="contained"
onClick={onSubmit}
@@ -95,7 +86,7 @@ export function SubmitSection({ onSubmit, loading, error, success }: Props) {
{loading
? t('completion.submitting')
: success
? t('completion.success')
? t('completion.registerButton')
: t('completion.registerButton')}
</Button>
{error && <Typography color="error">{error}</Typography>}

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { Box, Typography, Button } from '@mui/material';
import { useEffect, useState } from 'react';
import { Box, Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
import Logo from '@/components/Logo';
import { PersonalInfoFields } from './PersonalInfoFields';
@@ -7,7 +7,7 @@ import { PasswordSection } from './PasswordSection';
import { EmailSection } from './EmailSection';
import { SubmitSection } from './SubmitSection';
import apiClient from '@/lib/apiClient';
import { sendEmailOtp, fetchAuthToken } from '@/lib/authToken';
import { Toast } from '@/components/Toast';
export function UserCompletionForm() {
const { t } = useTranslation('completionForm');
@@ -48,6 +48,15 @@ export function UserCompletionForm() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState(false);
const [showSuccessToast, setShowSuccessToast] = useState(false);
const [showErrorToast, setShowErrorToast] = useState(false);
const [toastMessage, setToastMessage] = useState('');
const [showVerifyCodeSectionSuccess, setShowVerifyCodeSectionSuccess] =
useState(false);
const [showVerifyCodeSectionError, setShowVerifyCodeSectionError] =
useState(false);
const [sentVerificationCode, setSentVerificationCode] = useState('');
useEffect(() => {
if (password) {
@@ -65,18 +74,16 @@ export function UserCompletionForm() {
useEffect(() => {
let timer: NodeJS.Timeout;
if (buttonState === 'counting' && countdown > 0) {
timer = setInterval(
() =>
setCountdown((prev) => {
if (prev <= 1) {
setButtonState('default');
clearInterval(timer);
return 0;
}
return prev - 1;
}),
1000,
);
timer = setInterval(() => {
setCountdown((prev) => {
if (prev <= 1) {
setButtonState('default');
clearInterval(timer);
return 0;
}
return prev - 1;
});
}, 1000);
}
return () => clearInterval(timer);
}, [buttonState, countdown]);
@@ -97,29 +104,67 @@ export function UserCompletionForm() {
setError(null);
setLoading(true);
setSuccess(false);
try {
await sendEmailOtp(EMAIL);
setSuccess(true);
} catch {
setError('Failed to send OTP');
const response = await apiClient.post('/User/SendEmailOtp', { email });
if (response.data?.success) {
setSentVerificationCode(response.data.message);
setShowVerifyCodeSectionSuccess(true);
setCodeSent(true);
setButtonState('counting');
setCountdown(120);
setSuccess(true);
setSentVerificationCode(
response.data.message || 'کد با موفقیت ارسال شد',
);
} else {
setShowVerifyCodeSectionError(true);
setSentVerificationCode(response.data.message || 'مشکلی پیش آمده');
// setError(
// response.data?.message || t('completion.verificationCodeError'),
// );
}
} catch (err: any) {
setShowVerifyCodeSectionError(true);
setSentVerificationCode(err.response?.data?.message || 'مشکلی پیش آمده');
// setError(
// err.response?.data?.message || t('completion.verificationCodeError'),
// );
} finally {
setLoading(false);
}
};
const handleVerifyCode = async () => {
if (!verificationCode) return;
if (!verificationCode.trim()) {
setError('Please enter the verification code');
return;
}
setIsVerifyingCode(true);
setError(null);
try {
const tokenRes = await fetchAuthToken(email, verificationCode);
localStorage.setItem('authToken', tokenRes.access_token);
apiClient.defaults.headers.common['Authorization'] =
`Bearer ${tokenRes.access_token}`;
setEmailVerified(true);
} catch {
setError('Invalid verification code');
const res = await apiClient.post('/User/ConfirmEmailOtp', {
email,
otp: verificationCode,
});
if (res.data?.success) {
setEmailVerified(true);
setSuccess(true);
if (res.data.access_token) {
localStorage.setItem('authToken', res.data.access_token);
apiClient.defaults.headers.common['Authorization'] =
`Bearer ${res.data.access_token}`;
}
} else {
setError(res.data?.message || 'Invalid verification code');
}
} catch (err: any) {
setError(
err.response?.data?.message ||
'Something went wrong while verifying the code',
);
} finally {
setIsVerifyingCode(false);
}
@@ -143,6 +188,7 @@ export function UserCompletionForm() {
message: string;
validations: { property: string; message: string }[];
}>('/User/CompleteUserInformation', {
userId: '9cb8ae51-95f9-4f66-99b4-1c7c4d48251b',
firstName,
lastName,
gender: sex === 'female' ? 2 : 1,
@@ -155,21 +201,22 @@ export function UserCompletionForm() {
country,
});
if (data.success) {
setSuccess(true);
setToastMessage(data.message || t('completion.submitSuccess'));
setShowSuccessToast(true);
} else {
setError(data.message || 'Validation error');
setToastMessage(data.message || t('completion.submitError'));
setShowErrorToast(true);
}
} catch (err: any) {
setError(
err.response?.data?.message || err.message || 'An error occurred',
setToastMessage(
err.response?.data?.message || err.message || 'خطای ناشناخته',
);
setShowErrorToast(true);
} finally {
setLoading(false);
}
};
const EMAIL = 'klahouti81@gmail.com';
return (
<Box
sx={{
@@ -238,6 +285,21 @@ export function UserCompletionForm() {
showValidations={showPasswordValidations}
/>
<Toast
color="success"
open={showVerifyCodeSectionSuccess}
onClose={() => setShowVerifyCodeSectionSuccess(false)}
>
{sentVerificationCode}
</Toast>
<Toast
color="error"
open={showVerifyCodeSectionError}
onClose={() => setShowVerifyCodeSectionError(false)}
>
{sentVerificationCode}
</Toast>
<EmailSection
showEmail={showEmail}
setShowEmail={setShowEmail}
@@ -255,10 +317,20 @@ export function UserCompletionForm() {
isVerifyingCode={isVerifyingCode}
handleEditEmail={handleEditEmail}
/>
<Button onClick={handleSendCode} variant="contained" disabled={loading}>
{loading ? 'Sending…' : 'Send OTP'}
</Button>
<Toast
color="success"
open={showSuccessToast}
onClose={() => setShowSuccessToast(false)}
>
{toastMessage}
</Toast>
<Toast
color="error"
open={showErrorToast}
onClose={() => setShowErrorToast(false)}
>
{toastMessage}
</Toast>
<SubmitSection
onSubmit={handleSubmit}