feat: allow users to start the calendar week on Monday (#13295)

resolve twentyhq/core-team-issues#1255
- Introduced a new field isWeekStartMonday in the workspaceMember table.

- Added a function updateCalendarStartDay to update the
isWeekStartMonday value when the user toggles the corresponding field in
the settings.

The logic works for me, but I couldn’t find a way to create the column
locally in the database for the workspaceMember tables. Please let me
know if this approach looks good and how to properly create dynamic
columns that are not directly handled via migration.


https://github.com/user-attachments/assets/4eebada5-6a96-4a88-8e96-98f1501859e3

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Naifer
2025-07-30 11:46:05 +01:00
committed by GitHub
parent 1972e2fbf7
commit ad69ed9aba
31 changed files with 507 additions and 136 deletions
@@ -0,0 +1,42 @@
import { useMemo } from 'react';
import { SELECT_DAY_DROPDOWN_ID } from '@/ui/input/components/internal/date/constants/SelectDayDropdownId';
import { DayNameWithIndex } from '@/ui/input/components/internal/date/types/DayNameWithIndex';
import { Select } from '@/ui/input/components/Select';
import { SelectOption } from 'twenty-ui/input';
export const DaySelect = ({
label,
selectedDayIndex,
onChange,
dayList,
}: {
label: string;
selectedDayIndex: number;
onChange: (dayIndex: number | string) => void;
dayList: DayNameWithIndex[];
}) => {
const options: SelectOption<string | number>[] = useMemo(() => {
const days = dayList?.map<SelectOption<string | number>>(
({ day, index }) => ({
label: day,
value: index,
}),
);
return days;
}, [dayList]);
return (
<Select
fullWidth
dropdownId={SELECT_DAY_DROPDOWN_ID}
options={options}
label={label}
onChange={onChange}
value={selectedDayIndex}
dropdownWidth={218}
dropdownWidthAuto
/>
);
};
@@ -4,6 +4,9 @@ import { lazy, Suspense, useContext } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CalendarStartDay } from '@/localization/constants/CalendarStartDay';
import { detectCalendarStartDay } from '@/localization/utils/detectCalendarStartDay';
import { AbsoluteDatePickerHeader } from '@/ui/input/components/internal/date/components/AbsoluteDatePickerHeader';
import { DateTimeInput } from '@/ui/input/components/internal/date/components/DateTimeInput';
import { RelativeDatePickerHeader } from '@/ui/input/components/internal/date/components/RelativeDatePickerHeader';
@@ -17,6 +20,7 @@ import {
import { useTheme } from '@emotion/react';
import { t } from '@lingui/core/macro';
import 'react-datepicker/dist/react-datepicker.css';
import { useRecoilValue } from 'recoil';
import { IconCalendarX } from 'twenty-ui/display';
import {
MenuItemLeftContent,
@@ -343,7 +347,7 @@ export const DateTimePicker = ({
const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const handleClear = () => {
closeDropdowns();
onClear?.();
@@ -501,6 +505,12 @@ export const DateTimePicker = ({
openToDate={hasDate ? dateToUse : new Date()}
disabledKeyboardNavigation
onChange={handleDateChange as any}
calendarStartDay={
currentWorkspaceMember?.calendarStartDay ===
CalendarStartDay.SYSTEM
? CalendarStartDay[detectCalendarStartDay()]
: (currentWorkspaceMember?.calendarStartDay ?? undefined)
}
customInput={
<DateTimeInput
date={internalDate}
@@ -0,0 +1 @@
export const SELECT_DAY_DROPDOWN_ID = 'select-day-dropdown-Id';
@@ -0,0 +1,4 @@
export type DayNameWithIndex = {
day: string;
index: number;
};