page is better in shop now
This commit is contained in:
@@ -22,8 +22,21 @@ use crate::{
|
||||
views::shop as view,
|
||||
};
|
||||
|
||||
/// Results per page in the storefront listing/search.
|
||||
/// Default results per page in the storefront listing/search.
|
||||
const PER_PAGE: usize = 24;
|
||||
/// Allowed per-page choices offered in the toolbar; any other value falls back
|
||||
/// to [`PER_PAGE`].
|
||||
const PER_PAGE_OPTIONS: [usize; 3] = [24, 48, 96];
|
||||
|
||||
/// Resolve the requested per-page count to one of [`PER_PAGE_OPTIONS`],
|
||||
/// defaulting to [`PER_PAGE`].
|
||||
fn resolve_per_page(params: &SearchParams) -> usize {
|
||||
params
|
||||
.per_page
|
||||
.map(|p| p as usize)
|
||||
.filter(|p| PER_PAGE_OPTIONS.contains(p))
|
||||
.unwrap_or(PER_PAGE)
|
||||
}
|
||||
/// Hard cap on candidates a single text search considers before faceting; well
|
||||
/// above any realistic page of results for this catalog.
|
||||
const SEARCH_CAP: u64 = 1000;
|
||||
@@ -40,6 +53,7 @@ struct SearchParams {
|
||||
in_stock: Option<String>,
|
||||
sort: Option<String>,
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
}
|
||||
|
||||
/// A candidate product with everything the listing needs to filter, sort and
|
||||
@@ -81,6 +95,9 @@ fn query_base(params: &SearchParams) -> String {
|
||||
if let Some(s) = params.sort.as_deref().filter(|s| !s.is_empty()) {
|
||||
ser.append_pair("sort", s);
|
||||
}
|
||||
if let Some(p) = params.per_page.filter(|p| *p as usize != PER_PAGE) {
|
||||
ser.append_pair("per_page", &p.to_string());
|
||||
}
|
||||
ser.finish()
|
||||
}
|
||||
|
||||
@@ -198,14 +215,15 @@ async fn run_search(
|
||||
}
|
||||
|
||||
// 7. Paginate.
|
||||
let per_page = resolve_per_page(params);
|
||||
let total = items.len();
|
||||
let pages = total.div_ceil(PER_PAGE).max(1);
|
||||
let pages = total.div_ceil(per_page).max(1);
|
||||
let page = params.page.unwrap_or(1).clamp(1, pages as u32);
|
||||
let start = (page as usize - 1) * PER_PAGE;
|
||||
let start = (page as usize - 1) * per_page;
|
||||
|
||||
// 8. Render only the current page's cards (images fetched per row).
|
||||
let mut rows = Vec::new();
|
||||
for item in items.iter().skip(start).take(PER_PAGE) {
|
||||
for item in items.iter().skip(start).take(per_page) {
|
||||
let image = product_images::first_for(ctx, item.product.id).await?;
|
||||
let cat_name = item.product.category_id.and_then(|id| category_name.get(&id).cloned());
|
||||
rows.push(view::product_card(
|
||||
@@ -229,6 +247,8 @@ async fn run_search(
|
||||
"selected_category_id": selected_category.parse::<i32>().unwrap_or(-1),
|
||||
"uncategorized_count": uncategorized_count,
|
||||
"sort": sort,
|
||||
"per_page": per_page,
|
||||
"per_page_options": PER_PAGE_OPTIONS,
|
||||
"in_stock": in_stock_only,
|
||||
"min_price": params.min_price.clone().unwrap_or_default(),
|
||||
"max_price": params.max_price.clone().unwrap_or_default(),
|
||||
|
||||
Reference in New Issue
Block a user