Commit Graph
32 Commits
Author SHA1 Message Date
john-okeefe 04e2a069d6 fix(dashboard): stop duplicating items after scan completion
Release / build-and-push (push) Successful in 5m9s
The scan-complete handler in dashboard.ts attempted to deduplicate book
cards by querying [data-media-item-id], but neither the client-side
renderBookCard nor the server-side BookCard template ever set that
attribute. As a result the dedup Set was always empty, every item from
the API response was treated as new, and all items were prepended via
insertAdjacentHTML('afterbegin', ...) on every 5-minute scan — causing
visible duplication (doubling, tripling) that only cleared on page
refresh.

Fix by replacing the fragile dedup-and-prepend logic with a per-track
full innerHTML replace. This is simpler, correctly handles items that
should be removed after a scan (the old code never removed anything),
and also removes stale sections no longer returned by the API.

Additional hardening:
- Add data-media-item-id to both renderBookCard (dashboard.ts) and the
  server-side card wrapper (dashboard.templ) so server-rendered and
  JS-rendered cards are structurally identical.
- Guard the bookhoard:scan-complete listener registration with a
  module-level boolean (scanListenerRegistered) so the handler cannot
  accumulate if Alpine ever re-inits the body subtree.
- Remove debug console.log statements from the scan handler.
2026-08-10 14:46:13 -04:00
john-okeefe ab465d8e0e feat(ui): adopt book-open brand icon and add SVG favicon
Bring the tighten-ui brand treatment into new-ui:

- Replace the emoji book (📚) in the sidebar header with the book-open
  icon rendered in the theme accent color, matching the tighten-ui
  header brand (templates/header.templ).
- Add web/static/favicon.svg (book-open glyph, tokyo-night accent
  #7aa2f7 stroke) and reference it from the <head> of all 27 page
  templates, so the favicon is present on login/setup/error pages too.
- Regenerate templ output for all affected templates.
2026-08-10 13:43:13 -04:00
john-okeefe 9165c4eb3f feat(ui): use a book-open icon for the card read action
Swaps the play (triangle) icon for book-open on book cards, since the
action is to start reading rather than play media.
2026-08-06 08:01:33 -04:00
john-okeefe 9ef6c5b6ed feat(ui): split book-card play action into reader/detail routing
The play button on book cards now opens the reader directly, instead of
always going to the detail page. Cards with an active progress sync
conflict route the play button to the detail page (which hosts the
conflict dialogue and resolves before writing progress), so the user is
never silently dropped into the reader with an unresolved conflict.

Backend:
- Add HasConflict to BookInfo and stamp it via ListSyncConflictsByUser
  (MarkActiveConflicts / MarkActiveConflictsSections) on the dashboard,
  bookshelf, series, tag, and search result card builders.
- Each page issues a single conflict query regardless of card count.

BookCard:
- Restructure into a detail link (cover + meta) with the play action as a
  sibling overlay using a pointer-events split: the container passes
  clicks through to detail while only the circular button routes to the
  reader. No nested anchors.
- On touch devices (hover: none) the play button stays visible.

Fix: carousel nav buttons had opacity-0 without pointer-events-none, so
they swallowed hover/clicks over book cards on the dashboard. They are
now click-through until the carousel is hovered.
2026-08-06 07:52:20 -04:00
john-okeefe 07578e0206 feat(ui): redesign dashboard, bookshelf, book detail, and auth pages
- Dashboard: page heading, bold section headers with accent icon tiles,
  carousel chevrons as SVG icons with theme-aware gradients (wood-paneling
  gradient classes preserved), and a cinematic BookCard (hover overlay with
  a quick-action button). BookCard is now fluid so it fills both the
  carousel slot and the bookshelf grid.
- Bookshelf: the filter wall becomes a search toolbar + a slide-in filter
  drawer (filtersOpen state added to the bookshelf Alpine component). Every
  filter input, the tristate cover toggle, tag autocomplete, save/load/clear
  actions, HTMX search/sort, and pagination are preserved.
- Book detail: blurred cover backdrop hero, rounded-2xl cover, bold
  typography, .btn action bar, progress/metadata cards, chip-style external
  links. All interactive rating, modals, and data-attrs preserved.
- Auth/landing: brand-gradient hero for index/login/register, icon feature
  cards, data-driven theme select (ThemeOptions). All ids (#theme-select,
  #result, #auth-result, password-requirement ids) and Alpine init preserved.
2026-08-05 16:44:52 -04:00
john-okeefe 8e48aa4334 feat(templates): add library switcher to collections and dashboard pages
Replace inline library switcher HTML with shared LibrarySwitcher component
across all collection pages and the dashboard.

templates/collections.templ (Collection):
- Update signature to accept libData []LibraryData, currentLibraryID
- Add @LibrarySwitcher(libData, currentLibraryID) after header
- Change x-init to initCollectionsPage() for unified initialization

templates/collections.templ (CollectionDetail):
- Update signature to accept libData []LibraryData
- Add @LibrarySwitcher(libData, libraryID) after header
- Fix broken "Back to Collections" button: replace non-existent
  backToCollections Alpine method with a plain <a href="/collections"> link
- Change x-init to initCollectionsPage() for unified initialization

templates/dashboard.templ:
- Replace 46-line inline sticky library selector (lines 20-66) with
  @LibrarySwitcher(libData, currentLibraryID, DashboardActions())
- Dashboard-specific settings and refresh buttons extracted into the
  DashboardActions sub-component via the variadic actions parameter
2026-05-17 21:12:26 -04:00
john-okeefe 355ae5f7a9 fix(series): remove library switcher from detail page, add title tooltips to BookCard
Remove the library selector dropdown from the series detail page
since the page is scoped to the library from the browse page.
Replace it with a simple '← All Series' back link in the sticky bar.

Add title attributes to the shared BookCard template so the full
book title and author are visible on hover (useful for truncated
text with line-clamp).
2026-05-08 20:58:43 -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 b77da3a289 refactor: migrate dashboard to SSR-first Alpine.js pattern
Update dashboard to follow SSR-first Alpine.js guidelines:
- Add x-data="dashboard" and x-init="initDashboard()" to body tag
- Wrap initialization in initDashboard() function instead of executing at load time
- Alpine.js only manages UI state, data fetching happens via HTMX/SSR
- Remove immediate initDragAndDrop() call (now called from initDashboard)

This fixes DOM Content Loaded timing issues and follows the established pattern
used in analytics and docs pages. The dashboard now properly supports:
- SSR with initial data rendered server-side
- Alpine.js for interactive UI (drag-drop, modals)
- HTMX for dynamic updates without page reload
- Progressive enhancement (works without JavaScript)
2026-03-20 22:58:18 -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 96e206b671 perf(templates): add defer attribute to main.js script tags
- Add defer attribute to all main.js script includes across 22 template files
- Improves page load performance by allowing HTML parsing to continue without blocking
- Maintains script execution order while enabling parallel resource loading

This optimization reduces page render blocking and improves perceived load times
across all admin and user-facing pages that include the main.js bundle.

Affected pages include: admin dashboard, library management, settings, user
management, analytics, bookshelf, collections, conflicts, custom sections,
devices, documentation, profile, progress tracking, queue, and authentication
pages (login/register).
2026-03-12 09:04:13 -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 0919698cf4 refactor: Consolidate script imports to use main.js bundle
- dashboard.templ: Replaced individual script tags with single main.js import
- admin_users.templ, custom_section.templ: Minor formatting/cleanup
- docs.templ: Updated script imports (excluded from Alpine conversion per user request)
- api.ts, docs.ts, password_validation.ts: Minor updates for compatibility
2026-03-08 21:37:17 -04: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 62d3d50140 fix: Dashboard modal and slider library-specific behavior
Fix multiple issues with dashboard customization modal and slider
not working correctly per library.

Frontend changes in web/src/dashboard.ts:
- Fix openDashboardSettings() to use current library ID
  - Add library_id parameter to dashboard preferences API call
  - Show toast error message on API failure instead of opening modal
  - Prevent opening modal with stale/inaccurate data

- Fix slider query parameter mismatch
  - Change from 'libraryId' to 'library_id' to match backend API
  - Fix DOM query from collectionList.querySelector to document.querySelector
  - Ensure slider targets correct input element

- Fix saveDashboardSettings() to refresh current library
  - Fetch current library data before saving preferences
  - Use library_id from current library, not from URL
  - Show toast error message on save failure
  - Keep modal open on error for user to retry

- Add localStorage persistence for selected library
  - Store selectedLibrary in localStorage after switching
  - Enables persistence across page refreshes

- Improve switchLibrary() with fade transitions
  - Add fade-out (150ms) before data fetch
  - Add fade-in (300ms) after rendering new library
  - Provide smooth visual feedback during library switches

- Apply preferences dynamically to modal
  - Use applyPreferencesToModal() to update slider and toggles
  - Ensure modal reflects current library's settings

Backend changes in internal/router/dashboard.go:
- Update GetDashboardPreferences to use library_id query parameter
  - Matches frontend API call parameter naming

Template changes in templates/dashboard.templ:
- Remove duplicate renderDashboardCollections() inline script
  - Functionality now handled by dashboard.ts

These fixes ensure that:
1. Dashboard settings work correctly per library
2. Slider reflects and updates the correct library's item limit
3. Toggles show accurate visibility state for each library
4. Library switches provide smooth visual feedback
5. Errors are properly surfaced to users via toast messages
2026-03-01 00:29:00 -05:00
john-okeefe a8920a8f6c Add dashboard redesign, custom section builder, and enhanced search functionality
Features:
- Complete dashboard redesign with improved UI components and layout
- Implement custom section builder for personalized book organization
- Add new events tracking system for user interactions
- Enhance search functionality with better static search.js
- Update TypeScript type definitions for API responses

Backend:
- Update Go dependencies in go.mod
- Add new frontend routes in router

Templates:
- Update admin and dashboard templates with new components

Frontend:
- Refactor analytics, collections, conflicts, and queue modules
- Add new documentation features in docs.ts
- Implement linking between books and collections
- Add toast notifications for user feedback
- Include placeholder book SVG asset

This commit consolidates multiple feature additions and improvements
across the entire stack including backend, templates, and frontend.
2026-02-25 16:56:10 -05:00
john-okeefe 3870168452 refactor(dashboard): apply full-width layout and wood paneling
- Remove max-w-7xl constraints from library selector and collections
- Include woodPanelingInit.js script for early paneling application
- Prevent flash of wrong background on page load
- Wood paneling applied only to #collections-container
2026-02-24 13:02:34 -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 a1a14c2af8 feat(dashboard): implement Phase 9 dashboard template and TypeScript for Carousel-style dashboard
Replace library browser with Carousel-style collections carousel:

Template Changes (templates/dashboard.templ):
Complete rewrite from library browser to collections carousel:

1. Dashboard Main Template:
   - Sticky library selector dropdown
   - Customize dashboard button (settings modal)
   - Refresh button
   - Loading spinner for async operations
   - Collections container with carousels

2. CollectionCarousel Component:
   - Collection header with icon, title, description
   - View All link for system collections
   - Horizontal scrollable carousel track
   - Left/right navigation buttons
   - Book cards with cover images
   - Empty state handling

3. BookCard Component:
   - Aspect ratio [2/3] book cover
   - Cover image with fallback to placeholder
   - Title and author display
   - Click handler for viewing book details
   - Hover scale animation

4. DashboardSettingsModal Component:
   - Draggable collection list for reordering
   - Toggle switches for collection visibility
   - "System" badges for system collections
   - "Restore" buttons for system collections
   - Items per section slider (10-50, step 5)
   - Save/Cancel buttons

Template Features:
- Uses IsSystem boolean instead of Type string
- data-is-system attribute for JavaScript
- data-collection-id for DOM manipulation
- Supports drag-and-drop reordering
- Settings modal with live preview

TypeScript Implementation (web/src/dashboard.ts):

Core Functions:
- scrollCarousel: Smooth horizontal scrolling
- openDashboardSettings/closeDashboardSettings: Modal control
- toggleCollectionVisibility: Toggle visibility switches
- saveDashboardSettings: Save preferences to API
  * Collects hidden_collections and collection_order
  * Calls PUT /api/dashboard/preferences
  * Reloads page on success
- restoreSystemCollection: Reset system collection to defaults
  * Confirmation dialog
  * Calls POST /api/dashboard/restore-system-collection
  * Shows toast notifications
- switchLibrary: Switch between libraries
  * Async fetch from API
  * Re-renders collections
- renderCollections: Client-side rendering of collections
- renderBookCard: Generate book card HTML
- viewBook: Placeholder for book detail view
- reloadPage: Refresh page
- updateItemsCount: Update slider display
- initDragAndDrop: Drag-and-drop event handlers

Event Handling:
- Event delegation for performance
- data-action attributes for handler routing
- Proper type checking and null safety
- Error handling with toast notifications

Type Safety:
- Uses SectionData and BookInfo from api.d.ts
- Proper TypeScript types throughout
- Null checks for DOM elements
- Type assertions where needed

This implements Phase 9: Dashboard Template with unified collections terminology and full TypeScript interactivity.
2026-02-19 21:11:53 -05:00
john-okeefe fa16a3d78a Remove custom CSS from main user templates
Remove <style> tags from analytics, bookshelf, conflicts, and dashboard
templates. Convert custom CSS classes (.stat-card, .shelf, .book-item,
.conflict-card, etc.) to TailwindCSS utility classes. Rely on
centralized theme CSS variables in input.css.
2026-02-02 10:27:53 -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 ffb09ccc5e Phase 2 & 3: Update frontend with sorting and filtering UI
- Expand sort dropdown with 12 sorting options
- Add collapsible filter panel with 6 filter types
- Implement JavaScript filter logic (applyFilters, loadMediaItemsWithFilters, displayActiveFilters, clearFilters)
- Add URL state management for shareable filtered/sorted views
- Add active filter chips display with clear functionality
- Support filtering by author, genre, series, language, year range, has_cover
- Restore filters from URL on page load
2026-01-30 08:32:56 -05:00
john-okeefe 056cfb5b24 feat: include search.js script in templates
- Add search.js to bookshelf template
- Add search.js to dashboard template
- Enable search functionality on main pages
2026-01-29 20:20:55 -05:00
john-okeefe 0ef661d158 Fix header component rendering in bookshelf and dashboard templates
- Changed Header component calls from text to proper templ syntax (@Header)
- Header now properly renders navigation, search, theme switcher, and user menu
- Fixed both bookshelf.templ and dashboard.templ templates
2026-01-29 17:06:49 -05:00
john-okeefe c3dcbad177 feat: integrate header component into dashboard page
- Replace navigation bar with Header() component
- Remove duplicate logout function (now in header.js)
- Maintain consistent header across pages
- Update generated template files

This provides consistent navigation and theme switching
functionality across all pages using the reusable header component.
2026-01-29 15:56:18 -05:00
john-okeefe b887c38abf refactor: update templates for new frontend structure
- Extract inline JavaScript from index.templ
- Replace with external script include for theme.js
- All templates reference /static/ for assets
- Cleaner separation of concerns between markup and logic
2026-01-29 14:09:29 -05:00
john-okeefe 6d3db17cf5 feat: update frontend for library system
- Redesign dashboard to show library selection first
- Add media browsing within selected library
- Implement library management interface
- Add user visibility controls for libraries
- Support library type icons and metadata
- Add create library modal with type selection
- Include folder management for each library
- Implement user-specific library access controls

Replaces single ebook library with flexible multi-library system
2026-01-28 11:03:17 -05:00
john-okeefe f8eaca1b08 feat: Add role-based frontend controls
- Update User type to include role field
- Modify dashboard template to conditionally show admin links
- Add protected dashboard route with user context
- Update main.go to serve dashboard with proper authentication
2026-01-26 16:56:22 -05:00
john-okeefe 1140c4215e feat: Implement advanced rating system with half-star precision
- Add 5-star display with half-star support
- Implement dialog-based rating input with 0.5 increments
- Add rating conversion functions (10-point ↔ 5-point)
- Update visual styling for half-star display
- Maintain default 0 rating and "Not rated" state
- Add proper error handling and user feedback
2026-01-26 13:51:50 -05:00
john-okeefe 1bda408448 Add interactive rating display and controls to dashboard 2026-01-26 11:49:51 -05:00
john-okeefe 08e80ae84b refactor: reorganize project structure and update configurations
- Move migrations/ to database/schema/ for clarity on database schema definitions
- Move sqlc.yaml to internal/database/ to group with database code
- Move static/ to cmd/server/static/ to co-locate with server
- Update all configuration files and documentation
- Follow Go project conventions for better organization
2026-01-24 23:40:31 -05:00
john-okeefe 5f5870b95d Migrate to templ: Convert all HTML templates to type-safe templ components
- Add templ dependency for type-safe HTML rendering
- Convert index.html, login.html, register.html, dashboard.html, admin.html, admin_profile.html, admin_library.html to .templ files
- Generate Go code with templ generate for compile-time safety
- Update server routes to use templ components with proper rendering
- Refactor JavaScript in dashboard to avoid backtick parsing conflicts
- Delete old HTML template files
- Clean up project by removing unnecessary files and binaries
2026-01-23 16:33:08 -05:00