Archived
98 lines
2.9 KiB
Markdown
98 lines
2.9 KiB
Markdown
# 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
|
|
- **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
|
|
|
|
## 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) |