fix: dashboard api calls, multi profile fetch

This commit is contained in:
Sajad Mirjalili
2025-08-21 14:51:56 +03:30
parent 4d84a29bda
commit 16fa6615c9
24 changed files with 656 additions and 679 deletions

View File

@@ -1,5 +1,5 @@
import { useState, useEffect, useRef } from 'react';
import { Box, Button, Typography, CircularProgress } from '@mui/material';
import { Box, Button, CircularProgress } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { CardContainer } from '@/components/CardContainer';
import { ProfileImage } from './personalInformation/ProfileImage';
@@ -8,10 +8,13 @@ import { InfoRowEdit } from './personalInformation/InfoRowEdit';
import { PageWrapper } from '../PageWrapper';
import { useApi } from '@/hooks/useApi';
import { Gender, type InfoRowData } from '../../types/settingsType';
import { fetchProfile, saveProfile } from '../../api/settingsApi';
import { saveProfile } from '../../api/settingsApi';
import { useToast } from '@rkheftan/harmony-ui';
import { useProfile } from '../../hooks/useProfile';
export function PersonalInformation() {
const imageBaseUrl = import.meta.env.IMAGE_BASE_URL;
const { t } = useTranslation('setting');
const [isEditing, setIsEditing] = useState(false);
const [uploadedImageUrl, setUploadedImageUrl] = useState<string | null>(null);
@@ -27,52 +30,46 @@ export function PersonalInformation() {
const showToast = useToast();
const infoRowEditRef = useRef<{ validateFields: () => boolean }>(null);
const {
data: profileData,
loading: isLoadingProfile,
error: fetchProfileError,
} = useApi(fetchProfile, { immediate: true });
const {
data: saveData,
loading: isSavingProfile,
error: saveProfileError,
execute: executeSaveProfile,
} = useApi(saveProfile);
const { isLoadingProfile, refetchProfile } = useProfile();
const { loading: isSavingProfile, execute: executeSaveProfile } =
useApi(saveProfile);
useEffect(() => {
if (profileData?.success) {
const fetchedData = {
firstName: profileData.firstName ?? '',
lastName: profileData.lastName ?? '',
nationalCode: profileData.nationalCode ?? '',
gender: Object.values(Gender).includes(profileData.gender as Gender)
? (profileData.gender as Gender)
: Gender.None,
country: profileData.countryCode ?? '',
};
setData(fetchedData);
setOriginalData(fetchedData);
const imageBaseUrl = import.meta.env.IMAGE_BASE_URL;
setUploadedImageUrl(
profileData.profileImageUrl
? `${imageBaseUrl}${profileData.profileImageUrl}`
: null,
);
setUploadedImageFile(null);
}
}, [profileData]);
const loadProfile = async () => {
const profileData = await refetchProfile();
useEffect(() => {
if (saveData?.success) {
showToast({
message: t('settingForm.successSaveProfile'),
severity: 'success',
});
setIsEditing(false);
setOriginalData(data);
setUploadedImageFile(null);
}
}, [saveData, data, showToast, t]);
if (!profileData) return;
if (profileData.success) {
const fetchedData = {
firstName: profileData.firstName ?? '',
lastName: profileData.lastName ?? '',
nationalCode: profileData.nationalCode ?? '',
gender: Object.values(Gender).includes(profileData.gender as Gender)
? (profileData.gender as Gender)
: Gender.None,
country: profileData.countryCode ?? '',
};
setData(fetchedData);
setOriginalData(fetchedData);
setUploadedImageUrl(
profileData.profileImageUrl
? `${imageBaseUrl}${profileData.profileImageUrl}`
: null,
);
setUploadedImageFile(null);
} else {
showToast({
message: profileData.message || t('message.serverError'),
severity: 'error',
});
}
};
loadProfile();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const initials = `${data?.firstName?.trim()[0] || ''}${data?.lastName?.trim()[0] || ''}`;
@@ -84,36 +81,35 @@ export function PersonalInformation() {
setUploadedImageFile(null);
};
const handleSaveClick = () => {
const handleSaveClick = async () => {
if (!data) return;
const isValid = infoRowEditRef.current?.validateFields?.();
if (!isValid) return;
executeSaveProfile({ data, imageUrl: uploadedImageFile });
};
const getErrorMessage = (error: unknown): string | null => {
if (!error) return null;
if (error instanceof Error) return error.message;
return String(error);
};
const saveData = await executeSaveProfile({
data,
imageUrl: uploadedImageFile,
});
useEffect(() => {
if (saveProfileError)
if (!saveData) return;
if (saveData?.success) {
showToast({
message:
getErrorMessage(saveProfileError) || t('settingForm.errorSave'),
message: t('settingForm.successSaveProfile'),
severity: 'success',
});
setIsEditing(false);
setOriginalData(data);
setUploadedImageFile(null);
// Force a refetch to update the cache with the new data
refetchProfile({ force: true });
} else {
showToast({
message: saveData.message || t('message.serverError'),
severity: 'error',
});
}, [saveProfileError, showToast, t]);
useEffect(() => {
if (fetchProfileError)
showToast({
message:
getErrorMessage(fetchProfileError) || t('settingForm.errorFetch'),
severity: 'error',
});
}, [fetchProfileError, showToast, t]);
}
};
return (
<PageWrapper>
@@ -163,14 +159,6 @@ export function PersonalInformation() {
{t('settingForm.editButton')}
</Button>
)}
{getErrorMessage(saveProfileError) && (
<Typography
color="error"
sx={{ mt: 1, textAlign: 'right', width: '100%' }}
>
{getErrorMessage(saveProfileError)}
</Typography>
)}
</Box>
}
>
@@ -186,13 +174,6 @@ export function PersonalInformation() {
>
<CircularProgress />
</Box>
) : fetchProfileError ? (
<Box sx={{ textAlign: 'center', p: 4 }}>
<Typography color="error">
{getErrorMessage(fetchProfileError) ||
t('settingForm.errorFetch')}
</Typography>
</Box>
) : (
<Box
sx={{