This repository has been archived on 2026-07-21. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cloud-reader/docs/frontend/component-spec.md
T
Marko (Hermes Implementer) 84d8fed3f2 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
2026-05-26 04:35:13 +00:00

3.2 KiB

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

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