# Book Search & Discovery — Spec ## Overview Enable users to search books within the library and discover new books via filters and a dedicated detail view. ## Backend API Contracts ### Book List & Search `GET /api/books/` **Query Parameters:** | Param | Type | Description | |-------|------|-------------| | `q` | string | Full-text search across title, author, genre | | `genre` | string | Exact filter by genre | | `author` | string | Exact filter by author | | `reading_status` | string | Filter: `want_to_read`, `reading`, `finished`, `dnf` | | `ordering` | string | `title`, `author`, `genre`, `created_at` (prefix `-` for desc) | | `page` | int | Page number (default: 1) | **Response (paginated):** ```json { "count": 42, "next": "http://.../?page=2", "previous": null, "results": [ { "id": 1, "title": "Dune", "author": "Frank Herbert", "genre": "Science Fiction", "reading_status": "finished", "reading_status_display": "Finished", "cover_image": "https://..." } ] } ``` ### Book Detail `GET /api/books/{id}/` **Response:** ```json { "id": 1, "title": "Dune", "author": "Frank Herbert", "genre": "Science Fiction", "description": "...", "reading_status": "finished", "reading_status_display": "Finished", "cover_image": "https://...", "total_pages": 688, "created_at": "2025-01-01T00:00:00Z", "updated_at": "2025-01-15T00:00:00Z" } ``` ### Genre / Author Discovery `GET /api/books/genres/` → `["Fiction", "Science Fiction", ...]` `GET /api/books/authors/` → `["Frank Herbert", "Ursula K. Le Guin", ...]` ## Frontend Components ### LibraryPage (enhanced) - **Search bar** at top: text input with debounced `onChange` → calls API with `q` param - **Filter row**: genre dropdown, author dropdown, reading status dropdown - Genre/Author dropdowns populated from `/api/books/genres/` and `/api/books/authors/` - Reading status uses static enum values (`READING_STATUS_OPTIONS`) - **Results grid**: card layout showing cover, title, author, reading status badge - **Empty state**: "No books found" with clear message when results are empty - **Loading state**: spinner/skeleton while fetching - **Click card → navigate to** `/books/{id}` ### BookDetailPage (new) - Shows full book info: cover, title, author, genre, description, reading status, total pages - Back button to return to library - Clean, mobile-responsive layout ### API Client — `frontend/src/api/books.ts` | Method | Endpoint | Returns | |--------|----------|---------| | `searchBooks(params)` | `GET /api/books/` | `{count, results: BookListItem[]}` | | `getBook(id)` | `GET /api/books/{id}/` | `BookDetail` | | `getGenres()` | `GET /api/books/genres/` | `string[]` | | `getAuthors()` | `GET /api/books/authors/` | `string[]` | ## Routes (Frontend) | Path | Component | Auth | |------|-----------|------| | `/` | LibraryPage | Protected | | `/books/:id` | BookDetailPage | Protected | ## Data Flow 1. User types in search bar → 300ms debounce → `GET /api/books/?q=...` 2. User selects filter → `GET /api/books/?genre=...&author=...&reading_status=...` 3. User clicks result → navigate to `/books/:id` 4. BookDetailPage → `GET /api/books/{id}/` ## Mobile Optimizations - Filters collapse into a toggleable panel on small screens - Cards stack in single column on mobile - Touch-friendly tap targets (min 44px)