Todoist-style: priorities P1-P4, estimates, FAB add form, Today view, natural quick add, drag-and-drop with haptics
All checks were successful
Build & Release APK / build (push) Successful in 1m53s
All checks were successful
Build & Release APK / build (push) Successful in 1m53s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -78,7 +78,7 @@ function now() {
|
||||
|
||||
// Fields the API accepts — everything else (timestamps, completed_at) is local
|
||||
// bookkeeping until the server's authoritative row arrives via pull().
|
||||
const TASK_FIELDS = ["title", "notes", "status", "project_id", "context", "waiting_for", "due_date", "defer_date", "sort_order"] as const;
|
||||
const TASK_FIELDS = ["title", "notes", "status", "project_id", "context", "waiting_for", "due_date", "defer_date", "priority", "estimate_min", "sort_order"] as const;
|
||||
const PROJECT_FIELDS = ["name", "status", "notes", "sort_order"] as const;
|
||||
|
||||
function pickFields<T>(data: Partial<T>, fields: readonly (keyof T & string)[]): Partial<T> {
|
||||
@@ -111,6 +111,8 @@ export function createTask(data: Partial<Task> & { title: string }): Task {
|
||||
waiting_for: data.waiting_for ?? null,
|
||||
due_date: data.due_date ?? null,
|
||||
defer_date: data.defer_date ?? null,
|
||||
priority: data.priority ?? 4,
|
||||
estimate_min: data.estimate_min ?? null,
|
||||
completed_at: null,
|
||||
sort_order: data.sort_order ?? 0,
|
||||
created_at: now(),
|
||||
@@ -237,10 +239,30 @@ async function pull() {
|
||||
|
||||
// ---- selectors ----
|
||||
|
||||
function byPriorityDue(a: Task, b: Task): number {
|
||||
return (
|
||||
a.priority - b.priority ||
|
||||
(a.due_date ?? "9999").localeCompare(b.due_date ?? "9999") ||
|
||||
a.sort_order - b.sort_order ||
|
||||
b.created_at.localeCompare(a.created_at)
|
||||
);
|
||||
}
|
||||
|
||||
export function tasksByStatus(s: State, status: Task["status"]): Task[] {
|
||||
return s.tasks
|
||||
.filter((t) => t.status === status)
|
||||
.sort((a, b) => a.sort_order - b.sort_order || b.created_at.localeCompare(a.created_at));
|
||||
return s.tasks.filter((t) => t.status === status).sort(byPriorityDue);
|
||||
}
|
||||
|
||||
/** Overdue + due-today + deferred-arriving-today, across all open lists. */
|
||||
export function todayTasks(s: State): { overdue: Task[]; today: Task[] } {
|
||||
const now = new Date();
|
||||
const todayIso = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
|
||||
const open = s.tasks.filter((t) => t.status !== "done" && t.status !== "trashed");
|
||||
return {
|
||||
overdue: open.filter((t) => t.due_date && t.due_date < todayIso).sort(byPriorityDue),
|
||||
today: open
|
||||
.filter((t) => t.due_date === todayIso || (t.defer_date === todayIso && !t.due_date))
|
||||
.sort(byPriorityDue),
|
||||
};
|
||||
}
|
||||
|
||||
export function activeProjects(s: State): Project[] {
|
||||
|
||||
Reference in New Issue
Block a user