From 82b3f4c5e419bd6fdaa0dae14c92586b51aee8d7 Mon Sep 17 00:00:00 2001 From: syn Date: Mon, 8 Mar 2021 20:11:17 +0300 Subject: mvp --- front/index.jsx | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 front/index.jsx (limited to 'front/index.jsx') diff --git a/front/index.jsx b/front/index.jsx new file mode 100644 index 0000000..85b1977 --- /dev/null +++ b/front/index.jsx @@ -0,0 +1,172 @@ +import "preact/debug"; +import { get, post } from 'axios'; +import { Component, render, Fragment, h } from 'preact'; +import strftime from 'strftime'; +import { ConfigView, Config } from './config.jsx' +/** @jsx h */ +/** @jsxFrag Fragment */ + +/* naive. assumes: + year = 365 days, + day = 24 hrs, + hr = 60 mins, + min = 60 secs +*/ +function format_relative_naive(date) { + const sec = 1000; + const min = 60 * sec; + const hr = 60 * min; + const day = 24 * hr; + let now = new Date(); + let ms_diff = date - now; + if (Math.abs(ms_diff) < 2 * min) { + return `${Math.round(ms_diff / sec)}s`; + } else if (Math.abs(ms_diff) < 2 * hr) { + return `${Math.round(ms_diff / min)}m`; + } else if (Math.abs(ms_diff) < 2 * day) { + return `${Math.round(ms_diff / hr)}h`; + } else { + return `${Math.round(ms_diff / day)}d`; + } +} + + +class TodoList extends Component { + constructor() { + super(); + this.state = { todos: [] }; + } + + componentWillMount() { + get("/todos").then(resp => { + let todos = resp.data.todos; + todos.sort((todo1, todo2) => { return todo1.expires - todo2.expires; }) + this.setState({ todos: resp.data.todos }) + }) + } + + render({ config }, { todos }) { + let { datefmt, timezoneOffset } = config; + return + + + + + + + + + + {todos.map(todo => { + return strftime("%H:%M", date)} + done={todo.done} + desc={todo.desc} + display_date={new Date(todo.expires)} + key={`todo-${todo.id}`} + id={todo.id} + /> + })} + +
whatwhenleft
; + } +} + +class TodoRow extends Component { + constructor(props) { + super(props); + this.state = { id: props.id } + } + + deleteTodo(event) { + post("/delete-todo", { id: this.state.id }) + .then(resp => { + console.log(resp); + window.location.reload(); + }); + } + + render({ dateFormatter, done, desc, display_date, key }, { }) { + let status = done ? + DONE + : TODO + return + {status} + {desc} + {dateFormatter(display_date)} + {format_relative_naive(display_date)} + + + } +} + +class PostForm extends Component { + constructor({ notify_list, config }) { + super(); + this.state = { + notify_list: notify_list, + desc: "", + date: config.getDefaultDate() }; + } + postTodo(event) { + if (this.state.desc.length == 0) { + return; + } + post( + "/new-todo", { + desc: this.state.desc, + expires: new Date(this.state.date).getTime(), + done: false + } + ) + .then((resp) => { + console.log(resp.data); + window.location.reload(); + }).catch((err) => { + console.log("err: "); + console.log(err); + }); + } + + render(props, state) { + let isEmpty = state.desc.length == 0; + const noop = _ => {}; + let aClasslist = `a-button ${isEmpty ? "a-button-disabled" : ""}` + return <> + this.setState({ desc: e.target.value })} + /> + this.setState({ date: e.target.value })} + value={this.state.date} + /> + post + + } +} + +class App extends Component { + constructor() { + super(); + this.state = { config: new Config() }; + } + + changeConfig(newConfig) { + this.setState({ config: newConfig }); + } + + render({}, { config }) { + return
+ +

|

+ + +
+ } +} + +render(, document.getElementById("root")); -- cgit v1.2.1-18-gbd029