use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; use uuid::Uuid; #[derive(Debug, Clone, Serialize, Deserialize, FromRow)] pub struct Bookmark { pub id: Uuid, pub user_id: Uuid, pub manga_id: Uuid, pub chapter_id: Option, pub page: Option, pub created_at: DateTime, } /// `Bookmark` enriched with the parent manga's title + cover and the /// chapter's reader-facing number, so the /bookmarks page can render a /// proper card (title, cover, link target) without N+1 round-trips. /// Populated by JOINs in `repo::bookmark::list_for_user`: /// - `manga_title` / `manga_cover_image_path` come from `mangas` via an /// INNER JOIN (safe: `bookmarks.manga_id` is `ON DELETE CASCADE`, so a /// bookmark cannot outlive its manga). /// - `chapter_number` comes from `chapters` via a LEFT JOIN; `null` for /// manga-level bookmarks or for chapter bookmarks whose chapter has /// since been deleted (`bookmarks.chapter_id` is `ON DELETE SET NULL`). #[derive(Debug, Clone, Serialize, FromRow)] pub struct BookmarkSummary { pub id: Uuid, pub user_id: Uuid, pub manga_id: Uuid, pub manga_title: String, pub manga_cover_image_path: Option, pub chapter_id: Option, pub chapter_number: Option, pub page: Option, pub created_at: DateTime, }