Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Charles Bochet
2026-02-23 12:01:37 +01:00
committed by GitHub
parent 22bc3004b9
commit b51eb6471f
538 changed files with 4664 additions and 4127 deletions
@@ -15,9 +15,9 @@ import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useTheme } from '@emotion/react';
import { t } from '@lingui/core/macro';
import 'react-datepicker/dist/react-datepicker.css';
import { useRecoilValue } from 'recoil';
import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { Temporal } from 'temporal-polyfill';
import { type Nullable } from 'twenty-shared/types';
import {
@@ -356,7 +356,7 @@ export const DatePicker = ({
const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const handleClear = () => {
closeDropdowns();
onClear?.();
@@ -13,7 +13,7 @@ import {
} from './DateTimePicker';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useRecoilValue } from 'recoil';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { Temporal } from 'temporal-polyfill';
import { SOURCE_LOCALE } from 'twenty-shared/translations';
import { isDefined } from 'twenty-shared/utils';
@@ -57,7 +57,7 @@ export const DatePickerHeader = ({
nextMonthButtonDisabled,
hideInput = false,
}: DatePickerHeaderProps) => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const userLocale = currentWorkspaceMember?.locale ?? SOURCE_LOCALE;
const dateParsed = isDefined(date) ? Temporal.PlainDate.from(date) : null;
@@ -12,8 +12,8 @@ import { DatePickerHeader } from '@/ui/input/components/internal/date/components
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useTheme } from '@emotion/react';
import 'react-datepicker/dist/react-datepicker.css';
import { useRecoilValue } from 'recoil';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { Temporal } from 'temporal-polyfill';
import { type Nullable } from 'twenty-shared/types';
import { isDefined, turnJSDateToPlainDate } from 'twenty-shared/utils';
@@ -328,7 +328,7 @@ export const DatePickerWithoutCalendar = ({
const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const closeDropdowns = () => {
closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
@@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { Select } from '@/ui/input/components/Select';
import { DateTimePickerInput } from '@/ui/input/components/internal/date/components/DateTimePickerInput';
@@ -61,7 +61,7 @@ export const DateTimePickerHeader = ({
nextMonthButtonDisabled,
hideInput = false,
}: DateTimePickerHeaderProps) => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const userLocale = currentWorkspaceMember?.locale ?? SOURCE_LOCALE;
return (
@@ -1,4 +1,5 @@
import { renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { RecoilRoot } from 'recoil';
import { Temporal } from 'temporal-polyfill';
@@ -6,6 +7,7 @@ import { DateFormat } from '@/localization/constants/DateFormat';
import { NumberFormat } from '@/localization/constants/NumberFormat';
import { TimeFormat } from '@/localization/constants/TimeFormat';
import { workspaceMemberFormatPreferencesState } from '@/localization/states/workspaceMemberFormatPreferencesState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useParseZonedDateTimeToIMaskDateTimeInputString } from '@/ui/input/components/internal/date/hooks/useParseZonedDateTimeToIMaskDateTimeInputString';
import { CalendarStartDay } from 'twenty-shared/constants';
@@ -21,21 +23,20 @@ describe('useParseZonedDateTimeToIMaskDateTimeInputString', () => {
const createWrapper =
(dateFormat: DateFormat) =>
({ children }: { children: React.ReactNode }) => (
<RecoilRoot
initializeState={(snapshot) => {
snapshot.set(workspaceMemberFormatPreferencesState, {
timeZone: 'Pacific/Auckland',
dateFormat,
timeFormat: TimeFormat.HOUR_24,
numberFormat: NumberFormat.COMMAS_AND_DOT,
calendarStartDay: CalendarStartDay.MONDAY,
});
}}
>
{children}
</RecoilRoot>
);
({ children }: { children: React.ReactNode }) => {
jotaiStore.set(workspaceMemberFormatPreferencesState.atom, {
timeZone: 'Pacific/Auckland',
dateFormat,
timeFormat: TimeFormat.HOUR_24,
numberFormat: NumberFormat.COMMAS_AND_DOT,
calendarStartDay: CalendarStartDay.MONDAY,
});
return (
<JotaiProvider store={jotaiStore}>
<RecoilRoot>{children}</RecoilRoot>
</JotaiProvider>
);
};
it('should format with day first format (DD/MM/YYYY, HH:mm)', () => {
const { result } = renderHook(
@@ -1,8 +1,10 @@
import { renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { RecoilRoot } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
describe('useUserTimezone', () => {
const originalIntl = global.Intl;
@@ -24,7 +26,9 @@ describe('useUserTimezone', () => {
it('should return system timezone when currentWorkspaceMember is null', () => {
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<RecoilRoot>{children}</RecoilRoot>
<JotaiProvider store={jotaiStore}>
<RecoilRoot>{children}</RecoilRoot>
</JotaiProvider>
);
const { result } = renderHook(() => useUserTimezone(), {
@@ -36,32 +40,30 @@ describe('useUserTimezone', () => {
});
it('should return system timezone when currentWorkspaceMember.timeZone is "system"', () => {
jotaiStore.set(currentWorkspaceMemberState.atom, {
id: 'workspace-member-id',
name: {
firstName: 'John',
lastName: 'Doe',
},
colorScheme: 'Light',
locale: 'en-US',
userEmail: 'john@example.com',
timeZone: 'system',
dateFormat: null,
timeFormat: null,
numberFormat: null,
calendarStartDay: null,
});
const WrapperWithSystemTimezone = ({
children,
}: {
children: React.ReactNode;
}) => (
<RecoilRoot
initializeState={(snapshot) => {
snapshot.set(currentWorkspaceMemberState, {
id: 'workspace-member-id',
name: {
firstName: 'John',
lastName: 'Doe',
},
colorScheme: 'Light',
locale: 'en-US',
userEmail: 'john@example.com',
timeZone: 'system',
dateFormat: null,
timeFormat: null,
numberFormat: null,
calendarStartDay: null,
});
}}
>
{children}
</RecoilRoot>
<JotaiProvider store={jotaiStore}>
<RecoilRoot>{children}</RecoilRoot>
</JotaiProvider>
);
const { result } = renderHook(() => useUserTimezone(), {
@@ -75,32 +77,30 @@ describe('useUserTimezone', () => {
it('should return user-specific timezone when currentWorkspaceMember.timeZone is set', () => {
const userTimezone = 'Europe/Paris';
jotaiStore.set(currentWorkspaceMemberState.atom, {
id: 'workspace-member-id',
name: {
firstName: 'John',
lastName: 'Doe',
},
colorScheme: 'Light',
locale: 'en-US',
userEmail: 'john@example.com',
timeZone: userTimezone,
dateFormat: null,
timeFormat: null,
numberFormat: null,
calendarStartDay: null,
});
const WrapperWithUserTimezone = ({
children,
}: {
children: React.ReactNode;
}) => (
<RecoilRoot
initializeState={(snapshot) => {
snapshot.set(currentWorkspaceMemberState, {
id: 'workspace-member-id',
name: {
firstName: 'John',
lastName: 'Doe',
},
colorScheme: 'Light',
locale: 'en-US',
userEmail: 'john@example.com',
timeZone: userTimezone,
dateFormat: null,
timeFormat: null,
numberFormat: null,
calendarStartDay: null,
});
}}
>
{children}
</RecoilRoot>
<JotaiProvider store={jotaiStore}>
<RecoilRoot>{children}</RecoilRoot>
</JotaiProvider>
);
const { result } = renderHook(() => useUserTimezone(), {
@@ -1,9 +1,9 @@
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useRecoilValue } from 'recoil';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { WorkspaceMemberDateFormatEnum } from '~/generated-metadata/graphql';
export const useUserDateFormat = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const userDateFormat =
currentWorkspaceMember?.dateFormat ?? WorkspaceMemberDateFormatEnum.SYSTEM;
@@ -1,6 +1,6 @@
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { detectCalendarStartDay } from '@/localization/utils/detection/detectCalendarStartDay';
import { useRecoilValue } from 'recoil';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { CalendarStartDay } from 'twenty-shared/constants';
import {
convertCalendarStartDayNonIsoNumberToFirstDayOfTheWeek,
@@ -8,7 +8,7 @@ import {
} from 'twenty-shared/utils';
export const useUserFirstDayOfTheWeek = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const systemFirstDayOfTheWeek = detectCalendarStartDay();
const isSystemFirstDayOfTheWeek =
@@ -1,9 +1,9 @@
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useRecoilValue } from 'recoil';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { WorkspaceMemberTimeFormatEnum } from '~/generated-metadata/graphql';
export const useUserTimeFormat = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const userTimeFormat =
currentWorkspaceMember?.timeFormat ?? WorkspaceMemberTimeFormatEnum.SYSTEM;
@@ -1,8 +1,8 @@
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useRecoilValue } from 'recoil';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
export const useUserTimezone = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const systemTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const userTimezone =