- Shipped
- August 9, 2026 at 7:56 PM UTC
- Author
- kamo
- Commit
- 4449ec6
Adding a book POSTed a hard-coded placeholder name with no prompt, and nothing anywhere could rename one — so every book an org had was called the same thing, permanently. Books and groups are now created and edited through a dialog with a name, description and accent, renameable and removable from a row menu. Groups were never fetched at all: the sidebar rendered from a list that only grew when you created one, so a group vanished on reload. Contacts were cached per book and merged in the browser, so "All Contacts" showed only the books you had visited and sorting fought the cache. Both now come from the service, with the scope (book, group, query, order) driving one ordered, counted request. The rest of the page follows the console idiom the rest of the app uses: - Sidebar: books with their contact counts, groups nested with member counts, row actions for rename / add group / export / delete - List: server-side search and ordering, select-all and shift-range selection, infinite scroll, skeletons, an A–Z rail, and empty states that differ for "no contacts" and "nothing matches" - Selection bar: move, add to group, export, delete. The per-row checkboxes have been there all along with nothing to call - Detail panel: everything on file, each fact copyable and actionable, and one shared editor with the create dialog so the two cannot drift - Import reports what it skipped, so a partial import does not look like loss The contacts proxy turned every 204 into a 500 — a successful delete reported failure — because it parsed an empty body as JSON. No org-level option on a new book: listBooks returns every book in the org regardless of owner, so offering the choice would promise privacy the read path does not implement.