1 import { addDays, isValid } from 'date-fns';
3 import { DAY } from '@proton/shared/lib/constants';
4 import { startOfDay } from '@proton/shared/lib/date-fns-utc';
6 convertUTCDateTimeToZone,
7 convertZonedDateTimeToUTC,
10 } from '@proton/shared/lib/date/timezone';
11 import type { DateTimeModel, EventModel } from '@proton/shared/lib/interfaces/calendar';
13 import getFrequencyModelChange from '../eventForm/getFrequencyModelChange';
14 import { getDateTimeState, getTimeInUtc } from '../eventForm/time';
16 const DEFAULT_MIN_TIME = new Date(Date.UTC(2000, 0, 1, 0, 0));
18 interface UseDateTimeFormHandlersArgs {
20 setModel: (value: EventModel) => void;
23 const useDateTimeFormHandlers = ({ model, setModel }: UseDateTimeFormHandlersArgs) => {
24 const { isAllDay, start, end } = model;
26 const startUtcDate = getTimeInUtc(start, false);
27 const endUtcDate = getTimeInUtc(end, false);
29 const isDuration = +endUtcDate - +startUtcDate < DAY;
30 const minEndTimeInTimezone = toUTCDate(convertUTCDateTimeToZone(fromUTCDate(startUtcDate), end.tzid));
31 const { time: minEndTime } = getDateTimeState(isDuration ? minEndTimeInTimezone : DEFAULT_MIN_TIME, '');
33 const getMinEndDate = () => {
34 const { date: minDate } = getDateTimeState(minEndTimeInTimezone, '');
35 // If the minDate with the currently selected end time would lead to an error, don't allow it to be selected
36 const minTimeUtcDate = getTimeInUtc({ ...end, date: minDate, time: end.time }, false);
37 return startUtcDate > minTimeUtcDate ? addDays(minDate, 1) : minDate;
40 const minEndDate = isAllDay ? start.date : getMinEndDate();
42 const getStartChange = (newStart: DateTimeModel) => {
43 const newStartUtcDate = getTimeInUtc(newStart, false);
44 const diffInMs = +newStartUtcDate - +startUtcDate;
46 const newEndDate = new Date(+endUtcDate + diffInMs);
47 const endLocalDate = toUTCDate(convertUTCDateTimeToZone(fromUTCDate(newEndDate), end.tzid));
48 const newEnd = getDateTimeState(endLocalDate, end.tzid);
56 const getEndTimeChange = (newTime: Date) => {
57 const diffMs = +newTime - +minEndTime;
59 const endTimeInTimezone = toUTCDate(convertUTCDateTimeToZone(fromUTCDate(endUtcDate), end.tzid));
61 const minEndUtcDateBase = isDuration ? minEndTimeInTimezone : startOfDay(endTimeInTimezone);
63 const endUtcDateBase = toUTCDate(convertZonedDateTimeToUTC(fromUTCDate(minEndUtcDateBase), end.tzid));
64 const newEndUtcDate = new Date(+endUtcDateBase + diffMs);
65 const endLocalDate = toUTCDate(convertUTCDateTimeToZone(fromUTCDate(newEndUtcDate), end.tzid));
67 return getDateTimeState(endLocalDate, end.tzid);
70 const handleChangeStartDate = (newDate: Date | undefined) => {
71 if (!newDate || !isValid(newDate)) {
74 const newStart = { ...start, date: newDate };
77 frequencyModel: getFrequencyModelChange(start, newStart, model.frequencyModel),
78 ...getStartChange(newStart),
82 const handleChangeStartTime = (newTime: Date) => {
92 const handleEndUpdate = (newEnd: DateTimeModel) => {
99 const handleChangeEndDate = (newDate: Date | undefined) => {
100 if (!newDate || !isValid(newDate)) {
109 const handleChangeEndTime = (newTime: Date) => {
110 handleEndUpdate(getEndTimeChange(newTime));
113 handleChangeStartDate,
114 handleChangeStartTime,
123 export default useDateTimeFormHandlers;