import { Calendar, EventClickArg, EventSourceInput } from '@fullcalendar/core'; import dayGridPlugin from '@fullcalendar/daygrid'; import multiMonthPlugin from '@fullcalendar/multimonth'; import { makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { dateRangeStrToDates } from '../../../../Utils'; import { Doc } from '../../../../fields/Doc'; import { StrCast } from '../../../../fields/Types'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { FieldView, FieldViewProps } from '../FieldView'; type CalendarView = 'month' | 'multi-month' | 'week'; @observer export class CalendarBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string = 'calendar') { return FieldView.LayoutString(CalendarBox, fieldKey); } constructor(props: FieldViewProps) { super(props); makeObservable(this); } componentDidMount(): void {} componentWillUnmount(): void {} _calendarRef = React.createRef(); get dateRangeStr() { return StrCast(this.Document.date_range); } // Choose a calendar view based on the date range get calendarViewType(): CalendarView { const [fromDate, toDate] = dateRangeStrToDates(this.dateRangeStr); if (fromDate.getFullYear() !== toDate.getFullYear() || fromDate.getMonth() !== toDate.getMonth()) return 'multi-month'; if (Math.abs(fromDate.getDay() - toDate.getDay()) > 7) return 'month'; return 'week'; } get calendarStartDate() { return this.dateRangeStr.split('|')[0]; } get calendarToDate() { return this.dateRangeStr.split('|')[1]; } get childDocs(): Doc[] { return this.childDocs; // get all sub docs for a calendar } docBackgroundColor(type: string): string { // TODO: Return a different color based on the event type return 'blue'; } get calendarEvents(): EventSourceInput | undefined { if (this.childDocs.length === 0) return undefined; return this.childDocs.map((doc, idx) => { const docTitle = StrCast(doc.title); const docDateRange = StrCast(doc.date_range); const [startDate, endDate] = dateRangeStrToDates(docDateRange); const docType = doc.type; const docDescription = doc.description ? StrCast(doc.description) : ''; return { title: docTitle, start: startDate, end: endDate, allDay: false, classNames: [StrCast(docType)], // will determine the style editable: false, // subject to change in the future backgroundColor: this.docBackgroundColor(StrCast(doc.type)), color: 'white', extendedProps: { description: docDescription, }, }; }); } handleEventClick = (arg: EventClickArg) => { // TODO: open popover with event description, option to open CalendarManager and change event date, delete event, etc. }; calendarEl: HTMLElement = document.getElementById('calendar-box-v1')!; // https://fullcalendar.io get calendar() { return new Calendar(this.calendarEl, { plugins: [this.calendarViewType === 'multi-month' ? multiMonthPlugin : dayGridPlugin], headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek', }, initialDate: this.calendarStartDate, navLinks: true, editable: false, displayEventTime: false, displayEventEnd: false, events: this.calendarEvents, eventClick: this.handleEventClick, }); } render() { return (
); } }