[#341] added show week number toggle (#399)

* [#341] added show week number toggle
This commit is contained in:
Camille Moussu
2025-12-11 11:41:38 +01:00
committed by GitHub
parent 3cb445ea79
commit e8b1b72901
8 changed files with 114 additions and 32 deletions
+73 -29
View File
@@ -26,6 +26,7 @@ import {
setTimeZone as setSettingsTimeZone,
setIsBrowserDefaultTimeZone,
setHideDeclinedEvents,
setDisplayWeekNumbers,
} from "./SettingsSlice";
import {
updateUserConfigurationsAsync,
@@ -74,6 +75,10 @@ export default function SettingsPage() {
(state) => state.settings?.hideDeclinedEvents
);
const displayWeekNumbers = useAppSelector(
(state) => state.settings?.displayWeekNumbers
);
const [activeNavItem, setActiveNavItem] =
useState<SidebarNavItem>("settings");
const [activeSettingsSubTab, setActiveSettingsSubTab] =
@@ -83,7 +88,8 @@ export default function SettingsPage() {
const [alarmEmailsErrorOpen, setAlarmEmailsErrorOpen] = useState(false);
const [hideDeclinedEventsErrorOpen, setHideDeclinedEventsErrorOpen] =
useState(false);
const [displayWeekNumbersErrorOpen, setDisplayWeekNumbersErrorOpen] =
useState(false);
const handleBackClick = () => {
dispatch(setView("calendar"));
};
@@ -221,6 +227,27 @@ export default function SettingsPage() {
setAlarmEmailsErrorOpen(false);
};
const handleDisplayWeekNumbers = (doDisplayWeekNumbers: boolean) => {
// Optimistic update - update UI immediately
dispatch(setDisplayWeekNumbers(doDisplayWeekNumbers));
// Call API in background, don't wait for it
dispatch(
updateUserConfigurationsAsync({
displayWeekNumbers: doDisplayWeekNumbers,
})
)
.unwrap()
.catch((error) => {
console.error("Failed to update the week number setting:", error);
dispatch(setDisplayWeekNumbers(!doDisplayWeekNumbers));
setDisplayWeekNumbersErrorOpen(true);
});
};
const handleDisplayWeekNumbersErrorClose = () => {
setDisplayWeekNumbersErrorOpen(false);
};
return (
<main className="main-layout settings-layout">
<Box className="settings-sidebar">
@@ -344,37 +371,48 @@ export default function SettingsPage() {
</FormControl>
</Box>
</Box>
<Box>
<Box sx={{ mb: 6 }}>
<Typography variant="h6" sx={{ mb: 1 }}>
{t("settings.calAndEvent")}
</Typography>
<Box
sx={{
mb: 6,
}}
>
<FormControl size="small" sx={{ minWidth: 500 }}>
<FormControlLabel
control={
<Switch
checked={Boolean(!hideDeclinedEvents)}
onChange={() =>
handleHideDeclinedEvents(!hideDeclinedEvents)
}
aria-label={t("settings.showDeclinedEvent")}
/>
}
label={t("settings.showDeclinedEvent")}
labelPlacement="start"
sx={{
minWidth: 400,
justifyContent: "space-between",
marginLeft: 0,
mb: 2,
}}
/>
</FormControl>
</Box>
<FormControl size="small" sx={{ minWidth: 500 }}>
<FormControlLabel
control={
<Switch
checked={Boolean(!hideDeclinedEvents)}
onChange={() =>
handleHideDeclinedEvents(!hideDeclinedEvents)
}
aria-label={t("settings.showDeclinedEvent")}
/>
}
label={t("settings.showDeclinedEvent")}
labelPlacement="start"
sx={{
minWidth: 400,
justifyContent: "space-between",
marginLeft: 0,
}}
/>
<FormControlLabel
control={
<Switch
checked={Boolean(displayWeekNumbers)}
onChange={() =>
handleDisplayWeekNumbers(!displayWeekNumbers)
}
aria-label={t("settings.displayWeekNumbers")}
/>
}
label={t("settings.displayWeekNumbers")}
labelPlacement="start"
sx={{
minWidth: 400,
justifyContent: "space-between",
marginLeft: 0,
}}
/>
</FormControl>
</Box>
</Box>
)}
@@ -449,6 +487,12 @@ export default function SettingsPage() {
onClose={handleHideDeclinedEventsErrorClose}
message={t("settings.hideDeclinedEventsUpdateError")}
/>
<Snackbar
open={displayWeekNumbersErrorOpen}
autoHideDuration={4000}
onClose={handleDisplayWeekNumbersErrorClose}
message={t("settings.displayWeekNumbersUpdateError")}
/>
</main>
);
}
+18
View File
@@ -7,6 +7,7 @@ export interface SettingsState {
timeZone: string | null; // Allow null to represent browser default
isBrowserDefaultTimeZone: boolean;
hideDeclinedEvents: boolean | null;
displayWeekNumbers: boolean;
view: "calendar" | "settings" | "search";
}
@@ -23,6 +24,7 @@ const initialState: SettingsState = {
timeZone: defaultTimeZone,
isBrowserDefaultTimeZone: defaultTimeZone === null,
hideDeclinedEvents: null,
displayWeekNumbers: true,
view: "calendar",
};
@@ -44,6 +46,9 @@ export const settingsSlice = createSlice({
setHideDeclinedEvents: (state, action: PayloadAction<boolean | null>) => {
state.hideDeclinedEvents = action.payload;
},
setDisplayWeekNumbers: (state, action: PayloadAction<boolean>) => {
state.displayWeekNumbers = action.payload;
},
setView: (
state,
action: PayloadAction<"calendar" | "settings" | "search">
@@ -80,6 +85,18 @@ export const settingsSlice = createSlice({
typeof hideDeclinedEventsConfig?.value === "boolean"
? hideDeclinedEventsConfig.value
: null;
const calendarModule = action.payload.configurations.modules.find(
(module: any) => module.name === "calendar"
);
if (calendarModule?.configurations) {
const alarmEmailsConfig = calendarModule.configurations.find(
(config: any) => config.name === "displayWeekNumbers"
);
if (alarmEmailsConfig) {
state.displayWeekNumbers = alarmEmailsConfig.value === true;
}
}
});
},
});
@@ -90,5 +107,6 @@ export const {
setView,
setIsBrowserDefaultTimeZone,
setHideDeclinedEvents,
setDisplayWeekNumbers,
} = settingsSlice.actions;
export default settingsSlice.reducer;
+7
View File
@@ -38,6 +38,7 @@ export interface UserConfigurationUpdates {
language?: string;
notifications?: Record<string, unknown>;
timezone?: string | null;
displayWeekNumbers?: boolean;
previousConfig?: Record<string, any>;
alarmEmails?: boolean;
hideDeclinedEvents?: boolean;
@@ -77,6 +78,12 @@ export async function updateUserConfigurations(
value: updates.hideDeclinedEvents,
});
}
if (updates.displayWeekNumbers !== undefined) {
calendarConfigs.push({
name: "displayWeekNumbers",
value: updates.displayWeekNumbers,
});
}
const modules: Array<{
name: string;