personal discounts to businesses done

This commit is contained in:
Priec
2026-06-21 23:21:24 +02:00
parent ed566b5347
commit c713627a2c
35 changed files with 912 additions and 39 deletions

View File

@@ -8,17 +8,23 @@ use serde_json::json;
use crate::{
controllers::i18n::current_lang,
shared::guard,
models::{categories, product_images, products},
shared::{guard, pricing},
models::{categories, product_images, products, users},
views::shop as view,
};
/// Shape a list of products into card rows, loading each one's primary image.
async fn product_rows(ctx: &AppContext, list: Vec<products::Model>) -> Result<Vec<serde_json::Value>> {
/// Shape a list of products into card rows for `user` (None = public), pricing
/// each via [`pricing::price_many`] and loading its primary image.
async fn product_rows(
ctx: &AppContext,
user: Option<&users::Model>,
list: Vec<products::Model>,
) -> Result<Vec<serde_json::Value>> {
let priced = pricing::price_many(ctx, &list, user).await?;
let mut rows = Vec::with_capacity(list.len());
for product in list {
for (product, priced) in list.iter().zip(priced.iter()) {
let image = product_images::first_for(ctx, product.id).await?;
rows.push(view::product_card(&product, image, None));
rows.push(view::product_card(product, priced, image, None));
}
Ok(rows)
}
@@ -27,6 +33,7 @@ async fn product_rows(ctx: &AppContext, list: Vec<products::Model>) -> Result<Ve
/// by the home-page landing grid.
pub(crate) async fn featured_products(
ctx: &AppContext,
user: Option<&users::Model>,
limit: u64,
) -> Result<Vec<serde_json::Value>> {
let list = products::Entity::find()
@@ -35,7 +42,7 @@ pub(crate) async fn featured_products(
.limit(limit)
.all(&ctx.db)
.await?;
product_rows(ctx, list).await
product_rows(ctx, user, list).await
}
/// The site-wide category sidebar, loaded lazily via htmx by the base layout so
@@ -69,12 +76,13 @@ async fn index(
.all(&ctx.db)
.await?;
let c = guard::chrome(&ctx, &jar).await;
let user = guard::current_user(&ctx, &jar).await;
let c = guard::chrome_from(&ctx, user.as_ref());
format::view(
&v,
"shop/index.html",
json!({
"products": product_rows(&ctx, list).await?,
"products": product_rows(&ctx, user.as_ref(), list).await?,
"logged_in_admin": c.logged_in_admin,
"logged_in_customer": c.logged_in_customer,
"customer_name": c.customer_name,
@@ -112,12 +120,14 @@ async fn show(
None => None,
};
let c = guard::chrome(&ctx, &jar).await;
let user = guard::current_user(&ctx, &jar).await;
let priced = pricing::price_for(&ctx, &product, user.as_ref()).await?;
let c = guard::chrome_from(&ctx, user.as_ref());
format::view(
&v,
"shop/show.html",
json!({
"product": view::product_card(&product, None, category.as_ref().map(|c| c.name.clone())),
"product": view::product_card(&product, &priced, None, category.as_ref().map(|c| c.name.clone())),
"images": images.iter().map(|i| i.image_id.clone()).collect::<Vec<_>>(),
"category": category,
"logged_in_admin": c.logged_in_admin,
@@ -159,7 +169,8 @@ async fn category(
.all(&ctx.db)
.await?;
let c = guard::chrome(&ctx, &jar).await;
let user = guard::current_user(&ctx, &jar).await;
let c = guard::chrome_from(&ctx, user.as_ref());
format::view(
&v,
"shop/category.html",
@@ -167,7 +178,7 @@ async fn category(
"category": category,
"breadcrumbs": breadcrumbs,
"children": children,
"products": product_rows(&ctx, list).await?,
"products": product_rows(&ctx, user.as_ref(), list).await?,
"logged_in_admin": c.logged_in_admin,
"logged_in_customer": c.logged_in_customer,
"customer_name": c.customer_name,