Commit Graph
39 Commits
Author SHA1 Message Date
john-okeefe 7cd88b6107 chore(templates): regenerate all templ generated Go files
Regenerated all _templ.go files after running templ generate. Changes
include updated FileName references (relative path normalization) and
line number adjustments from the templ code generator.
2026-04-24 14:03:16 -04:00
john-okeefe a157c546fd feat: add book detail page links from browse pages
Add clickable links to book detail page (/media/:uuid) from:

- Dashboard: BookCard components now link to detail page
  - Changed from data-action pattern to direct <a> tags
  - Removes unused viewBook() function and switch case
  - Follows progressive enhancement (works without JS)

- Collections: Book titles link to detail page
  - Books displayed in collection detail view

- Progress: Book titles link to detail page
  - Progress cards now have clickable title links

All links use direct navigation for better UX and progressive enhancement.
Book detail page can display comprehensive metadata, reading progress,
sync status, and external service links.
2026-03-28 23:54:42 -04:00
john-okeefe 75df623982 Fix collections page Alpine errors and modal container issues
Fixed multiple issues preventing the collections page and modals from working correctly:

1. Alpine Expression Error on page load:
   - Added missing semicolon between function calls in x-init directive
   - Added missing parentheses to initializeCollectionWebSocket() call
   - Collections page now loads without JavaScript errors

2. Modal container removal bug:
   - Fixed closeCollectionModal() removing #modal-container parent element
   - Changed from modal.parentElement.remove() to modal.remove()
   - Modal can now be opened and closed multiple times without errors
   - Fixes htmx:targetError when trying to open modal after first close

3. Emoji grid display:
   - Modal now properly preserves container across open/close cycles
   - setupHTMXModalInit() can successfully repopulate icon grid
   - Emoji picker displays correctly on all modal opens

Technical details:
- templates/collections.templ: Fixed x-init syntax errors
- web/src/collections.ts: Fixed modal close logic to preserve container
- Modal container persists across HTMX swaps, allowing repeated use
2026-03-28 21:20:58 -04:00
john-okeefe e74eeb5c5b feat: implement collections book picker with Alpine.store
Add multi-select book picker modal for collections using Alpine.js patterns:
- Alpine.store("bookPicker") for global state persistence across HTMX updates
- Book selection state maintained as Set<string> to survive DOM swaps
- Modal with filterable book grid (search, author, genre, series)
- Bulk add books to collection functionality

Templates:
- collections.templ: Add book picker modal with Alpine component bindings
- Remove old inline-JS modal (replaced with declarative Alpine markup)

TypeScript:
- web/src/bookPicker.ts: New module with Alpine.store and Alpine.data definitions
- web/src/main.ts: Import bookPicker module
- web/src/collections.ts: Remove old modal functions (replaced by Alpine)

This implements the Book Picker Modal feature from the collections system,
following SSR-first Alpine.js patterns with HTMX for dynamic updates.

Fixes "Add Books" button being disabled - modal now fully functional.
2026-03-20 22:58:09 -04:00
john-okeefe 9ae99d0ddd feat: add functional book picker modal to collections
Update CollectionDetail template to enable book picker:

Enable Add Books button:
- Remove disabled attribute and inline JavaScript handlers
- Wire to $store.bookPicker.open() using Alpine store

Remove old modal:
- Delete non-functional inline-JavaScript modal (add-books-modal)
- Remove inline event handlers (onchange, onclick)
- Clean up unused DOM elements

Add new book picker modal:
- Full-screen modal with HTMX-powered filtering UI
- Search by title, author, genre with live filtering
- Multi-select checkboxes with Alpine.store state persistence
- Selected count display and submit functionality
- Clear filters resets search (preserves selections)
- ESC key closes modal via Alpine event listener

SSR-first implementation:
- Alpine.store.bookPicker manages all state (no DOM state)
- HTMX swaps book grid without losing selections
- Checkboxes re-rendered from store state after DOM swap
- Selection persists across pagination and filter changes
- No class="hidden" for stateful UI (use x-show)
- style="display: none;" prevents FOUC on x-show elements

Replaces non-functional inline JavaScript approach.
Matches bookshelf filtering UX for consistency.

Changes to collections_templ.go are auto-generated from .templ file.
2026-03-20 11:51:11 -04:00
john-okeefe 6d92dff5e3 feat(collections): add book picker modal and fix icon picker
- Add book picker modal with Alpine.js state management for selecting books
- Add toggleBookPickerBook, isBookPickerBookSelected, getBookPickerSelectedCount methods
- Add clearBookPickerFilters function to reset filter form
- Fix icon picker: add showAllIcons function to reset icon search
- Fix setupHTMXModalInit to properly initialize Alpine tree after HTMX swap
- Update collections template with book picker modal structure
2026-03-16 16:24:10 -04:00
john-okeefe af7533529c refactor(templates): remove duplicate main.js script tags, consolidate to header component
Remove redundant <script src="/static/main.js" defer></script> tags from 17+
templates that include the @Header component, eliminating duplicate script
loading that was causing Alpine.js to initialize twice per page load.

The header.templ component now serves as the single source of truth for
main.js inclusion, following the DRY principle and ensuring consistent
script loading across all pages that use the header navigation.

Additionally, add type="button" attribute to all buttons in header navigation
to prevent default form submission behavior when buttons are clicked.

Changes:
- Remove main.js script tag from templates using @Header component
- Keep main.js in header.templ (line 279) as universal inclusion point
- Preserve main.js in special pages: index.templ, login.templ, register.templ
  (these don't use @Header and are standalone entry points)
- Add type="button" to theme toggle, theme selection, wood paneling, and user menu buttons
  to prevent unwanted form submissions or page navigation

Benefits:
- Eliminates Alpine.js double-initialization bug
- Reduces HTTP requests (one script load instead of two)
- Improves maintainability (add header, get scripts automatically)
- Fixes broken @click handlers on collections, devices, and other pages
- Prevents buttons from triggering default form submission behavior

Technical notes:
- Templates affected: admin, analytics, bookshelf, collection_rules,
  collections, conflicts, custom_section, dashboard, devices, docs,
  library, profile, progress, queue, unlinked_books
- No changes to entry pages (index, login, register) which don't use @Header
- HTMX script remains in individual templates (stateless, no double-load issue)
- All interactive buttons in header now explicitly marked type="button" to
  prevent default browser form submission behavior

Related to: previous commit fixing Vite code-splitting
2026-03-13 22:25:12 -04:00
john-okeefe 41e7445524 refactor: remove inline WebSocket code from templates
collections.templ:
- Removed ~75 lines of inline WebSocket JS
- Added initializeCollectionWebSocket using websocket.ts utility
- Updated template to use x-init for WebSocket init

admin.templ:
- Removed ~55 lines of inline WebSocket JS
- Added initializeScanWebSocket using websocket.ts utility
- Updated template to use x-init for WebSocket init

Both now use the shared websocket.ts createWebSocket function
2026-03-13 12:51:11 -04:00
john-okeefe 06461a3202 refactor(alpine): migrate remaining pages to x-init declarative initialization
- Remove DOMContentLoaded event listeners from analytics.ts and docs.ts
- Rely on x-init attribute in templates for page initialization
- Clean up unused exports from collections.ts Alpine data
- Add x-init calls to admin_library, analytics, and docs templates
- Normalize quote style in collections WebSocket script (single to double)
- Disable Add Books button in collection detail (pending implementation)
2026-03-12 18:13:12 -04:00
john-okeefe b4cf1ddafa style: apply code formatting to generated templates and TypeScript files
- Regenerate Go template files with updated FileName paths for error reporting
- Apply Prettier formatting to api-explorer-docs.ts for consistency
- Format long function signatures across multiple lines for readability
- Format long conditional chains for better code clarity

Changes are purely formatting and do not affect functionality:
- api-explorer-docs.ts: Format initAPIExplorerDoc, tryDocEndpoint, and other functions
- Generated _templ.go files: Update FileName paths from relative to absolute (e.g., "admin.templ" → "templates/admin.templ")

This ensures consistent code style across the codebase and improves
error reporting by providing full file paths in template error messages.
2026-03-12 15:44:46 -04:00
john-okeefe 2e65cd7ff5 fix(templates): correct file paths in generated template error reporting
- Update FileName paths in error reporting from relative to absolute paths
- Changes template error paths from 'filename.templ' to 'templates/filename.templ'
- Affects 21 auto-generated Go template files compiled from .templ sources

This fix ensures that template rendering errors provide accurate file locations,
making debugging and error tracking more reliable. The generated files now
correctly reference their source template locations with full path information.

Note: These files are auto-generated by the templ compiler from the .templ
source files committed in the previous commit.
2026-03-12 09:04:26 -04:00
john-okeefe af337c88e2 build: regenerate templ files and compiled CSS
Generated files updated to reflect:
- New admin_settings.templ template
- Updated admin_sidebar.templ with Settings link
- Fixed devices.templ with correct regenerate-token path
- Compiled TailwindCSS with any style changes
2026-03-11 16:42:56 -04:00
john-okeefe 2214288d9c style: Standardize template formatting and indentation
Applies consistent code formatting to template source files:

Changes:
- Fixed inconsistent indentation in admin_library.templ (tabs vs spaces)
- Standardized whitespace alignment across multiple template files
- Ensured generated Go files match reformatted sources

Templates Updated:
- admin_library.templ: Indentation fixes for AdminSidebar component
- analytics.templ: Whitespace normalization
- collections.templ: Whitespace normalization
- conflicts.templ: Whitespace normalization
- dashboard.templ: Whitespace normalization

Generated Go Files:
- All corresponding *_templ.go files regenerated to match

These are cosmetic formatting changes only - no functional changes.
Alpine.js integration, template logic, and application behavior unchanged.
2026-03-11 11:39:42 -04:00
john-okeefe 5faf562250 Fix Path A: Resolve function mismatches and missing functions
Fixed template function call mismatches:
- conflicts.templ: Renamed showConflictModal→showResolveModal, hideConflictModal→hideResolveModal, handleResolveConflict→handleResolveSubmit
- collections.templ: Fixed case mismatch addSelectedBooks→addbooksToAdd
- queue.templ: Removed dead /static/queue.js reference
- progress.templ: Removed vestigial x-data="progress" attribute

Added missing queue functions:
- showQueueItemModal() - Shows queue item detail modal
- hideQueueItemModal() - Hides queue item modal
- filterQueue() - Filters queue by status (stubbed)

Fixed build errors:
- main.ts: Removed imports for deleted themeDropdown.ts and woodPaneling.ts files

All fixes are minimal and conservative. No breaking changes to existing functionality.
TypeScript builds successfully (168KB main.js).
Templates regenerate successfully.
2026-03-11 11:04:53 -04:00
john-okeefe 083f152b35 Safety backup before Path A fixes - fixing function mismatches and missing functions 2026-03-11 11:01:43 -04:00
john-okeefe 647644fdce refactor: Consolidate script imports and update Alpine.js syntax in templates
This commit updates all generated template files and the header.templ source
to use consolidated script bundles and modern Alpine.js syntax.

Changes to templates/*.go (generated from .templ source files):
- Replace individual script imports (admin.js, toast.js, header.js, etc.)
  with single /static/main.js bundle
- Convert onclick attributes to Alpine.js @click directives for better
  integration with reactive components
- Add x-data attributes to body elements where needed for Alpine components
- Update event handlers to use Alpine.js syntax consistently

Changes to templates/header.templ source file:
- Add Alpine.js test div with x-data and x-init for debugging
- Reformat theme dropdown and user menu markup with proper indentation
- Maintain consistent Alpine.js directive formatting throughout

This change reduces the number of HTTP requests and ensures consistent
Alpine.js integration across all pages.
2026-03-09 20:58:46 -04:00
john-okeefe a84ffb253e chore: Remove obsolete documentation and regenerate template
Remove outdated migration documentation and regenerate template after
script tag cleanup.

Changes:
- Delete ECHO_V5_MIGRATION.md: Obsolete migration plan, superseded by
  ESBUILD_MIGRATION_PLAN.md
- Delete esbuild-setup.md: Incomplete setup document, replaced by
  comprehensive migration plan
- Regenerate templates/collections_templ.go: Remove collections.js
  script tag (now using main.js bundle)

Template update:
- Removed <script src="/static/collections.js"> from template
- Now uses single main.js bundle (ESBuild output)
- Line number adjustments in generated Go code

Cleanup of obsolete documentation as part of ESBuild migration.
2026-03-08 01:14:48 -05:00
john-okeefe 9b3d8cc949 feat: implement collection library filter with WebSocket improvements and test coverage
This commit adds comprehensive functionality for filtering collections by library,
improves WebSocket real-time updates with user activity detection, and adds
extensive test coverage.

## Core Features

### Collection Library Filter
- Added library_id parameter to media-items search API
- Collections can now be filtered by specific library
- Toggle UI component for enabling/disabling library filter
- Default state is "checked" when library_id is present
- Consistent behavior across partial and fuzzy search modes

### WebSocket Auto-Reload Mitigation
- Added user activity detection to prevent disruptive page reloads
- Checks if user is actively typing in INPUT/TEXTAREA/SELECT elements
- Skips auto-reload when user is interacting with form elements
- Toast notifications still show for awareness
- Prevents data loss during editing operations

## Implementation Changes

### Backend
- internal/database/queries.sql.go: Added library filter support to search queries
- internal/handlers/media.go: Enhanced search with library_id parameter validation
- internal/handlers/collections.go: Updated collection handlers with library filtering
- internal/sync/websocket.go: Improved broadcast mechanism with user-scoped updates
- internal/router/frontend.go: Pass libraryID to collection templates

### Frontend
- templates/collections.templ: Added library filter toggle UI component
- web/src/collections.ts: TypeScript implementation with WebSocket integration
- templates/collections_templ.go: Generated template code

### Testing
- cmd/server/tests/search_test.go: Added TestCollectionSearchLibraryFilter
- cmd/server/tests/websocket_test.go: Added TestWebSocketUserScopedBroadcast
- New helper functions for creating libraries and media items via API
- Comprehensive test coverage for library filtering and user-scoped broadcasts

## API Documentation Updates

### Bruno Tests (Comprehensive Documentation)
- bruno/collections/*: Added detailed API documentation for all collection endpoints
- bruno/devices/*: Added device management and sync API documentation
- bruno/devices/kobo/api.yml: Kobo-specific sync protocol docs
- bruno/devices/koreader/api.yml: KOReader-specific sync protocol docs
- bruno/opds/*: Added OPDS feed and download endpoint documentation
- bruno/library/browse-folders.yml: Library folder browsing API docs

### New Bruno Tests
- bruno/media-items/Search All Libraries.yml: Test search without library filter
- bruno/media-items/Search Specific Library.yml: Test search with library filter
- bruno/media-items/Search Invalid Library ID.yml: Test error handling

## Documentation

- docs/developer/api/media-items/search_media_items.md: Updated with library_id parameter
- IMPLEMENTATION_COLLECTION_FIX.md: Comprehensive implementation guide with test scenarios

## Testing

### Integration Tests
- Library filter tests verify correct filtering across multiple libraries
- Invalid library_id tests ensure proper error handling
- WebSocket tests verify user-scoped broadcast behavior
- User A no longer receives User B's collection updates

### Manual Testing Scenarios
- Open collection in multiple tabs - updates propagate correctly
- Type in search box while another tab adds books - no disruptive reload
- Add/remove books from collection - toast notifications appear
- Toggle library filter - results update dynamically

## Technical Details

- WebSocket broadcasts are now user-scoped for privacy
- Active element detection uses tagName and contenteditable attributes
- Library ID validation uses UUID format checking
- Progressive enhancement maintained - page works without JavaScript
- All changes follow PROJECT_GUIDELINES.md conventions
- TypeScript only for frontend logic
- TailwindCSS only for styling
- Procedural programming style throughout

## Breaking Changes

None - all changes are additive and backward compatible.
2026-03-04 22:37:47 -05:00
john-okeefe bdc3dcff96 refactor(templates): migrate collections page to HTMX modals
Refactor collections.templ to use HTMX-powered modals instead of
client-side JavaScript modals. This aligns with project guidelines
for server-side rendering and progressive enhancement.

Key changes:

1. Remove inline modal HTML and JavaScript:
   - Delete hardcoded create-modal div with inline form
   - Remove all inline JavaScript (showCreateModal, hideCreateModal,
     selectColor, handleCreate, viewCollection, editCollection,
     deleteCollection, logout)

2. Add HTMX modal infrastructure:
   - Add modal container div: <div id="modal-container"></div>
   - Load modals dynamically via hx-get attributes
   - Remove JavaScript modal toggling functions

3. Refactor collection cards for event delegation:
   - Change from <a> wrapper to <div> with onclick="navigateToCollection()"
   - Add data-href attribute for navigation target
   - Wrap edit/delete buttons in separate container to prevent
     unwanted card navigation when clicking buttons

4. Update buttons to use HTMX:
   - Create button: hx-get="/collections/create-modal"
   - Edit button: hx-get="/collections/{id}/edit-modal"
   - Delete button: hx-delete="/api/collections/{id}" with hx-confirm
   - Restore System button: hx-get="/collections/restore-modal"

5. Remove redundant forms:
   - Delete empty-state "Create Your First Collection" button's
     inline onclick (now uses HTMX like the main create button)

6. Add external JavaScript:
   - Load /static/collections.js for helper functions
     (navigateToCollection, setupHTMXAuth, etc.)

Benefits:
- Smaller initial page load (modal HTML loaded on-demand)
- Server-side rendering follows project guidelines
- Progressive enhancement (page works without JavaScript)
- Consistent with auth page modal pattern
- Easier to maintain (modal logic separated into dedicated templates)
2026-03-01 21:00:20 -05:00
john-okeefe 42a20e3be3 feat: Improve wood paneling border colors and background blend
- Update wood-light border from harsh black (#2a2a2a) to lighter warm brown (#8b5a2b) for better harmony with light background
- Update wood-dark border from #5c3317 to #7a5228 (slightly lighter medium brown) for improved visibility on dark backgrounds
- Update wood-mahogany border from #5c3317 to #8b3a3a (medium red-brown) to enhance mahogany's characteristic reddish tones
- Reduce background blend opacity from 60% to 40% to create more subtle text area background that complements new border colors

These changes improve visual consistency between border colors and their respective wood paneling backgrounds while maintaining good text contrast across all wood themes.
2026-03-01 12:22:36 -05:00
john-okeefe 0b666f3fdd feat: Add collection detail page with /collections/:id route
Add comprehensive collection detail page that works for both system collections
(continue-reading, recently-added, not-started) and user collections.

Backend changes:
- Add new /collections/:id route in internal/router/frontend.go
  - Fetches collection using GetCollection with UUID parameter
  - Determines collection type from QueryType field
  - Resolves library_id for system collections
  - Converts database.MediaItems to handlers.BookInfo for display
  - Renders CollectionDetail template with collection and books data

- Update SectionData struct in internal/handlers/collections.go
  - Add CollectionID string field for view all links

- Update BuildSections() in internal/handlers/dashboard.go
  - Pass CollectionID to SectionData for proper link generation

- Simplify getViewAllURL() in internal/handlers/dashboard.go
  - Return /collections/{collectionID} instead of /section/{type}
  - Works uniformly for both system and user collections

Frontend changes:
- Fix CollectionDetail template in templates/collections.templ
  - Fix broken div nesting causing compilation error
  - Add null check for CoverImagePath to prevent broken images
  - Update aspect ratio to modern aspect-[3/4] syntax
  - Use responsive widths (w-16 sm:w-20) for mobile/desktop
  - Improve card layout with horizontal flex structure
  - Add placeholder image fallback for books without covers
  - Remove erroneous renderBooks() function call

This change aligns with the backend update where system collections are
now pre-made user collections in the database with query_type fields.
All collections can now use the same CollectionDetail template for a
consistent viewing experience.
2026-03-01 00:28:54 -05:00
john-okeefe b7e0e7ffbb generated: update templ files after admin.templ changes 2026-02-26 10:12:02 -05:00
john-okeefe 4b43116f13 refactor(templates): apply activeClass helper and full-width layout
- Replace inline ternary operators with activeClass helper function
- Change layout containers from max-w-7xl to w-full for full-width design
- Update file path references in error messages for better debugging
2026-02-24 13:41:19 -05:00
john-okeefe e7f30a00c0 style(templates): fix code formatting with consistent indentation
-- Reformat all generated template Go files with consistent indentation
-- Standardize code style across templates/
-- No functional changes, formatting only
-- Generated by templ tool during development
2026-02-23 20:24:10 -05:00
john-okeefe 9ea0ec5a3e feat(templates): consolidate admin and profile templates
Add admin_users.templ for user management interface with delete, password
reset, and edit capabilities. Add profile.templ and related components for
user profile management. Remove admin_profile.templ. Update all templates
to use new consolidated API endpoints.
2026-02-22 01:58:02 -05:00
john-okeefe 0c515a277c refactor(templates): add error toast support to page templates
Update all page templates to accept an optional error message parameter
and display it via the ErrorToast component when data loading fails.
2026-02-20 13:25:49 -05:00
john-okeefe 81c72e706a chore(templates): regenerate template files after templ update
Regenerate all _templ.go files with latest templ generator.
Changes are minimal formatting updates (error message file paths).
2026-02-16 16:51:10 -05:00
john-okeefe 2a64ca423f Refactor: Eliminate duplicate types - Use handler types directly
- Deleted templates.CollectionDetailData - using templates.CollectionData everywhere
- Deleted templates.BookData - using handlers.BookInfo everywhere
- Deleted templates.DeviceData - using handlers.DeviceInfo everywhere
- Deleted templates.ProgressItemData - using handlers.ProgressWithMedia everywhere
- Deleted templates.convertDevices() helper - Use handlers types directly in templates
- Enhanced handlers.ProgressWithMedia with device metadata fields
- Added handlers.getDeviceIcon() helper
- Updated all templates to import handlers package
- Cleaned up unused imports

This aligns codebase with templ's design philosophy (use Go types directly, no parallel type system)
2026-02-12 19:48:07 -05:00
john-okeefe 826ea2de26 chore(templates): regenerate templates from build process
- Update all templates from latest templ build
- No functional changes, just formatting/build artifacts
- Includes updates to admin, collections, conflicts, devices, and queue templates
- Part of regular template maintenance
2026-02-06 21:59:20 -05:00
john-okeefe ed0a41e2d1 refactor: remove templates/ prefix from template error file names
Clean up generated template code to use simpler file paths in error messages by removing the redundant templates/ directory prefix.
2026-02-02 21:18:56 -05:00
john-okeefe afdcc7b589 docs: add API explorer template component and fix rendering
Phase 3 part 1: Add interactive API explorer
- Create templates/api_explorer.templ with mock and real modes
- Add EndpointInfo and APIExplorerData types to templates/types.go
- Fix markdown rendering with UnsafeHTML.ToComponent()
- Add templ import for Component support
- API explorer supports:
  - Mock data mode for non-authenticated users
  - Real execution mode for logged-in users
  - Request/response display
  - cURL generation
  - Copy to clipboard
2026-02-02 08:56:23 -05:00
john-okeefe a8e904a7fb regenerate templ files with updated file paths 2026-02-01 21:18:05 -05:00
john-okeefe bb713f6300 Rename frontend template references: Bookmann → Bookhoard
Template changes:
- Update page titles: "Bookmann" → "Bookhoard"
- Update header branding and navigation text
- Regenerate compiled .go templates from .templ sources
- Update all UI references in HTML templates

This is part 3 of the project rename to Bookhoard.
2026-02-01 16:11:59 -05:00
john-okeefe 40c732481a feat(collections): add real-time updates via WebSocket (Limitation #4)
Implement real-time collection updates when books are added/removed:

Backend Changes:
- Added connManager to CollectionHandler struct
- Updated constructor to accept ConnectionManager
- Updated all NewCollectionHandler() calls in ebook.go and main.go
- Added WebSocket broadcasts in AddBooks() handler
- Added WebSocket broadcasts in BulkRemoveBooks() handler
- Broadcasts collection_updated events with:
  - collection_id: Which collection changed
  - action: books_added or books_removed
  - book_ids: Array of affected book IDs
  - count: Number of books changed

Frontend Changes:
- Added WebSocket connection in collections UI
- connectWebSocket() establishes connection to /ws/sync
- Listens for collection_updated events
- Shows toast notification on collection change
- Auto-reloads page after 1 second to show updated book list
- Auto-reconnect on disconnect (5s delay)
- Error handling for WebSocket failures

WebSocket Event Format:
{
  "type": "collection_updated",
  "timestamp": "2026-02-01T12:00:00Z",
  "data": {
    "collection_id": "uuid",
    "action": "books_added",
    "book_ids": ["uuid1", "uuid2"],
    "count": 2
  }
}

User Experience:
- When another user adds books to a collection, all connected clients see:
  1. Toast notification: "Collection updated: books_added (2 books)"
  2. Page auto-refreshes after 1 second
  3. Updated book list displays
- Same for book removal
- Works across multiple browser tabs/devices
- No manual refresh needed

Technical Notes:
- Broadcasts to ALL connected WebSocket clients
- Client-side filtering by collection_id
- Existing progress/conflict broadcasts continue to work
- Connection manager handles broadcast distribution

Resolves Limitation #4: Real-time Collection Updates
2026-02-01 00:54:41 -05:00
john-okeefe 4bc7a842b5 feat(collections): add collection-specific search/filter (Limitation #3)
Add search and filter within a collection:

Frontend Implementation:
- Search input box in collection detail toolbar
- filterCollectionBooks() JavaScript function
- Real-time filtering of books by title and author
- Case-insensitive search
- Hides non-matching book cards
- Shows all books when search is cleared

How It Works:
- AllBooks array contains book data from server render
- On keyup, filters books by title and author
- Toggles display property on book cards
- Empty state has ID and is not hidden
- Pure client-side filtering (no server round-trips)

User Experience:
- Instant search results as user types
- No page reload required
- Works with existing multi-select for bulk operations
- Search box always visible in toolbar

Resolves Limitation #3: Collection-Specific Search
2026-02-01 00:52:45 -05:00
john-okeefe 508bfb0387 feat(collections): implement bulk add and remove books (Limitations #2 & #5)
Complete bulk operations for collections management:

BULK ADD BOOKS:
- Implemented searchBooks() with real API integration
- Multi-select checkboxes for book selection
- SelectedBooks Set tracks chosen books
- AddSelectedBooks() sends array to existing endpoint
- Uses existing POST /api/collections/:id/books endpoint

BULK REMOVE BOOKS:
- New endpoint: POST /api/collections/:id/books/bulk-remove
- Checkboxes on each book card for selection
- BooksToRemove Set tracks selections
- Live counter showing selected count
- BulkRemoveBooks() handler removes all in one API call
- More efficient than N individual DELETE requests

Frontend Changes:
- Selected counter badge shows number selected
- Bulk remove button (enabled when books selected)
- Checkboxes on all books for multi-select
- Confirmation dialog for bulk operations
- Toast notifications with counts

Backend Changes:
- BulkRemoveBooks() handler in collections.go
- Accepts book_ids array, returns removed/total counts
- Iterates and removes, counting successes
- Route: POST /api/collections/:id/books/bulk-remove

API Request:
{
  "book_ids": ["uuid1", "uuid2", "uuid3"]
}

API Response:
{
  "removed": 3,
  "total": 3
}

Tests Added:
- TestCompareValues_* (existing)
- TestEvaluateRule_* (existing)

Resolves Limitations #2 (Bulk Operations) and #5 (Bulk Remove)
2026-02-01 00:52:09 -05:00
john-okeefe 60453c3e21 chore(templates): regenerate templates after Phase 9 updates
Regenerate Go template files after adding:
- Progress visualization components
- Unlinked books resolution interface
- Collection rules builder
- Enhanced device settings with view preferences
- Updated type definitions with new data structures

Template regeneration ensures:
- Compiled templates match source .templ files
- Type safety for template data structures
- Proper Go code generation for rendering

No functional changes - purely compilation artifacts from
templ template processor updates.
2026-02-01 00:27:08 -05:00
john-okeefe 6266a06abb feat: Add SSR for conflicts and queue pages
- Update conflicts.templ to accept pre-rendered data
- Update queue.templ to accept pre-rendered data
- Update /conflicts and /queue routes in main.go for SSR
- Update stats rendering to use server-side values
- Add server-side conflict list rendering
- Add server-side queue list rendering
- Update conflicts.js to use location.reload() after operations
- Update queue.js to use location.reload() after operations
- Remove initial load calls from JavaScript files

Preserves all API endpoints and backward compatibility
2026-01-31 23:14:08 -05:00
john-okeefe 033d66f503 feat(templates): Add hybrid SSR collection templates
- Add Collection template with SSR support
- Add CollectionDetail template for book display
- Templates accept pre-rendered data from server
2026-01-31 22:32:47 -05:00