# Edit Book Actions — design spec ## Problem The index page shows books grouped by status but provides no way to change a book's status, add reading notes, or record ratings. Users must edit the Org file manually. We need lightweight, context-sensitive edit actions accessible from the agenda view. ## Interaction model Click a book row on the index page → the footer (minibuffer) shows action links tailored to that book's current status. Clicking an action either performs it immediately (status transitions) or shows a lightweight prompt page (add note, mark read with date). No JavaScript. All actions are plain `` links or simple HTML forms. ## Actions per status ### WANT - **Mark reading** — immediate: sets TODO to READING - **Add note** — prompt page: date + textarea, appends a note ### READING - **Mark read** — prompt page: date picker (default today) Rating is deferred (see out of scope). - **Abandon** — immediate: sets TODO to ABANDONED - **Add note** — prompt page: date + textarea ### READ - **Read again** — immediate: sets TODO to READING - **Add note** — prompt page: date + textarea ### ABANDONED - **Try again** — immediate: sets TODO to READING ## Implementation ### New Org write functions (`spine.el`) **`spine-set-status (id status &optional date)`** Finds the book by `:ID:` property, changes its TODO keyword to `status`, and records the state transition in the LOGBOOK drawer (using `org-todo`). If `date` is provided (for READ status), sets a `:READ_DATE:` property. **`spine-add-note (id text &optional date)`** Finds the book by `:ID:`, appends `- [YYYY-MM-DD] text` to the headline body. Date defaults to today if not provided. Follows the same pattern as `spine-add-book`: `find-file-noselect`, modify, save, `kill-buffer`. **`spine-set-rating (id rating)`** Sets the `:RATING:` property on the book. ### Handler: `httpd/edit` Single handler dispatching on `action` query param: - `action=status` — calls `spine-set-status` with `id` and `value` (the target TODO state). Redirects to `/index?id=`. - `action=note` — GET shows a prompt page with date + textarea for the book. POST processes: calls `spine-add-note` with `id`, `text`, and optional `date`. Redirects to `/index?id=`. - `action=rating` — calls `spine-set-rating` with `id` and `value`. Redirects to `/index?id=`. - Unknown action or missing `id` — redirect to `/index` silently. The prompt page for notes is a minimal HTML page (no Mustache template needed — small enough to inline): shows the book title as context, a date input (default today), a textarea, and a submit button. POST data includes `id`, `action`, `date`, `text`. ### Model: `spine-index-model` minibuffer extension When a book is selected (`selected-id` matches), the model gains a `minibuffer` field: ```elisp ("minibuffer" . (ht ("actions" (list (ht ("label" "Mark reading") ("href" "/edit?id=X&action=status&value=READING")) (ht ("label" "Add note") ("href" "/edit?id=X&action=note")))))) ``` Actions are computed from the selected book's `:status` property. The exact set follows the table in "Actions per status" above. ### Template: `index.mustache` minibuffer section The existing minibuffer footer placeholder is replaced with a dynamic version: ```mustache {{#minibuffer}} {{/minibuffer}} ``` Styled as pill links consistent with the existing pill classes. `M-x` prefix keeps the Emacs feel. ### Testing New test file `test/spine-edit-test.el`: - `spine-set-status` changes TODO state correctly for each transition - `spine-set-status` records LOGBOOK entry - `spine-add-note` appends a note with the correct format - `spine-add-note` defaults to today when no date provided - `spine-set-rating` sets the rating property - Model includes `minibuffer` field when book is selected - Model has correct action set per status ## Out of scope - Editing book properties (author, format, ISBN) — add-book covers creation; editing those can come later if needed - Deleting books — add-book is additive; no delete flow yet - Rating prompt on the "Mark read" page — deferred; rating can be set separately - Inline editing in the detail section — the minibuffer actions are the primary surface for now