Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / applications / calendar / src / app / components / eventModal / eventForm / getFrequencyModelChange.ts
blobdb772cb1fdb0225d39c296994c54da273fb23721
1 import { isBefore } from 'date-fns';
3 import { MONTHLY_TYPE, WEEKLY_TYPE } from '@proton/shared/lib/calendar/constants';
4 import { getNegativeSetpos, getPositiveSetpos } from '@proton/shared/lib/calendar/recurrence/rrule';
5 import { fromLocalDate, toUTCDate } from '@proton/shared/lib/date/timezone';
6 import type { DateTimeModel, FrequencyModel } from '@proton/shared/lib/interfaces/calendar';
7 import replace from '@proton/utils/replace';
9 const getFrequencyModelChange = (
10     oldStart: DateTimeModel,
11     newStart: DateTimeModel,
12     frequencyModel: FrequencyModel
13 ): FrequencyModel => {
14     // change days in weekly
15     const oldStartDay = oldStart.date.getDay();
16     const newStartDay = newStart.date.getDay();
17     const oldDays = frequencyModel.weekly && frequencyModel.weekly.days;
18     const newDays = oldDays ? replace(oldDays, oldStartDay, newStartDay).sort() : [];
20     /**
21      * Notice that after replacement we may end up with repeated days in the newDays array.
22      * That would indicate that the user entered a multiple-day selection, and we want to keep track of that.
23      * Notice that if we filtered by unique days, an initial two-day selection of e.g. MO and WE (oldDays = [1,3]), with
24      * the recurring event starting on MO, would be changed into a one-day selection if the user moves
25      * the starting starting date of the event to a WE, i.e. (newDays = [3]). If the user changes her mind again and moves
26      * the starting date to a TH now, we would display a single-day selection (newDays = [4]), but from a UX
27      * perspective it makes more sense to display a two-day selection WE and TH (i.e. newDays = [4, 4])
28      */
30     const startFakeUtcDate = toUTCDate(fromLocalDate(newStart.date));
32     // change monthly type
33     const changeToNthDay =
34         frequencyModel.monthly.type === MONTHLY_TYPE.ON_MINUS_NTH_DAY && getNegativeSetpos(startFakeUtcDate) !== -1;
36     const changeToMinusNthDay =
37         frequencyModel.monthly.type === MONTHLY_TYPE.ON_NTH_DAY && getPositiveSetpos(startFakeUtcDate) === 5;
39     const newFrequencyModel = {
40         ...frequencyModel,
41         weekly: {
42             type: WEEKLY_TYPE.ON_DAYS,
43             days: newDays,
44         },
45     };
47     if (changeToNthDay) {
48         return { ...newFrequencyModel, monthly: { type: MONTHLY_TYPE.ON_NTH_DAY } };
49     }
51     if (changeToMinusNthDay) {
52         return { ...newFrequencyModel, monthly: { type: MONTHLY_TYPE.ON_MINUS_NTH_DAY } };
53     }
55     const {
56         ends: { until: oldRecurringUntil },
57     } = frequencyModel;
59     if (oldRecurringUntil && isBefore(oldRecurringUntil, newStart.date)) {
60         newFrequencyModel.ends = {
61             ...frequencyModel.ends,
62             until: newStart.date,
63         };
64     }
66     return newFrequencyModel;
69 export default getFrequencyModelChange;