loco straucture

This commit is contained in:
Priec
2026-06-16 23:40:53 +02:00
parent 9ce07e8c23
commit b88c990873
43 changed files with 378 additions and 102 deletions

45
src/views/auth.rs Normal file
View File

@@ -0,0 +1,45 @@
use serde::{Deserialize, Serialize};
use crate::models::_entities::users;
#[derive(Debug, Deserialize, Serialize)]
pub struct LoginResponse {
pub token: String,
pub pid: String,
pub name: String,
pub is_verified: bool,
pub is_admin: bool,
}
impl LoginResponse {
#[must_use]
pub fn new(user: &users::Model, token: &String, is_admin: bool) -> Self {
Self {
token: token.to_string(),
pid: user.pid.to_string(),
name: user.name.clone(),
is_verified: user.email_verified_at.is_some(),
is_admin,
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct CurrentResponse {
pub pid: String,
pub name: String,
pub email: String,
pub is_admin: bool,
}
impl CurrentResponse {
#[must_use]
pub fn new(user: &users::Model, is_admin: bool) -> Self {
Self {
pid: user.pid.to_string(),
name: user.name.clone(),
email: user.email.clone(),
is_admin,
}
}
}

64
src/views/checkout.rs Normal file
View File

@@ -0,0 +1,64 @@
//! JSON shaping for order confirmation and admin order templates.
use serde_json::{json, Value};
use crate::models::_entities::{order_items, orders};
use crate::shared::money::format_price;
/// Line items of an order, shaped for templates.
pub fn items(items: &[order_items::Model]) -> Vec<Value> {
items
.iter()
.map(|item| {
json!({
"product_name": item.product_name,
"quantity": item.quantity,
"unit_price": format_price(item.unit_price_cents),
"line_total": format_price(item.unit_price_cents * i64::from(item.quantity)),
})
})
.collect()
}
/// Full order detail for the confirmation and admin show pages. `bank_iban` and
/// `bank_account_name` come from settings and are embedded for bank-transfer
/// payment instructions.
pub fn detail(order: &orders::Model, bank_iban: &str, bank_account_name: &str) -> Value {
json!({
"id": order.id,
"order_number": order.order_number,
"email": order.email,
"customer_name": order.customer_name,
"status": order.status,
"subtotal": format_price(order.total_cents - order.shipping_cents),
"shipping": format_price(order.shipping_cents),
"total": format_price(order.total_cents),
"currency": order.currency,
"address": order.address,
"city": order.city,
"zip": order.zip,
"country": order.country,
"note": order.note,
"payment_method": order.payment_method,
"carrier_name": order.carrier_name,
"pickup_point_name": order.pickup_point_name,
// Numeric, sequential order id doubles as the bank variable symbol.
"variable_symbol": order.id,
"bank_iban": bank_iban,
"bank_account_name": bank_account_name,
"created_at": order.created_at.to_rfc3339(),
})
}
/// Compact row for the admin orders list.
pub fn summary(order: &orders::Model) -> Value {
json!({
"id": order.id,
"order_number": order.order_number,
"email": order.email,
"status": order.status,
"total": format_price(order.total_cents),
"currency": order.currency,
"created_at": order.created_at.to_rfc3339(),
})
}

5
src/views/mod.rs Normal file
View File

@@ -0,0 +1,5 @@
//! JSON view-shaping structs for API responses and templates.
pub mod auth;
pub mod checkout;
pub mod shop;

56
src/views/shop.rs Normal file
View File

@@ -0,0 +1,56 @@
//! JSON shaping for storefront and catalog-admin templates.
use serde_json::{json, Value};
use crate::models::_entities::{categories, products};
use crate::shared::money::format_price;
/// Card/list shape for a product: model fields plus a formatted price, its
/// optional primary image filename and category name.
pub fn product_card(
product: &products::Model,
image: Option<String>,
category_name: Option<String>,
) -> Value {
json!({
"id": product.id,
"name": product.name,
"slug": product.slug,
"description": product.description,
"price": format_price(product.price_cents),
"currency": product.currency,
"sku": product.sku,
"stock": product.stock,
"published": product.published,
"image": image,
"category_name": category_name,
})
}
/// Shape used to pre-fill the admin product form (exposes `category_id` rather
/// than a resolved name, and the current primary image).
pub fn product_form(product: &products::Model, image: Option<String>) -> Value {
json!({
"id": product.id,
"name": product.name,
"slug": product.slug,
"description": product.description,
"price": format_price(product.price_cents),
"currency": product.currency,
"sku": product.sku,
"stock": product.stock,
"published": product.published,
"category_id": product.category_id,
"image": image,
})
}
/// Depth-ordered `{ name, slug, depth }` rows for the storefront sidebar,
/// rendered as an indented flat list.
pub fn sidebar_rows(tree: &[(categories::Model, usize)]) -> Vec<Value> {
tree.iter()
.map(|(category, depth)| {
json!({ "name": category.name, "slug": category.slug, "depth": depth })
})
.collect()
}