# Task List — Product Requirements (v2.4)

Task List is a classic personal todo list. People type a title and press Enter to add a task, tick tasks off, edit them inline, delete them, switch between All, Active and Completed views and clear what is done. Each browser tab keeps its own list on the server.

**Problem.** A todo list is only useful if the counter, the visible items and the stored list always agree, and if keyboard-only use is as complete as mouse use.

## Users
- **Everyday user** — Capture, tick off and tidy tasks quickly, mostly from the keyboard.

## Goals
- The "items left" counter always equals the number of active todos.
- Every edit gesture (Enter, Escape, blur, empty title) has one predictable outcome.
- Bulk actions only affect the todos they promise to affect.

## List and counter (LST)

Seeded list, footer counter and empty state.

- **FR-LST-01** (Must) A fresh tab shows three seeded todos, with the completed one struck through, and a footer with the active counter, the All / Active / Completed filters and Clear completed.
  - Buy oat milk (active), Book dentist appointment (completed), Renew library card (active)
  - Footer "2 items left" with All selected
- **FR-LST-02** (Must) The footer counter equals the number of active (not completed) todos, and is singular for one: "1 item left".
  - Ticking Buy oat milk: "1 item left"; unticking: "2 items left"
  - All completed: "0 items left"
- **FR-LST-03** (Could) With no todos the list, footer and toggle-all chevron are hidden and a hint is shown.
  - "Nothing to do — add your first todo above."

## Adding todos (ADD)

Keyboard-only entry.

- **FR-ADD-01** (Must) Typing a title in "What needs to be done?" and pressing Enter appends an unchecked todo and empties the input; there is no add button.
  - "Water the plants" is last and unchecked; "3 items left"
- **FR-ADD-02** (Should) Todos keep the order in which they were added.
  - Three more todos added in sequence appear after the seeded three in the same order; "5 items left"
- **FR-ADD-03** (Should) Empty or whitespace-only input adds nothing; surrounding spaces are trimmed from a valid title.
  - Enter on empty and on "     " leaves three todos
  - "   Feed the cat   " is added as "Feed the cat"
- **FR-ADD-04** (Could) Titles are shown as plain text and long titles wrap inside the list.
  - <b>bold?</b> & "quotes" is displayed literally, not as bold
  - A 100-character title wraps without horizontal scroll

## Completing todos (CMP)

Single and bulk completion.

- **FR-CMP-01** (Must) The checkbox toggles a todo between active and completed (struck through) and updates the counter.
- **FR-CMP-02** (Must) The chevron left of the input ("Mark all as complete") completes every todo; clicking it again reopens every todo and hides Clear completed.
  - All three struck through, "0 items left"; again: none completed, "3 items left"
- **FR-CMP-03** (Must) Clear completed removes only the completed todos and then hides itself.
  - After ticking Buy oat milk: only Renew library card remains, "1 item left", button hidden
  - With the seed, clearing leaves Buy oat milk and Renew library card and "2 items left"
  - Mark all then Clear completed leaves the empty-list state

## Editing and deleting (EDT)

Inline edit and hover delete.

- **FR-EDT-01** (Must) Double-click opens an inline editor with the current text; Enter saves the trimmed text and the change survives a reload.
  - "Renew library card online  " is saved as "Renew library card online"
- **FR-EDT-02** (Should) Escape discards the edit and keeps the original title.
  - Typing "Buy almond milk" then Escape leaves "Buy oat milk"
- **FR-EDT-03** (Should) Clicking elsewhere (blur) saves the edit.
  - "Buy oat milk and bread" is kept after clicking the heading
- **FR-EDT-04** (Must) Saving an empty title deletes the todo; no blank row is ever left.
  - Clearing Renew library card and pressing Enter leaves two todos and "1 item left"
- **FR-EDT-05** (Should) A × button is revealed only while hovering a row and deletes that todo.
  - No × without hover; after hover and click, Buy oat milk is gone and "1 item left"

## Filters (FLT)

Hash-routed All / Active / Completed views.

- **FR-FLT-01** (Should) Filters show the right subset and are reflected in the URL hash; the current filter is outlined.
  - Active: #/active, Buy oat milk and Renew library card
  - Completed: #/completed, only Book dentist appointment
  - All shows all three
- **FR-FLT-02** (Could) A filter URL opens directly on that filter and the browser Back button returns to the previous filter.
  - /todos/#/completed shows only Book dentist appointment; Active then Back shows Completed again
- **FR-FLT-03** (Should) Completing a todo while the Active filter is selected removes it from the view.
  - Ticking Buy oat milk: it disappears, "1 item left"

## Persistence and API (PER)

Per-tab server state and REST interface.

- **FR-PER-01** (Should) Changes survive a reload in the same tab; a new tab starts from the seeded three todos.
  - Added Water the plants, reload: four todos, "3 items left"; new tab: seeded three
- **FR-PER-02** (Should) The REST API supports list, add, update, delete and reset with specific errors.
  - GET lists 3 todos, active 2, completed 1
  - Blank title: 422 "Title is required"
  - Add returns 201 with id t4; PATCH completed true and DELETE return 200; DELETE again 404
  - Reset restores the seeded three

## Non-functional requirements

- **NFR-01** (Must) Data integrity: the counter, the visible list and the stored list never disagree after any add, edit, delete, toggle or clear.
- **NFR-02** (Should) Keyboard accessibility: add, save and cancel are available from the keyboard (Enter, Escape).

## Glossary and rules

- **Active** — A todo that is not completed.
- **Toggle all** — The chevron left of the input that completes or reopens every todo.

## Out of scope

- Drag to reorder
- Multiple lists
