Archived
feat: full book management system with backend API, frontend UI, and spec docs
- Backend: Book model with reading progress, DRF ViewSet with full CRUD, search, sort, filter, pagination, mark-as-finished, stats endpoint - Frontend: Library grid, BookCard, BookDetail, BookForm components with React 19 + TypeScript + Vite - Tests: 29 passing tests covering models, API, serializers, permissions - Spec: backend api-spec.md and frontend component-spec.md in docs/ Closes crisleo-hermes/cloud-reader#3
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# Frontend Component Specification — Cloud Reader
|
||||
|
||||
## Overview
|
||||
|
||||
React 19 + TypeScript SPA using Vite for development and production builds. State managed via React hooks and Context API. Routing via `react-router-dom` v7 with `lazy`/`Suspense` for code splitting.
|
||||
|
||||
## Components
|
||||
|
||||
### App (root)
|
||||
|
||||
- **Path:** `/`
|
||||
- **Layout:** Header with logo + `<Routes>` wrapper
|
||||
- **Routing:** `/` → `Library`, `*` → redirect to `/`
|
||||
- **Code splitting:** `Library` loaded via `React.lazy` + `<Suspense>`
|
||||
|
||||
### Library
|
||||
|
||||
- **State:** `books[]`, `stats`, `search`, `sortBy`, `statusFilter`, `currentPage`, `view`
|
||||
- **Views:** `library` (grid), `detail` (selected book), `add` (modal form)
|
||||
- **Sub-components:** `BookCard`, `BookDetail`, `BookForm`
|
||||
- **Data flow:** Calls `fetchBooks()` on mount and when filters/page change
|
||||
|
||||
### BookCard
|
||||
|
||||
- **Props:** `{ book: Book, onClick: (book: Book) => void }`
|
||||
- **Display:** Cover image (or first-letter placeholder), title, author, genre badge, reading progress bar with status color
|
||||
- **Interaction:** Click/keyboard-accessible (Enter/Space)
|
||||
|
||||
### BookDetail
|
||||
|
||||
- **Props:** `{ bookId: number, onBack: () => void, onUpdated: () => void }`
|
||||
- **Sections:** Cover, metadata (title, author, genre, ISBN), progress bar with page count, action buttons
|
||||
- **Actions:** Mark as Finished, Edit Details (switches to BookForm), Delete (with confirmation)
|
||||
- **States:** Loading, error, editing mode
|
||||
|
||||
### BookForm
|
||||
|
||||
- **Props:** `{ initialData?: Book, onSubmit: (data: BookFormData) => Promise<void>, onCancel: () => void }`
|
||||
- **Fields:** Title*, Author*, Genre, Description, Cover URL, ISBN, Total Pages, Current Page, Status
|
||||
- **Client validation:** Title/author required, page ≤ total pages
|
||||
- **Loading state:** Submit button shows "Saving..." when `isLoading`
|
||||
|
||||
## Types
|
||||
|
||||
```typescript
|
||||
interface Book {
|
||||
id: number; title: string; author: string; genre: string;
|
||||
description: string; cover_image_url: string; isbn: string;
|
||||
total_pages: number; current_page: number;
|
||||
reading_status: ReadingStatus; reading_progress: number;
|
||||
owner: string; created_at: string; updated_at: string;
|
||||
}
|
||||
|
||||
type ReadingStatus = 'not_started' | 'reading' | 'finished' | 'dnf';
|
||||
|
||||
interface BookFormData {
|
||||
title: string; author: string; genre: string;
|
||||
description: string; cover_image_url: string; isbn: string;
|
||||
total_pages: number; current_page: number; reading_status: ReadingStatus;
|
||||
}
|
||||
```
|
||||
|
||||
## API Client (`api/books.ts`)
|
||||
|
||||
| Function | HTTP Call |
|
||||
|----------------------|------------------------------------|
|
||||
| `fetchBooks(params)` | `GET /api/books/` |
|
||||
| `fetchBook(id)` | `GET /api/books/{id}/` |
|
||||
| `createBook(data)` | `POST /api/books/` |
|
||||
| `updateBook(id, data)` | `PATCH /api/books/{id}/` |
|
||||
| `deleteBook(id)` | `DELETE /api/books/{id}/` |
|
||||
| `markAsFinished(id)` | `POST /api/books/{id}/mark_finished/` |
|
||||
| `fetchBookStats()` | `GET /api/books/stats/` |
|
||||
|
||||
## Styling
|
||||
|
||||
Dark theme with CSS custom properties. All styles in `App.css`. Responsive grid layout with breakpoint at 768px.
|
||||
|
||||
## Build & Dev
|
||||
|
||||
- `yarn workspace frontend dev` — Vite dev server on port 5173 with API proxy to 127.0.0.1:8000
|
||||
- `yarn workspace frontend build` — TypeScript check + Vite production build
|
||||
Reference in New Issue
Block a user