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() : [];
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])
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 = {
42 type: WEEKLY_TYPE.ON_DAYS,
48 return { ...newFrequencyModel, monthly: { type: MONTHLY_TYPE.ON_NTH_DAY } };
51 if (changeToMinusNthDay) {
52 return { ...newFrequencyModel, monthly: { type: MONTHLY_TYPE.ON_MINUS_NTH_DAY } };
56 ends: { until: oldRecurringUntil },
59 if (oldRecurringUntil && isBefore(oldRecurringUntil, newStart.date)) {
60 newFrequencyModel.ends = {
61 ...frequencyModel.ends,
66 return newFrequencyModel;
69 export default getFrequencyModelChange;