plane/web/store/issue/issue_calendar_view.store.ts

132 lines
3.8 KiB
TypeScript

import { observable, action, makeObservable, runInAction, computed } from "mobx";
// helpers
import { ICalendarPayload, ICalendarWeek } from "components/issues";
import { generateCalendarData } from "helpers/calendar.helper";
// types
import { getWeekNumberOfDate } from "helpers/date-time.helper";
import { computedFn } from "mobx-utils";
export interface ICalendarStore {
calendarFilters: {
activeMonthDate: Date;
activeWeekDate: Date;
};
calendarPayload: ICalendarPayload | null;
// action
updateCalendarFilters: (filters: Partial<{ activeMonthDate: Date; activeWeekDate: Date }>) => void;
updateCalendarPayload: (date: Date) => void;
// computed
allWeeksOfActiveMonth:
| {
[weekNumber: string]: ICalendarWeek;
}
| undefined;
activeWeekNumber: number;
allDaysOfActiveWeek: ICalendarWeek | undefined;
getStartAndEndDate: (layout: "week" | "month") => { startDate: string; endDate: string } | undefined;
}
export class CalendarStore implements ICalendarStore {
loader: boolean = false;
error: any | null = null;
// observables
calendarFilters: { activeMonthDate: Date; activeWeekDate: Date } = {
activeMonthDate: new Date(),
activeWeekDate: new Date(),
};
calendarPayload: ICalendarPayload | null = null;
constructor() {
makeObservable(this, {
loader: observable.ref,
error: observable.ref,
// observables
calendarFilters: observable.ref,
calendarPayload: observable.ref,
// actions
updateCalendarFilters: action,
updateCalendarPayload: action,
//computed
allWeeksOfActiveMonth: computed,
activeWeekNumber: computed,
allDaysOfActiveWeek: computed,
});
this.initCalendar();
}
get allWeeksOfActiveMonth() {
if (!this.calendarPayload) return undefined;
const { activeMonthDate } = this.calendarFilters;
return this.calendarPayload[`y-${activeMonthDate.getFullYear()}`][`m-${activeMonthDate.getMonth()}`];
}
get activeWeekNumber() {
return getWeekNumberOfDate(this.calendarFilters.activeWeekDate);
}
get allDaysOfActiveWeek() {
if (!this.calendarPayload) return undefined;
const { activeWeekDate } = this.calendarFilters;
return this.calendarPayload[`y-${activeWeekDate.getFullYear()}`][`m-${activeWeekDate.getMonth()}`][
`w-${this.activeWeekNumber - 1}`
];
}
getStartAndEndDate = computedFn((layout: "week" | "month") => {
switch (layout) {
case "week":
if (!this.allDaysOfActiveWeek) return;
const dates = Object.keys(this.allDaysOfActiveWeek);
return { startDate: dates[0], endDate: dates[dates.length - 1] };
case "month":
if (!this.allWeeksOfActiveMonth) return;
const weeks = Object.keys(this.allWeeksOfActiveMonth);
const firstWeekDates = Object.keys(this.allWeeksOfActiveMonth[weeks[0]]);
const lastWeekDates = Object.keys(this.allWeeksOfActiveMonth[weeks[weeks.length - 1]]);
return { startDate: firstWeekDates[0], endDate: lastWeekDates[lastWeekDates.length - 1] };
}
});
updateCalendarFilters = (filters: Partial<{ activeMonthDate: Date; activeWeekDate: Date }>) => {
this.updateCalendarPayload(filters.activeMonthDate || filters.activeWeekDate || new Date());
runInAction(() => {
this.calendarFilters = {
...this.calendarFilters,
...filters,
};
});
};
updateCalendarPayload = (date: Date) => {
if (!this.calendarPayload) return null;
const nextDate = new Date(date);
runInAction(() => {
this.calendarPayload = generateCalendarData(this.calendarPayload, nextDate);
});
};
initCalendar = () => {
const newCalendarPayload = generateCalendarData(null, new Date());
runInAction(() => {
this.calendarPayload = newCalendarPayload;
});
};
}