chore: change styles and add Api for user profile
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CardContainer } from '@/components/CardContainer';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
@@ -7,13 +7,53 @@ import SocialMediaMenu from './socialMedia/SocialMediaMenu';
|
||||
import SocialMediaDialog from './socialMedia/SocialMediaDialog';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import type { Theme } from '@mui/material/styles';
|
||||
import apiClient from '@/lib/apiClient';
|
||||
import { Box, CircularProgress, Typography } from '@mui/material';
|
||||
|
||||
interface EmailAccount {
|
||||
email: string;
|
||||
provider: 'email' | 'google';
|
||||
time: string;
|
||||
}
|
||||
|
||||
interface GetProfileApiResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
interface SendCodeApiResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
interface ConfirmCodeApiResponse {
|
||||
success: boolean;
|
||||
confirm?: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
interface ChangeEmailApiResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export function SocialMedia() {
|
||||
const { t } = useTranslation('profileSetting');
|
||||
const { t } = useTranslation('setting');
|
||||
const token = localStorage.getItem('authToken');
|
||||
|
||||
const [openDialog, setOpenDialog] = useState(false);
|
||||
const [emailInput, setEmailInput] = useState('');
|
||||
const [emailError, setEmailError] = useState(false);
|
||||
const [verificationCode, setVerificationCode] = useState('');
|
||||
const [dialogStep, setDialogStep] = useState<'enterEmail' | 'enterCode'>(
|
||||
'enterEmail',
|
||||
);
|
||||
const [apiError, setApiError] = useState<string | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [emailList, setEmailList] = useState<EmailAccount[]>([]);
|
||||
|
||||
const [isFetching, setIsFetching] = useState(true);
|
||||
const [fetchError, setFetchError] = useState<string | null>(null);
|
||||
|
||||
const fullScreen = useMediaQuery((theme: Theme) =>
|
||||
theme.breakpoints.down('sm'),
|
||||
@@ -26,10 +66,128 @@ export function SocialMedia() {
|
||||
| 'lg'
|
||||
| 'xl';
|
||||
|
||||
const emailList = [
|
||||
{ email: 'emailtemp@email.com', provider: 'email', time: '1 ماه پیش' },
|
||||
{ email: 'emailtemp@gmail.com', provider: 'google', time: '1 ماه پیش' },
|
||||
] as const;
|
||||
useEffect(() => {
|
||||
const fetchInitialEmail = async () => {
|
||||
setIsFetching(true);
|
||||
setFetchError(null);
|
||||
if (!token) {
|
||||
setIsFetching(false);
|
||||
setFetchError(t('settingForm.notLoggedIn'));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await apiClient.post<GetProfileApiResponse>(
|
||||
'/Profile/GetProfile',
|
||||
{},
|
||||
{ headers: { Authorization: `Bearer ${token}` } },
|
||||
);
|
||||
|
||||
if (res.data.success && res.data.email) {
|
||||
const userEmail = res.data.email;
|
||||
const newAccount: EmailAccount = {
|
||||
email: userEmail,
|
||||
provider: userEmail.includes('gmail.com') ? 'google' : 'email',
|
||||
time: '',
|
||||
};
|
||||
setEmailList([newAccount]);
|
||||
} else if (!res.data.success) {
|
||||
throw new Error(res.data.message || t('settingForm.failFetchEmail'));
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
let message = t('settingForm.errorFetchEmail');
|
||||
if (err instanceof Error) {
|
||||
message = err.message;
|
||||
}
|
||||
setFetchError(message);
|
||||
} finally {
|
||||
setIsFetching(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchInitialEmail();
|
||||
}, [token, t]);
|
||||
|
||||
const resetDialog = () => {
|
||||
setOpenDialog(false);
|
||||
setEmailInput('');
|
||||
setVerificationCode('');
|
||||
setApiError(null);
|
||||
setIsLoading(false);
|
||||
setDialogStep('enterEmail');
|
||||
};
|
||||
|
||||
const handleSendCode = async () => {
|
||||
if (!/^\S+@\S+\.\S+$/.test(emailInput)) {
|
||||
setApiError(t('settingForm.emailIsInvalid'));
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
setApiError(null);
|
||||
try {
|
||||
const res = await apiClient.post<SendCodeApiResponse>(
|
||||
'Profile/SendEmailChangeCode',
|
||||
{ email: emailInput },
|
||||
{ headers: { Authorization: `Bearer ${token}` } },
|
||||
);
|
||||
if (res.data.success) {
|
||||
setDialogStep('enterCode');
|
||||
} else {
|
||||
setApiError(res.data.message || t('settingForm.sendCodeFailed'));
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
setApiError(t('settingForm.sendCodeFailed'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirmAndChangeEmail = async () => {
|
||||
if (verificationCode.length < 4) {
|
||||
setApiError(t('settingForm.verificationCodeRequired'));
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
setApiError(null);
|
||||
try {
|
||||
const confirmRes = await apiClient.post<ConfirmCodeApiResponse>(
|
||||
'Profile/ConfirmEmailChangeCode',
|
||||
{ email: emailInput, verifyCode: verificationCode },
|
||||
{ headers: { Authorization: `Bearer ${token}` } },
|
||||
);
|
||||
|
||||
if (confirmRes.data.success && confirmRes.data.confirm) {
|
||||
const changeRes = await apiClient.post<ChangeEmailApiResponse>(
|
||||
'Profile/ChangeEmail',
|
||||
{ email: emailInput },
|
||||
{ headers: { Authorization: `Bearer ${token}` } },
|
||||
);
|
||||
|
||||
if (changeRes.data.success) {
|
||||
setEmailList((prevList) => [
|
||||
...prevList,
|
||||
{
|
||||
email: emailInput,
|
||||
provider: 'email',
|
||||
time: t('settingForm.justNow'),
|
||||
},
|
||||
]);
|
||||
resetDialog();
|
||||
} else {
|
||||
setApiError(
|
||||
changeRes.data.message || t('settingForm.changeEmailFailed'),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setApiError(
|
||||
confirmRes.data.message || t('settingForm.verifyCodeFailed'),
|
||||
);
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
setApiError(t('settingForm.anErrorOccurred'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
@@ -40,15 +198,38 @@ export function SocialMedia() {
|
||||
<SocialMediaMenu t={t} onOpenDialog={() => setOpenDialog(true)} />
|
||||
}
|
||||
>
|
||||
<SocialMediaList t={t} emailList={emailList} />
|
||||
{isFetching ? (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
p: 4,
|
||||
minHeight: '100px',
|
||||
}}
|
||||
>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
) : fetchError ? (
|
||||
<Box sx={{ textAlign: 'center', p: 4 }}>
|
||||
<Typography color="error.main">{fetchError}</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<SocialMediaList t={t} emailList={emailList} />
|
||||
)}
|
||||
<SocialMediaDialog
|
||||
open={openDialog}
|
||||
onClose={() => setOpenDialog(false)}
|
||||
onClose={resetDialog}
|
||||
t={t}
|
||||
emailInput={emailInput}
|
||||
setEmailInput={setEmailInput}
|
||||
emailError={emailError}
|
||||
setEmailError={setEmailError}
|
||||
verificationCode={verificationCode}
|
||||
setVerificationCode={setVerificationCode}
|
||||
apiError={apiError}
|
||||
isLoading={isLoading}
|
||||
dialogStep={dialogStep}
|
||||
onSendCode={handleSendCode}
|
||||
onConfirmEmail={handleConfirmAndChangeEmail}
|
||||
fullScreen={fullScreen}
|
||||
computedMaxWidth={computedMaxWidth}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user