sidebar in the admin

This commit is contained in:
Priec
2026-06-22 12:49:08 +02:00
parent 09634e1cd8
commit 77d5c0fc25
9 changed files with 228 additions and 11 deletions

View File

@@ -21,13 +21,14 @@ use crate::{
controllers::i18n::current_lang,
models::{
account_discount_profiles, account_product_prices, account_product_resolutions,
discount_profiles, products, _entities::users,
categories, discount_profiles, products, _entities::users,
},
shared::{
guard,
money::{format_bp, format_price, parse_price_to_cents},
pricing,
},
views::shop as view,
};
const COMPANY: &str = "company";
@@ -131,6 +132,12 @@ async fn show(
})
.collect();
let all_categories = categories::Entity::find()
.order_by_asc(categories::Column::Position)
.order_by_asc(categories::Column::Name)
.all(&ctx.db)
.await?;
let list = products::Entity::find()
.order_by_asc(products::Column::Name)
.all(&ctx.db)
@@ -143,10 +150,22 @@ async fn show(
let business = pricing::audience_price_many(&ctx, &list, BUSINESS_AUDIENCE).await?;
let details = pricing::detail_many(&ctx, &list, Some(&company)).await?;
// Category sidebar tree (counts over the full, unfiltered list) plus the
// active `?category=` filter applied to the rows.
let category_ids: Vec<Option<i32>> = list.iter().map(|p| p.category_id).collect();
let category_groups = view::admin_category_groups(&all_categories, &category_ids);
let selected_category = params
.get("category")
.map(String::as_str)
.unwrap_or("all")
.to_string();
let filter = view::category_filter_ids(&all_categories, &selected_category);
let rows: Vec<serde_json::Value> = list
.iter()
.zip(business.iter())
.zip(details.iter())
.filter(|((product, _), _)| view::category_filter_keep(&filter, product.category_id))
.map(|((product, b), d)| {
json!({
"product_id": product.id,
@@ -170,6 +189,10 @@ async fn show(
"customer": { "id": company.id, "name": company.name, "email": company.email },
"profiles": profiles_json,
"products": rows,
"category_groups": category_groups,
"selected_category": selected_category,
"total_count": list.len(),
"uncategorized_count": category_ids.iter().filter(|c| c.is_none()).count(),
"error": params.get("error"),
"lang": current_lang(&jar),
}),

View File

@@ -126,6 +126,16 @@ async fn index(
) -> Result<Response> {
guard::current_admin(auth, &ctx).await?;
let audience = read_audience(&params);
let all_categories = categories::Entity::find()
.order_by_asc(categories::Column::Position)
.order_by_asc(categories::Column::Name)
.all(&ctx.db)
.await?;
let category_name: HashMap<i32, String> = all_categories
.iter()
.map(|c| (c.id, c.name.clone()))
.collect();
let list = products::Entity::find()
.order_by_desc(products::Column::CreatedAt)
.all(&ctx.db)
@@ -133,16 +143,27 @@ async fn index(
// Effective price each product carries for the active audience, after the
// global per-product discount and any profiles assigned to that audience.
let effective = pricing::audience_price_many(&ctx, &list, audience).await?;
// Category sidebar tree (counts over the full, unfiltered list) plus the
// active `?category=` filter applied to the rows.
let category_ids: Vec<Option<i32>> = list.iter().map(|p| p.category_id).collect();
let category_groups = view::admin_category_groups(&all_categories, &category_ids);
let selected_category = params
.get("category")
.map(String::as_str)
.unwrap_or("all")
.to_string();
let filter = view::category_filter_ids(&all_categories, &selected_category);
let mut rows = Vec::new();
for (product, priced) in list.iter().zip(effective.iter()) {
if !view::category_filter_keep(&filter, product.category_id) {
continue;
}
let image = product_images::first_for(&ctx, product.id).await?;
let category_name = match product.category_id {
Some(id) => categories::Entity::find_by_id(id)
.one(&ctx.db)
.await?
.map(|c| c.name),
None => None,
};
let category_name = product
.category_id
.and_then(|id| category_name.get(&id).cloned());
rows.push(product_row(product, priced, image, category_name, audience));
}
@@ -153,6 +174,10 @@ async fn index(
"products": rows,
"profiles": load_audience_profiles(&ctx, audience).await?,
"audience": audience,
"category_groups": category_groups,
"selected_category": selected_category,
"total_count": list.len(),
"uncategorized_count": category_ids.iter().filter(|c| c.is_none()).count(),
"lang": current_lang(&jar),
}),
)