Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / applications / calendar / src / app / components / eventModal / hooks / useDateTimeFormHandlers.ts
blob29c46d33e5d04abc9cce6838b45fea6840da25db
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';
5 import {
6     convertUTCDateTimeToZone,
7     convertZonedDateTimeToUTC,
8     fromUTCDate,
9     toUTCDate,
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 {
19     model: EventModel;
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;
38     };
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);
50         return {
51             start: newStart,
52             end: newEnd,
53         };
54     };
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);
68     };
70     const handleChangeStartDate = (newDate: Date | undefined) => {
71         if (!newDate || !isValid(newDate)) {
72             return;
73         }
74         const newStart = { ...start, date: newDate };
75         setModel({
76             ...model,
77             frequencyModel: getFrequencyModelChange(start, newStart, model.frequencyModel),
78             ...getStartChange(newStart),
79         });
80     };
82     const handleChangeStartTime = (newTime: Date) => {
83         setModel({
84             ...model,
85             ...getStartChange({
86                 ...start,
87                 time: newTime,
88             }),
89         });
90     };
92     const handleEndUpdate = (newEnd: DateTimeModel) => {
93         setModel({
94             ...model,
95             end: newEnd,
96         });
97     };
99     const handleChangeEndDate = (newDate: Date | undefined) => {
100         if (!newDate || !isValid(newDate)) {
101             return;
102         }
103         handleEndUpdate({
104             ...end,
105             date: newDate,
106         });
107     };
109     const handleChangeEndTime = (newTime: Date) => {
110         handleEndUpdate(getEndTimeChange(newTime));
111     };
112     return {
113         handleChangeStartDate,
114         handleChangeStartTime,
115         handleChangeEndDate,
116         handleChangeEndTime,
117         minEndDate,
118         minEndTime,
119         isDuration,
120     };
123 export default useDateTimeFormHandlers;