user-app: redesigned home screen and product detail
Design language introduced here and reused across both screens:
- LESS colour tokens (@ink/@inkSoft/@inkMuted/@inkFaint, @wine/@wineSoft,
@canvas/@canvasSoft, @hairline/@hairlineSoft) added to
themeConfig/colors.json and injected globally via vite's modifyVars, so
scoped <style lang="less"> blocks resolve them with no import
- BEM-ish scoped class names, hairline-bordered cards at 14-18px radii,
ink surfaces with a wine accent, dashed-border empty states
- components/home/: SectionHead, ShowcaseCard, ShowcaseSlider, CategoryRail,
RateStrip, AccountStrip
Data honesty is deliberate throughout: no rial price is printed for a piece,
because a finished item's price is the live gold rate x weight plus wage,
computed at order time and never stored on the product. Only genuinely
present fields are shown (weight, making-charge percent, stock, category,
brand). Categories and the hero are derived from the real catalogue, so an
empty catalogue renders an empty state rather than placeholder tiles.
Also fixes a real bug in the product detail view: it ran, at module scope,
history.pushState + window.onpopstate = () => history.go(1). Because the
drawer mounts its slot eagerly, that fired for every product card on the
home screen and permanently hijacked the back button for the session.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a12fb0450e
commit
f2d83c53df
@@ -36,7 +36,13 @@ export function useProduct(productItem: ProductSummary, initialVariant?: Product
|
||||
const min_gram = computed(() => selectedVariant.value ? parseFloat(selectedVariant.value.rashWeightGrams) : 0)
|
||||
const wage = computed(() => (selectedVariant.value ? parseFloat(selectedVariant.value.defaultWagePercent) : null))
|
||||
const hasDiscountWage = ref<number | null>(null) // no promotions backend yet — see file header
|
||||
const is_exist = ref(true) // no stock field on ProductVariant yet
|
||||
// REAL stock: ProductVariant.qty / isPreOrder exist and are returned by
|
||||
// GET /catalog/products. A variant is orderable when it has stock, or when
|
||||
// it is flagged pre-order — the same rule the admin cart uses.
|
||||
const qty = computed(() => selectedVariant.value?.qty ?? 0)
|
||||
const isPreOrder = computed(() => selectedVariant.value?.isPreOrder ?? false)
|
||||
const is_exist = computed(() => qty.value > 0 || isPreOrder.value)
|
||||
const productCode = computed(() => product.value.productCode ?? null)
|
||||
const has_warranty = ref(false) // no warranty field on ProductVariant yet
|
||||
|
||||
return {
|
||||
@@ -44,11 +50,14 @@ export function useProduct(productItem: ProductSummary, initialVariant?: Product
|
||||
image,
|
||||
id,
|
||||
title,
|
||||
productCode,
|
||||
variants,
|
||||
selectedVariant,
|
||||
min_gram,
|
||||
wage,
|
||||
hasDiscountWage,
|
||||
qty,
|
||||
isPreOrder,
|
||||
is_exist,
|
||||
has_warranty,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user