import { action, observable, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { FieldView } from './FieldView'; import { DateField } from '../../../fields/DateField'; import { Doc } from '../../../fields/Doc'; import './TaskManagerTask.scss'; interface TaskManagerProps { Document: Doc; } @observer export class TaskManagerTask extends React.Component { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(TaskManagerTask, fieldStr); } @action updateText = (e: React.ChangeEvent) => { this.props.Document.text = e.target.value; }; @action updateTitle = (e: React.ChangeEvent) => { this.props.Document.title = e.target.value; }; @action updateAllDay = (e: React.ChangeEvent) => { this.props.Document.allDay = e.target.checked; if (e.target.checked) { delete this.props.Document.startTime; delete this.props.Document.endTime; } this.setTaskDateRange(); }; @action updateStart = (e: React.ChangeEvent) => { const newStart = new Date(e.target.value); this.props.Document.startTime = new DateField(newStart); const endDate = this.props.Document.endTime instanceof DateField ? this.props.Document.endTime.date : undefined; if (endDate && newStart > endDate) { // Alert user alert('Start time cannot be after end time. End time has been adjusted.'); // Fix end time const adjustedEnd = new Date(newStart.getTime() + 60 * 60 * 1000); this.props.Document.endTime = new DateField(adjustedEnd); } this.setTaskDateRange(); }; @action updateEnd = (e: React.ChangeEvent) => { const newEnd = new Date(e.target.value); this.props.Document.endTime = new DateField(newEnd); const startDate = this.props.Document.startTime instanceof DateField ? this.props.Document.startTime.date : undefined; if (startDate && newEnd < startDate) { // Alert user alert('End time cannot be before start time. Start time has been adjusted.'); // Fix start time const adjustedStart = new Date(newEnd.getTime() - 60 * 60 * 1000); this.props.Document.startTime = new DateField(adjustedStart); } this.setTaskDateRange(); }; @action setTaskDateRange() { const doc = this.props.Document; if (doc.allDay) { // All-day task → use date only if (!doc.title) return; const parsedDate = new Date(doc.title as string); if (!isNaN(parsedDate.getTime())) { const localStart = new Date(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()); const localEnd = new Date(localStart); doc.date_range = `${localStart.toISOString()}|${localEnd.toISOString()}`; doc.allDay = true; } } else { // Timed task → use full startTime and endTime const startField = doc.startTime; const endField = doc.endTime; const startDate = startField instanceof DateField ? startField.date : null; const endDate = endField instanceof DateField ? endField.date : null; if (startDate && endDate && !isNaN(startDate.getTime()) && !isNaN(endDate.getTime())) { doc.date_range = `${startDate.toISOString()}|${endDate.toISOString()}`; doc.allDay = false; } else { console.warn('startTime or endTime is invalid'); } } } @action toggleComplete = (e: React.ChangeEvent) => { this.props.Document.completed = e.target.checked; }; constructor(props: TaskManagerProps) { super(props); makeObservable(this); } componentDidMount() { this.setTaskDateRange(); } render() { function toLocalDateTimeString(date: Date): string { const pad = (n: number) => n.toString().padStart(2, '0'); return ( date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate()) + 'T' + pad(date.getHours()) + ':' + pad(date.getMinutes()) ); } const doc = this.props.Document; const taskDesc = typeof doc.text === 'string' ? doc.text : ''; const taskTitle = typeof doc.title === 'string' ? doc.title : ''; const allDay = !!doc.allDay; const isCompleted = !!this.props.Document.completed; const startTime = doc.startTime instanceof DateField && doc.startTime.date instanceof Date ? toLocalDateTimeString(doc.startTime.date) : ''; const endTime = doc.endTime instanceof DateField && doc.endTime.date instanceof Date ? toLocalDateTimeString(doc.endTime.date) : ''; return (