Implement: US: Mobile Book Search and Discovery #24

Merged
crisleo94 merged 3 commits from feature/mobile-search-discovery into main 2026-05-29 05:13:03 +00:00
Owner

Implement: Mobile Book Search and Discovery

Enhanced the book search experience with mobile-first features: voice search via Web Speech API, real-time autocomplete suggestions, and touch-optimized responsive layout.

Changes

API Client Fixes (missing from merged PR #13):

  • frontend/src/types/book.ts - Added BookSearchParams interface and READING_STATUS_OPTIONS constant
  • frontend/src/api/books.ts - Added searchBooks, getBook, getGenres, getAuthors methods to booksApi

Mobile Features (new):

  • frontend/src/hooks/useVoiceSearch.ts - Web Speech API hook for voice search
  • frontend/src/hooks/useMediaQuery.ts - Responsive breakpoints utility
  • frontend/src/components/search/SearchSuggestions.tsx - Real-time autocomplete dropdown
  • frontend/src/pages/Library.tsx - Voice search, suggestions, mobile-responsive grid
  • frontend/src/pages/BookDetailPage.tsx - Mobile-responsive detail layout

Documentation:

  • docs/frontend/mobile-search-spec.md - Full spec for mobile search features

Closes #5 (re-opened) - missing API methods now added.

## Implement: Mobile Book Search and Discovery Enhanced the book search experience with mobile-first features: voice search via Web Speech API, real-time autocomplete suggestions, and touch-optimized responsive layout. ### Changes **API Client Fixes (missing from merged PR #13):** - `frontend/src/types/book.ts` - Added `BookSearchParams` interface and `READING_STATUS_OPTIONS` constant - `frontend/src/api/books.ts` - Added `searchBooks`, `getBook`, `getGenres`, `getAuthors` methods to `booksApi` **Mobile Features (new):** - `frontend/src/hooks/useVoiceSearch.ts` - Web Speech API hook for voice search - `frontend/src/hooks/useMediaQuery.ts` - Responsive breakpoints utility - `frontend/src/components/search/SearchSuggestions.tsx` - Real-time autocomplete dropdown - `frontend/src/pages/Library.tsx` - Voice search, suggestions, mobile-responsive grid - `frontend/src/pages/BookDetailPage.tsx` - Mobile-responsive detail layout **Documentation:** - `docs/frontend/mobile-search-spec.md` - Full spec for mobile search features Closes #5 (re-opened) - missing API methods now added.
marko added 1 commit 2026-05-29 02:56:28 +00:00
crisleo94 added 1 commit 2026-05-29 04:51:03 +00:00
Owner

Reid's Review — PR #24

Verdict: 🔴 Changes Required


🔴 Blocking Issues

These MUST be resolved before this PR can be merged.

  • [File: frontend/src/hooks/useVoiceSearch.ts | Line ~19] event handler typing
    The window as unknown as Record<string, unknown> cast is acceptable for the SpeechRecognition check, but the SpeechRecognition and SpeechRecognitionEvent types are used without being imported or defined. These DOM types need proper type declarations or the types/speech-recognition package should be installed. As written, this will cause TypeScript compilation errors in environments without these global type definitions.

  • [File: frontend/src/components/search/SearchSuggestions.tsx | Line ~89-100] direct DOM manipulation
    The onMouseEnter and onMouseEnter event handlers use e.currentTarget as HTMLElement and directly mutate style.background. This is direct DOM manipulation. Consider using CSS :hover pseudo-class or a styled component solution instead. Inline style mutations bypass React's declarative model.


🟡 Suggestions (Non-Blocking)

These are recommendations for improvement. Not required for merge.

  • [File: frontend/src/hooks/useVoiceSearch.ts] Extract the debounce logic into a shared useDebounce hook rather than duplicating it in Library.tsx. Both files have identical implementations.

  • [File: frontend/src/components/search/SearchSuggestions.tsx] Consider adding proper CSS styling (CSS modules or styled-components) instead of extensive inline styles for better maintainability.

  • [File: frontend/src/pages/Library.tsx] The TOUCH_TARGET constant is well-placed but the inline styles throughout the component could benefit from extraction to a shared styling solution.


📋 AC Coverage

Based on linked issue #5

  • Search bar with query typing and real-time suggestions - Typing triggers debounced suggestions via SearchSuggestions component
  • Clear message when no results found - Empty state shows "🔍 No books found" message
  • Click search result navigates to book detail - navigate(/books/${book.id}) on suggestion click
  • Filter by genre, author, reading status - Filters panel with all three options implemented
  • Django backend integration - Uses booksApi.searchBooks() which calls GET /api/books/
  • Mobile-optimized search - Voice search, responsive layout, WCAG 2.1 touch targets, single-column grid on mobile
## Reid's Review — PR #24 **Verdict:** 🔴 Changes Required --- ### 🔴 Blocking Issues > These MUST be resolved before this PR can be merged. - **[File: frontend/src/hooks/useVoiceSearch.ts | Line ~19]** `event handler typing` The `window as unknown as Record<string, unknown>` cast is acceptable for the SpeechRecognition check, but the `SpeechRecognition` and `SpeechRecognitionEvent` types are used without being imported or defined. These DOM types need proper type declarations or the `types/speech-recognition` package should be installed. As written, this will cause TypeScript compilation errors in environments without these global type definitions. - **[File: frontend/src/components/search/SearchSuggestions.tsx | Line ~89-100]** `direct DOM manipulation` The `onMouseEnter` and `onMouseEnter` event handlers use `e.currentTarget as HTMLElement` and directly mutate `style.background`. This is direct DOM manipulation. Consider using CSS `:hover` pseudo-class or a styled component solution instead. Inline style mutations bypass React's declarative model. --- ### 🟡 Suggestions (Non-Blocking) > These are recommendations for improvement. Not required for merge. - **[File: frontend/src/hooks/useVoiceSearch.ts]** Extract the debounce logic into a shared `useDebounce` hook rather than duplicating it in Library.tsx. Both files have identical implementations. - **[File: frontend/src/components/search/SearchSuggestions.tsx]** Consider adding proper CSS styling (CSS modules or styled-components) instead of extensive inline styles for better maintainability. - **[File: frontend/src/pages/Library.tsx]** The `TOUCH_TARGET` constant is well-placed but the inline styles throughout the component could benefit from extraction to a shared styling solution. --- ### 📋 AC Coverage > Based on linked issue #5 - [x] Search bar with query typing and real-time suggestions - Typing triggers debounced suggestions via `SearchSuggestions` component - [x] Clear message when no results found - Empty state shows "🔍 No books found" message - [x] Click search result navigates to book detail - `navigate(`/books/${book.id}`)` on suggestion click - [x] Filter by genre, author, reading status - Filters panel with all three options implemented - [x] Django backend integration - Uses `booksApi.searchBooks()` which calls `GET /api/books/` - [x] Mobile-optimized search - Voice search, responsive layout, WCAG 2.1 touch targets, single-column grid on mobile
marko added 1 commit 2026-05-29 05:10:14 +00:00
Author
Owner

Addressed — All Review Issues Resolved

🔴 Blocking — Fixed

1. SpeechRecognition type declarations (useVoiceSearch.ts ~Line 19)

  • Created frontend/src/types/speech-recognition.d.ts with full type declarations for SpeechRecognition, SpeechRecognitionEvent, SpeechRecognitionErrorEvent, and the Window interface extensions
  • The file covers all types used in the hook — no dependency on global type definitions
  • Commit: ade810a

2. Direct DOM manipulation (SearchSuggestions.tsx ~Lines 89-100)

  • Removed onMouseEnter/onMouseLeave inline style mutations entirely
  • Created SearchSuggestions.module.css with .suggestionItem:hover pseudo-class handling the background highlight via CSS
  • The same pattern was also fixed in Library.tsx (~Lines 493-500) — created Library.module.css with .bookCard:hover for the lift effect
  • No more e.currentTarget as HTMLElement or inline style mutations

🟡 Suggestions — Addressed

  • Shared useDebounce hook: Extracted to frontend/src/hooks/useDebounce.ts. Both Library.tsx and SearchSuggestions.tsx now import from the shared module. Exported via hooks/index.ts.
  • CSS modules: SearchSuggestions.module.css and Library.module.css now handle hover states declaratively via :hover pseudo-classes.
## ✅ Addressed — All Review Issues Resolved ### 🔴 Blocking — Fixed **1. SpeechRecognition type declarations (`useVoiceSearch.ts` ~Line 19)** - Created `frontend/src/types/speech-recognition.d.ts` with full type declarations for `SpeechRecognition`, `SpeechRecognitionEvent`, `SpeechRecognitionErrorEvent`, and the `Window` interface extensions - The file covers all types used in the hook — no dependency on global type definitions - Commit: `ade810a` **2. Direct DOM manipulation (`SearchSuggestions.tsx` ~Lines 89-100)** - Removed `onMouseEnter`/`onMouseLeave` inline style mutations entirely - Created `SearchSuggestions.module.css` with `.suggestionItem:hover` pseudo-class handling the background highlight via CSS - The same pattern was also fixed in `Library.tsx` (~Lines 493-500) — created `Library.module.css` with `.bookCard:hover` for the lift effect - No more `e.currentTarget as HTMLElement` or inline style mutations ### 🟡 Suggestions — Addressed - **Shared `useDebounce` hook**: Extracted to `frontend/src/hooks/useDebounce.ts`. Both `Library.tsx` and `SearchSuggestions.tsx` now import from the shared module. Exported via `hooks/index.ts`. - **CSS modules**: `SearchSuggestions.module.css` and `Library.module.css` now handle hover states declaratively via `:hover` pseudo-classes.
crisleo94 approved these changes 2026-05-29 05:12:58 +00:00
crisleo94 merged commit 3f626259e8 into main 2026-05-29 05:13:03 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No labels
3 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: HermesFactory/cloud-reader#24