Functional Weave
Code in TypeScript

todo.group-by-due@1.0.0

impl/typescript.ts

1,447 bytes · the TypeScript implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { dayOfWeek } from "./dates_day_of_week.ts";  ← from dates.day-of-week ^1.0.0 · built alongside by fune
import { type DueStatus, dueStatus } from "./todo_due_status.ts";  ← from todo.due-status ^1.0.0 · built alongside by fune
import { type DueGroup } from "./todo_group_by_due_types.ts";
import { type Todo } from "./todo_item.ts";  ← from todo.item ^1.0.0 · built alongside by fune

const SECTIONS: readonly [DueStatus, string][] = [
  ["overdue", "Overdue"],
  ["today", "Today"],
  ["tomorrow", "Tomorrow"],
  ["this-week", "This week"],
  ["later", "Later"],
  ["none", "No date"],
  ["done", "Done"],
];

/**
 * Todos in planner sections, fixed order, empty sections left out. Sections
 * spanning several dates are sorted by due date, stably; the rest keep the
 * caller's order, so a list pre-sorted by priority stays that way.
 */
export function groupByDue(todos: readonly Todo[], today: string): readonly DueGroup[] {
  dayOfWeek(today); // a bad today is an error even for an empty list
  const statuses = todos.map((todo) => dueStatus(todo, today));
  const groups: DueGroup[] = [];
  for (const [status, title] of SECTIONS) {
    const members = todos.filter((_, i) => statuses[i] === status);
    if (members.length === 0) continue;
    if (status === "overdue" || status === "this-week" || status === "later") {
      // Array.prototype.sort is stable, so equal dates keep input order.
      members.sort((a, b) => ((a.due as string) < (b.due as string) ? -1 : (a.due as string) > (b.due as string) ? 1 : 0));
    }
    groups.push({ status, title, todos: members });
  }
  return groups;
}