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

@@ -12,10 +12,11 @@ import { CardContainer } from '@/components/CardContainer';
import { useTranslation } from 'react-i18next';
import { ThemeToggleButton } from '@/components/ThemToggle';
import { PageWrapper } from '../components/PageWrapper';
import { Icon } from '@rkheftan/harmony-ui';
import { Icon, useToast } from '@rkheftan/harmony-ui';
import { Sun1, Moon, Calendar1 } from 'iconsax-react';
import { useApi } from '@/hooks/useApi';
import { fetchProfile, saveSettings } from '../api/settingsApi';
import { saveSettings } from '../api/settingsApi';
import { useProfile } from '../hooks/useProfile';
type ThemeMode = 'light' | 'dark';
type CalendarType = 'christian' | 'solar' | 'lunar';
@@ -51,40 +52,50 @@ export function SettingPage() {
const [draftSettings, setDraftSettings] =
useState<SettingsState>(savedSettings);
const [isEditing, setIsEditing] = useState(false);
const showToast = useToast();
const {
data: profileData,
loading: isFetching,
error: fetchError,
} = useApi(fetchProfile);
const { isLoadingProfile, refetchProfile } = useProfile();
const {
loading: isSaving,
error: saveError,
execute: executeSaveSettings,
} = useApi(saveSettings);
const { loading: isSaving, execute: executeSaveSettings } =
useApi(saveSettings);
useEffect(() => {
if (profileData?.success && profileData.userSettings) {
const { theme, calendarType, language } = profileData.userSettings;
const themeReverseMap: { [key: number]: ThemeMode | undefined } = {
1: 'light',
2: 'dark',
};
const newSettings: SettingsState = {
theme: themeReverseMap[theme] || 'light',
calendar:
calendarOptions.find((c) => c.apiValue === calendarType)?.key ||
'solar',
language:
languageOptions.find((l) => l.apiValue === language)?.code || 'en',
};
setSavedSettings(newSettings);
setDraftSettings(newSettings);
setMode(newSettings.theme);
i18n.changeLanguage(newSettings.language);
}
}, [profileData, setMode, i18n]);
const loadProfile = async () => {
const profileData = await refetchProfile();
if (!profileData) return;
if (profileData.success) {
if (!profileData.userSettings) return;
const { theme, calendarType, language } = profileData.userSettings;
const themeReverseMap: { [key: number]: ThemeMode | undefined } = {
1: 'light',
2: 'dark',
};
const newSettings: SettingsState = {
theme: themeReverseMap[theme] || 'light',
calendar:
calendarOptions.find((c) => c.apiValue === calendarType)?.key ||
'solar',
language:
languageOptions.find((l) => l.apiValue === language)?.code || 'en',
};
setSavedSettings(newSettings);
setDraftSettings(newSettings);
setMode(newSettings.theme);
i18n.changeLanguage(newSettings.language);
} else {
showToast({
message: profileData.message || t('message.serverError'),
severity: 'error',
});
}
};
loadProfile();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (isEditing) {
@@ -115,22 +126,27 @@ export function SettingPage() {
language: languageObj.apiValue,
});
if (!result) return;
if (result?.success) {
setMode(draftSettings.theme);
setSavedSettings(draftSettings);
i18n.changeLanguage(draftSettings.language);
setIsEditing(false);
refetchProfile({ force: true });
} else {
// Handle save failure
showToast({
message: result.message || t('message.serverError'),
severity: 'error',
});
}
}
} else {
setIsEditing(true);
}
};
const getErrorMessage = (error: unknown): string | null => {
if (!error) return null;
if (error instanceof Error) return error.message;
return String(error);
};
return (
<PageWrapper>
@@ -150,7 +166,7 @@ export function SettingPage() {
textTransform: 'none',
fontSize: { xs: '0.85rem', sm: '1rem' },
}}
disabled={isSaving || isFetching}
disabled={isSaving || isLoadingProfile}
>
{t('settings.rejectButton')}
</Button>
@@ -159,7 +175,7 @@ export function SettingPage() {
onClick={handleEditToggle}
size="large"
variant={isEditing ? 'contained' : 'outlined'}
disabled={isSaving || isFetching}
disabled={isSaving || isLoadingProfile}
>
{isSaving ? (
<CircularProgress size={24} />
@@ -172,7 +188,7 @@ export function SettingPage() {
</Box>
}
>
{isFetching ? (
{isLoadingProfile ? (
<Box
sx={{
display: 'flex',
@@ -184,12 +200,6 @@ export function SettingPage() {
>
<CircularProgress />
</Box>
) : fetchError ? (
<Box sx={{ textAlign: 'center', p: 4 }}>
<Typography color="error.main">
{getErrorMessage(fetchError)}
</Typography>
</Box>
) : (
<Box
sx={{
@@ -200,11 +210,6 @@ export function SettingPage() {
gap: 2,
}}
>
{getErrorMessage(saveError) && (
<Typography color="error.main" variant="body2" mb={2}>
{getErrorMessage(saveError)}
</Typography>
)}
<Box
sx={{
display: 'flex',