package handlers import "bookhoard/internal/database" // MediaDetail embeds database.MediaItems for complete book metadata // No field duplication - template gets direct access to all database fields type MediaDetail struct { database.MediaItems // Embedded - ALL book fields available // Absolute on-disk location (library folder + relative path), resolved by // the page handler so the UI can show where the file lives. FileLocation string `json:"file_location"` // User-specific data Rating *database.MediaRatings `json:"rating,omitempty"` Review *database.MediaReviews `json:"review,omitempty"` // raw markdown Collections []database.Collections `json:"collections"` ReadingProgress *database.ReadingProgress `json:"reading_progress,omitempty"` // The viewer's own reading-history card for this book (nil when the // user has no sessions here); rendered as the "Your Reading Stats" // section of the book page. BookStats *BookStatsData `json:"book_stats,omitempty"` // Conflict data (if exists) ActiveConflict *ConflictDetailResponse `json:"active_conflict,omitempty"` // Computed counts NotesCount int `json:"notes_count"` HighlightsCount int `json:"highlights_count"` // Deleted-annotation history (tombstoned rows, newest first) — the book // page's "recently deleted" list with restore/permanent-delete actions. DeletedAnnotations []DeletedAnnotationResponse `json:"deleted_annotations"` } // BookStatsData is the per-book reading-stats card payload. type BookStatsData struct { TotalMinutes int TotalPages int SessionCount int MaxProgress float64 // 0..1 Finished bool LastSession string FirstSession string }