use crate::http::utils::stringify; use serde::{Deserialize, Serialize}; pub const PAGE_DEFAULT: i64 = 1; pub const PAGE_MIN: i64 = 1; pub const PAGE_MAX: i64 = 100; pub const PAGE_SIZE_DEFAULT: i64 = 10; pub const PAGE_SIZE_MIN: i64 = 5; pub const PAGE_SIZE_MAX: i64 = 100; pub const LIMITED_PAGE_DEFAULT: i64 = 1; pub const LIMITED_PAGE_MIN: i64 = 1; pub const LIMITED_PAGE_MAX: i64 = 5; pub const LIMITED_PAGE_SIZE_DEFAULT: i64 = 5; pub const LIMITED_PAGE_SIZE_MIN: i64 = 5; pub const LIMITED_PAGE_SIZE_MAX: i64 = 5; #[derive(Deserialize, Default)] pub struct Pagination { pub page: Option, pub page_size: Option, } #[derive(Serialize, Debug)] pub struct PaginationView { // Legacy fields for backwards compatibility pub previous: Option, pub previous_url: Option, pub next: Option, pub next_url: Option, // New fields for template compatibility pub current_page: i64, pub has_prev: bool, pub prev_page: i64, pub has_next: bool, pub next_page: i64, pub page_range: Vec, } impl Pagination { pub fn admin_clamped(&self) -> (i64, i64) { let page = self.page.unwrap_or(1).clamp(1, 25000); let page_size = self.page_size.unwrap_or(1).clamp(20, 100); (page, page_size) } pub fn clamped(&self) -> (i64, i64) { let page = self.page.unwrap_or(PAGE_DEFAULT).clamp(PAGE_MIN, PAGE_MAX); let page_size = self .page_size .unwrap_or(PAGE_SIZE_DEFAULT) .clamp(PAGE_SIZE_MIN, PAGE_SIZE_MAX); (page, page_size) } } impl PaginationView { pub fn new(page_size: i64, total: i64, page: i64, params: Vec<(&str, &str)>) -> Self { let total_pages = if total == 0 { 1 } else { (total + page_size - 1) / page_size }; // Legacy fields for backwards compatibility let (previous, previous_url) = { if page > 1 { let page_value = (page - 1).to_string(); let mut page_args: Vec<(&str, &str)> = vec![("page", &page_value)]; page_args.extend(params.clone()); (Some(page - 1), Some(stringify(page_args))) } else { (None, None) } }; let (next, next_url) = { if page < total_pages { let page_value = (page + 1).to_string(); let mut page_args: Vec<(&str, &str)> = vec![("page", &page_value)]; page_args.extend(params.clone()); (Some(page + 1), Some(stringify(page_args))) } else { (None, None) } }; // New fields for template compatibility let current_page = page; let has_prev = page > 1; let prev_page = if has_prev { page - 1 } else { 1 }; let has_next = page < total_pages; let next_page = if has_next { page + 1 } else { page }; // Create page range (show 5 pages around current page) let mut page_range = Vec::new(); let range_start = if current_page <= 3 { 1 } else { current_page - 2 }; let range_end = std::cmp::min(total_pages, range_start + 4); for page_num in range_start..=range_end { page_range.push(page_num); } Self { previous, previous_url, next, next_url, current_page, has_prev, prev_page, has_next, next_page, page_range, } } }