Add plan dates, postponing, backlog and projects

- Tasks get an optional plan date separate from the deadline. Unfinished
  plans roll over in Today; only missed deadlines count as overdue.
- Postpone sheet on every task (tomorrow, weekend, next week, ...) that
  can move either the plan date or the deadline, with undo.
- Backlog view for undated tasks, with suggestions in Today.
- Projects with deadline, notes, progress, next step and "falling
  behind" warnings, shown in Today and in their own view.
- Times and the calendar now follow the plan date (else the deadline).
- Schema v3 migration (backup taken first); export format v3 includes
  projects and still imports older files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
goyban
2026-10-07 14:26:32 +02:00
parent 509b1a1320
commit 39842c72d7
8 changed files with 931 additions and 157 deletions
+98 -27
View File
@@ -28,7 +28,12 @@
<aside id="sidebar" class="sidebar">
<div class="brand"><img src="icons/icon.svg" alt="" width="28" height="28"> WhatToDo</div>
<nav id="views" class="nav"></nav>
<div class="nav-heading">Categories</div>
<div class="nav-heading">
<span>Projects</span>
<button id="new-project" class="icon-btn small" type="button" aria-label="New project" title="New project">+</button>
</div>
<nav id="projects" class="nav"></nav>
<div class="nav-heading"><span>Categories</span></div>
<nav id="cats" class="nav"></nav>
<div class="sidebar-foot">
<button id="settings-btn" class="nav-item" type="button"><span class="nav-icon">⚙️</span> Settings</button>
@@ -65,10 +70,45 @@
<input id="t-title" required maxlength="500" autocomplete="off">
</label>
<div class="row">
<label class="field">
<span>Plan to do on</span>
<input id="t-planned" type="date">
</label>
<label class="field">
<span>Deadline</span>
<input id="t-due" type="date">
</label>
</div>
<div class="quick-dates">
<span class="muted small-label">Plan:</span>
<button type="button" class="chip-btn" data-plan="today">Today</button>
<button type="button" class="chip-btn" data-plan="tomorrow">Tomorrow</button>
<button type="button" class="chip-btn" data-plan="weekend">Weekend</button>
<button type="button" class="chip-btn" data-plan="nextweek">Next week</button>
<button type="button" class="chip-btn" data-plan="">No plan</button>
</div>
<div class="row">
<label class="field">
<span>From <small>(optional)</small></span>
<input id="t-start" type="time" step="300">
</label>
<label class="field">
<span>To</span>
<input id="t-end" type="time" step="300">
</label>
</div>
<div id="t-day" class="day-preview" hidden></div>
<div class="row">
<label class="field">
<span>Project</span>
<select id="t-project"></select>
</label>
<label class="field">
<span>Category</span>
<select id="t-category"></select>
</label>
</div>
<div class="row">
<label class="field">
<span>Priority</span>
<select id="t-priority">
@@ -78,12 +118,6 @@
<option value="3">High</option>
</select>
</label>
</div>
<div class="row">
<label class="field">
<span>Deadline</span>
<input id="t-due" type="date">
</label>
<label class="field">
<span>Repeat</span>
<select id="t-repeat">
@@ -99,30 +133,13 @@
<input id="t-interval" type="number" min="1" max="365" value="1">
</label>
</div>
<div class="quick-dates">
<button type="button" class="chip-btn" data-days="0">Today</button>
<button type="button" class="chip-btn" data-days="1">Tomorrow</button>
<button type="button" class="chip-btn" data-days="7">Next week</button>
<button type="button" class="chip-btn" data-days="">No date</button>
</div>
<div class="row">
<label class="field">
<span>From <small>(optional)</small></span>
<input id="t-start" type="time" step="300">
</label>
<label class="field">
<span>To</span>
<input id="t-end" type="time" step="300">
</label>
</div>
<div id="t-day" class="day-preview" hidden></div>
<label class="field">
<span>Tags <small>(comma separated)</small></span>
<input id="t-tags" placeholder="e.g. editing, urgent" autocomplete="off">
</label>
<label class="field">
<span>Notes</span>
<textarea id="t-notes" rows="4" maxlength="20000"></textarea>
<textarea id="t-notes" rows="3" maxlength="20000"></textarea>
</label>
<div class="field">
<span>Checklist</span>
@@ -141,6 +158,60 @@
</form>
</dialog>
<dialog id="plan-dialog" class="sheet">
<div class="dialog-body">
<h3 id="p-title">Postpone</h3>
<div id="p-mode" class="segmented" role="group" aria-label="What to move">
<button type="button" data-mode="plan">Plan date</button>
<button type="button" data-mode="due">Deadline</button>
</div>
<p id="p-current" class="muted"></p>
<div id="p-options" class="plan-options"></div>
<div class="row">
<input id="p-date" type="date" aria-label="Pick a date">
<button id="p-set" class="btn primary" type="button">Set</button>
</div>
<div class="dialog-actions">
<button id="p-clear" class="btn" type="button">Remove date</button>
<span class="spacer"></span>
<button id="p-cancel" class="btn" type="button">Cancel</button>
</div>
</div>
</dialog>
<dialog id="project-dialog">
<form id="project-form" class="dialog-body">
<h3 id="pr-dialog-title">Project</h3>
<label class="field">
<span>Name</span>
<input id="pr-name" required maxlength="100" autocomplete="off">
</label>
<div class="row">
<label class="field">
<span>Category</span>
<select id="pr-category"></select>
</label>
<label class="field">
<span>Deadline</span>
<input id="pr-due" type="date">
</label>
</div>
<label class="field">
<span>Goal / notes</span>
<textarea id="pr-notes" rows="4" maxlength="20000"></textarea>
</label>
<label class="check-field">
<input id="pr-done" type="checkbox"> Finished
</label>
<div class="dialog-actions">
<button id="pr-delete" type="button" class="btn danger">Delete</button>
<span class="spacer"></span>
<button id="pr-cancel" type="button" class="btn">Cancel</button>
<button type="submit" class="btn primary">Save</button>
</div>
</form>
</dialog>
<dialog id="settings-dialog">
<div class="dialog-body">
<h3>Settings</h3>
@@ -157,8 +228,8 @@
<section class="settings-section">
<h4>Export / import</h4>
<p class="muted">Export downloads all tasks and categories as a JSON file. Import it on another
install, such as production, to move your data there.</p>
<p class="muted">Export downloads all tasks, projects and categories as a JSON file. Import it on
another install, such as production, to move your data there.</p>
<div class="row wrap">
<a id="s-export" class="btn primary" href="api/export" download>Export data</a>
</div>