diff --git a/src/helpers/datetime.ts b/src/helpers/datetime.ts index 19644c7..7ee5aba 100644 --- a/src/helpers/datetime.ts +++ b/src/helpers/datetime.ts @@ -1,8 +1,16 @@ +import format from "date-fns/format"; + export const DateFormat = "yyyy-MM-dd"; export const TimeFormat = "HH:mm"; /** - * Converts a JS date to epoch timestamp. + * Converts a JS date to epoch timestamp. Returns `0` on error. * @param date Date in JS `Date` class */ -export const dateTimeToUnixTime = (date: Date) => date.getTime(); +export const dateTimeToUnixTime = (date: Date) => date.getTime() || 0; + +/** + * Expands a Unix epoch timestamp into a string that looks like this: + * "05/29/1453, 12:00 AM" + */ +export const fmtDate = (date: number) => format(new Date(date), "Pp"); diff --git a/src/views/components/dateTimePicker.tsx b/src/views/components/dateTimePicker.tsx index 826b9fc..89aacf8 100644 --- a/src/views/components/dateTimePicker.tsx +++ b/src/views/components/dateTimePicker.tsx @@ -8,6 +8,9 @@ import { TimeFormat, } from "../../helpers/datetime"; +/** Helper for `new Date()`. */ +const FDate = (v: number | undefined) => new Date(v || 0); + interface Props { dateRequired?: boolean; timeRequired?: boolean; @@ -19,14 +22,17 @@ interface State { } export class DateTimePicker extends React.Component { state = { - date: new Date(this.props.initialValue || 0), + date: FDate(this.props.initialValue), }; - componentDidUpdate = (_p: Props, prevState: State) => { + componentDidUpdate = (prevProps: Props, prevState: State) => { if (this.props.onChange) { if (prevState.date !== this.state.date) { this.props.onChange(dateTimeToUnixTime(this.state.date)); } } + if (this.props.initialValue !== prevProps.initialValue) { + this.setState({ date: FDate(this.props.initialValue) }); + } }; updateDate = (e: React.FormEvent) => { // event input is a string of format like "2020-01-03" @@ -40,29 +46,33 @@ export class DateTimePicker extends React.Component { 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); + // TODO: add an "Unset" button + render = () => { + let date, time; + try { + date = format(this.state.date, DateFormat); + time = format(this.state.date, TimeFormat); + } catch { + date = ""; + time = ""; } - return ""; + return ( +
+ + +
+ ); }; - // TODO: add an "Unset" button - render = () => ( -
- - -
- ); } export default DateTimePicker; diff --git a/src/views/components/taskLine.tsx b/src/views/components/taskLine.tsx index e0eec3e..cf80e88 100644 --- a/src/views/components/taskLine.tsx +++ b/src/views/components/taskLine.tsx @@ -1,7 +1,6 @@ import React from "react"; import { connect } from "react-redux"; import { withRouter, RouteComponentProps as RCP } from "react-router"; -import format from "date-fns/format"; import Level from "../components/bulma/level"; import Button from "../components/bulma/button"; @@ -10,6 +9,7 @@ import { Task } from "../../typings/tasks"; import { Dispatch } from "../../typings/react"; import { updateTask } from "../../actions/tasks"; +import { fmtDate } from "../../helpers/datetime"; import strings from "../assets/locales"; @@ -40,9 +40,6 @@ class TaskLine extends React.Component { task.Completed = !task.Completed; this.props.update(task); }; - // Pp expands to a localized date string that looks like this: - // "05/29/1453, 12:00 AM" - fmtDate = (date: number) => format(new Date(date), "Pp"); gotoEditor = () => this.props.history.push(`/task/${this.state.task.ID}`); render = () => { const { @@ -75,12 +72,12 @@ class TaskLine extends React.Component { - {`(D: ${this.fmtDate(Deadline)})`} + {`(D: ${fmtDate(Deadline)})`} {/* eslint-disable react/jsx-no-literals */}   - {`(R: ${this.fmtDate(Reminder)})`} + {`(R: ${fmtDate(Reminder)})`}