diff --git a/.eslintrc.json b/.eslintrc.json index 8566e25..15e8e01 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -110,7 +110,7 @@ "ignoreEnums": true, "enforceConst": true, "ignoreReadonlyClassProperties": true, - "ignore": [0, 1, 2] + "ignore": [0, 1, 2, 1000] } ], "@typescript-eslint/brace-style": ["error", "1tbs"], diff --git a/src/helpers/datetime.ts b/src/helpers/datetime.ts new file mode 100644 index 0000000..d402991 --- /dev/null +++ b/src/helpers/datetime.ts @@ -0,0 +1,9 @@ +export const DateFormat = "yyyy-MM-dd"; +export const TimeFormat = "HH:mm"; + +/** + * Converts a JS date to epoch timestamp. + * @param date Date in JS `Date` class + */ +export const dateTimeToUnixTime = (date: Date) => + parseInt((date.getTime() / 1000).toFixed(0)); diff --git a/src/views/assets/locales.ts b/src/views/assets/locales.ts index 3a12260..abd5276 100644 --- a/src/views/assets/locales.ts +++ b/src/views/assets/locales.ts @@ -34,6 +34,8 @@ export default new LocalizedStrings({ editor_textTp: "Text:", editor_parentTp: "Parent:", editor_parentNoParentVal: "No parent", + editor_deadline: "Deadline:", + editor_reminder: "Reminder:", task_toggleBtnCompleted: "Completed", task_toggleBtnPending: "Pending", app_versionString: `${appFullName} v${appVersion} by ${appAuthor}`, diff --git a/src/views/components/dateTimePicker.tsx b/src/views/components/dateTimePicker.tsx new file mode 100644 index 0000000..0b8ccae --- /dev/null +++ b/src/views/components/dateTimePicker.tsx @@ -0,0 +1,67 @@ +import React from "react"; +import parse from "date-fns/parse"; +import format from "date-fns/format"; + +import { + dateTimeToUnixTime, + DateFormat, + TimeFormat, +} from "../../helpers/datetime"; + +interface Props { + dateRequired?: boolean; + timeRequired?: boolean; + initialValue?: number; + onChange?: (date: number) => void; +} +interface State { + date: Date; +} +export class DateTimePicker extends React.Component { + state = { + date: new Date(this.props.initialValue || 0), + }; + componentDidUpdate = (_p: Props, prevState: State) => { + if (this.props.onChange) { + if (prevState.date !== this.state.date) { + this.props.onChange(dateTimeToUnixTime(this.state.date)); + } + } + }; + updateDate = (e: React.FormEvent) => { + // event input is a string of format like "2020-01-03" + // eslint-disable-next-line react/no-access-state-in-setstate + const date = parse(e.currentTarget.value, DateFormat, this.state.date); + this.setState({ date }); + }; + updateTime = (e: React.FormEvent) => { + // input is a string of format like "13:45" + // eslint-disable-next-line react/no-access-state-in-setstate + const date = parse(e.currentTarget.value, TimeFormat, this.state.date); + this.setState({ date }); + }; + inputInitValue = (date: Date, fmt: string): string => { + if (date.getTime()) { + return format(date, fmt); + } + return ""; + }; + render = () => ( +
+ + +
+ ); +} + +export default DateTimePicker; diff --git a/src/views/editorView.tsx b/src/views/editorView.tsx index d78ad8b..78d0b1d 100644 --- a/src/views/editorView.tsx +++ b/src/views/editorView.tsx @@ -8,6 +8,7 @@ import Input from "./components/bulma/input"; import Field from "./components/bulma/field"; import Level from "./components/bulma/level"; import TaskSelect from "./components/taskSelect"; +import DateTimePicker from "./components/dateTimePicker"; import { deleteTask, updateTask, createTask } from "../actions/tasks"; import { hotkeyHandler, escCode, Hotkey } from "./helpers/keyboard"; @@ -88,6 +89,8 @@ class EditorView extends React.Component { Text: "", ID: 0, PID: 0, + Deadline: 0, + Reminder: 0, } as Task, newTask: false, title: "", @@ -134,18 +137,28 @@ class EditorView extends React.Component { updateText = (e: React.FormEvent) => { const { task } = this.state; task.Text = e.currentTarget.value; - this.setState(() => ({ task })); + this.setState({ task }); }; updateStatus = () => { const { task } = this.state; task.Completed = !task.Completed; - this.setState(() => ({ task })); + this.setState({ task }); }; updateParent = (e: React.FormEvent) => { const newPID = parseInt(e.currentTarget.value); const { task } = this.state; task.PID = newPID; - this.setState(() => ({ task })); + this.setState({ task }); + }; + updateDeadline = (date: number) => { + const { task } = this.state; + task.Deadline = date; + this.setState({ task }); + }; + updateReminder = (date: number) => { + const { task } = this.state; + task.Reminder = date; + this.setState({ task }); }; saveChanges = () => { if (this.state.newTask) { @@ -235,6 +248,24 @@ class EditorView extends React.Component { /> } /> + + } + /> + + } + />