fix: dashboard api calls, multi profile fetch
This commit is contained in:
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user