- Initialize Git repository with main branch - Create comprehensive .gitignore for Node.js, React, and environment files - Set up directory structure (frontend/, backend/, docs/) - Create detailed README.md with project overview and setup instructions - Add .env.example with all required environment variables - Configure Prettier for consistent code formatting All acceptance criteria met: ✅ Git repository initialized with appropriate .gitignore ✅ Directory structure matches Technical Assumptions ✅ README.md created with project overview and setup docs ✅ .env.example file with all required environment variables ✅ Prettier config files added for code formatting consistency 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
190 lines
7.2 KiB
Markdown
190 lines
7.2 KiB
Markdown
# Epic 2: Book Search & Management
|
|
|
|
**Epic Goal:** Enable users to search for books using the Open Library API and add selected books to their reading list with deadline dates, providing the foundation for all progress tracking features.
|
|
|
|
## Story 2.1: Open Library API Integration Service
|
|
|
|
As a **developer**,
|
|
I want **a backend service that queries the Open Library API**,
|
|
so that **users can search for books by title, author, or ISBN**.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
1. Service module created in `backend/src/services/openLibraryService.js`
|
|
2. Function `searchBooks(query)` implemented:
|
|
- Makes HTTP request to `https://openlibrary.org/search.json?q={query}`
|
|
- Parses response and extracts relevant fields: title, author, first_publish_year, cover_i, number_of_pages, isbn
|
|
- Returns array of book objects with normalized structure
|
|
- Handles API errors gracefully (returns empty array or error object)
|
|
3. Function limits results to top 20 books for performance
|
|
4. Book cover URLs constructed using cover_i: `https://covers.openlibrary.org/b/id/{cover_i}-M.jpg`
|
|
5. Service includes error handling for network failures and invalid responses
|
|
6. Service respects rate limits (implements basic request throttling if needed)
|
|
7. Unit tests written for service (mocked HTTP responses)
|
|
|
|
## Story 2.2: Book Search API Endpoint
|
|
|
|
As a **user**,
|
|
I want **an API endpoint to search for books**,
|
|
so that **the frontend can retrieve book search results**.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
1. API endpoint created: `GET /api/books/search?q={query}`
|
|
2. Endpoint validates query parameter (required, non-empty, max length 200 characters)
|
|
3. Endpoint calls `openLibraryService.searchBooks(query)`
|
|
4. Returns JSON response with book results:
|
|
```json
|
|
{
|
|
"results": [
|
|
{
|
|
"olid": "OL12345W",
|
|
"title": "The Name of the Wind",
|
|
"author": "Patrick Rothfuss",
|
|
"publishYear": 2007,
|
|
"coverUrl": "https://covers.openlibrary.org/b/id/123456-M.jpg",
|
|
"totalPages": 662
|
|
}
|
|
]
|
|
}
|
|
```
|
|
5. Returns 400 error if query parameter is missing or invalid
|
|
6. Returns 500 error if Open Library API fails, with user-friendly error message
|
|
7. Endpoint returns 200 with empty results array if no books found
|
|
8. Caches search results for 1 hour (in-memory cache acceptable for MVP)
|
|
9. Integration test written for endpoint (mocked Open Library service)
|
|
|
|
## Story 2.3: Add Book API Endpoint
|
|
|
|
As a **user**,
|
|
I want **an API endpoint to add a book to my reading list**,
|
|
so that **I can start tracking progress for that book**.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
1. API endpoint created: `POST /api/books`
|
|
2. Endpoint accepts JSON request body:
|
|
```json
|
|
{
|
|
"title": "The Name of the Wind",
|
|
"author": "Patrick Rothfuss",
|
|
"totalPages": 662,
|
|
"coverUrl": "https://covers.openlibrary.org/b/id/123456-M.jpg",
|
|
"deadlineDate": "2025-03-15"
|
|
}
|
|
```
|
|
3. Endpoint validates all required fields: title, totalPages (>0), deadlineDate (valid date, not in past)
|
|
4. Author and coverUrl are optional
|
|
5. Endpoint creates new Book record in database via Prisma
|
|
6. Sets `status` to "reading" by default
|
|
7. Returns 201 status with created book object including generated ID
|
|
8. Returns 400 error if validation fails with specific error messages
|
|
9. Returns 500 error if database operation fails
|
|
10. Unit and integration tests written covering success and error cases
|
|
|
|
## Story 2.4: List Active Books API Endpoint
|
|
|
|
As a **user**,
|
|
I want **an API endpoint to retrieve my active books**,
|
|
so that **the frontend can display my current reading list**.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
1. API endpoint created: `GET /api/books`
|
|
2. Endpoint queries database for all books with `status = "reading"`
|
|
3. Returns JSON array of book objects:
|
|
```json
|
|
{
|
|
"books": [
|
|
{
|
|
"id": 1,
|
|
"title": "The Name of the Wind",
|
|
"author": "Patrick Rothfuss",
|
|
"totalPages": 662,
|
|
"coverUrl": "https://covers.openlibrary.org/b/id/123456-M.jpg",
|
|
"deadlineDate": "2025-03-15",
|
|
"isPrimary": false,
|
|
"status": "reading",
|
|
"createdAt": "2025-12-01T10:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
4. Books ordered by deadline date (soonest first)
|
|
5. Returns 200 status with empty array if no active books
|
|
6. Returns 500 error if database query fails
|
|
7. Integration test written
|
|
|
|
## Story 2.5: Book Search UI Component
|
|
|
|
As a **user**,
|
|
I want **a search interface to find and select books**,
|
|
so that **I can add them to my reading list**.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
1. "Add Book" screen/modal component created in `frontend/src/pages/AddBook.jsx`
|
|
2. Search input field with placeholder "Search by title, author, or ISBN"
|
|
3. Search triggers API call to `/api/books/search?q={query}` on form submit or button click
|
|
4. Loading indicator displayed while search is in progress
|
|
5. Search results displayed as a list/grid with:
|
|
- Book cover thumbnail (or placeholder if no cover)
|
|
- Title (bold)
|
|
- Author
|
|
- Total pages
|
|
- "Select" button
|
|
6. Clicking "Select" button navigates to book detail view with pre-filled data
|
|
7. Empty state message shown if no results found
|
|
8. Error message shown if API call fails
|
|
9. Search input debounced (300ms delay) if implementing search-as-you-type
|
|
10. Component is mobile-responsive (card layout stacks vertically on small screens)
|
|
|
|
## Story 2.6: Add Book Form UI
|
|
|
|
As a **user**,
|
|
I want **a form to confirm book details and set a deadline**,
|
|
so that **I can add the book to my reading list with a finish date**.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
1. Add book form component created (can be part of AddBook screen or separate)
|
|
2. Form displays selected book information (cover, title, author, total pages) as read-only
|
|
3. Form includes:
|
|
- Deadline date picker (required)
|
|
- "Add to Reading List" button
|
|
- "Cancel" or "Back" button
|
|
4. Deadline date picker validates:
|
|
- Date must be in the future
|
|
- User-friendly date selection interface (mobile-optimized)
|
|
5. Clicking "Add to Reading List" calls `POST /api/books` with form data
|
|
6. Loading state shown while API call is in progress
|
|
7. Success: User redirected to home screen (book list) with success message
|
|
8. Error: Error message displayed below form, user can retry
|
|
9. Form validation prevents submission if deadline is invalid
|
|
10. Form is mobile-responsive and thumb-friendly
|
|
|
|
## Story 2.7: Book List Display UI
|
|
|
|
As a **user**,
|
|
I want **to see all my active books on the home screen**,
|
|
so that **I can quickly view my reading list and select a book to log progress**.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
1. Home screen component created in `frontend/src/pages/Home.jsx`
|
|
2. Component fetches active books from `GET /api/books` on mount
|
|
3. Books displayed as cards/list items showing:
|
|
- Cover thumbnail (left side)
|
|
- Title and author (prominent)
|
|
- Total pages and deadline date
|
|
- Placeholder text for pace calculation (to be implemented in Epic 3)
|
|
4. "Add Book" button prominently displayed (e.g., floating action button or top-right)
|
|
5. Empty state shown if no books (with "Add your first book" message and CTA)
|
|
6. Loading state shown while fetching books
|
|
7. Error state shown if API call fails (with retry button)
|
|
8. Tapping a book card navigates to book detail screen (or triggers log progress modal - Epic 3)
|
|
9. List ordered by deadline date (soonest first)
|
|
10. Component is mobile-responsive with smooth scrolling
|
|
|
|
---
|