"""Layout registration + header data builders.""" from __future__ import annotations from shared.sx.helpers import sx_call from .utils import _set_prices, _price_str # --------------------------------------------------------------------------- # Header data extraction — pure data, no component references # --------------------------------------------------------------------------- def _market_header_data(ctx: dict) -> dict: """Extract market header data for .sx composition.""" from quart import url_for from shared.utils import route_prefix prefix = route_prefix() hx_select = ctx.get("hx_select_search", "#main-panel") select_colours = ctx.get("select_colours", "") rights = ctx.get("rights", {}) qs = ctx.get("qs", "") categories = ctx.get("categories", {}) all_href = prefix + url_for("market.browse.browse_all") + qs cat_data = [] for cat, data in categories.items(): cat_href = prefix + url_for("market.browse.browse_top", top_slug=data["slug"]) + qs cat_data.append({ "href": cat_href, "active": cat == ctx.get("category_label", ""), "label": cat, }) admin_href = "" if rights and rights.get("admin"): admin_href = prefix + url_for("defpage_market_admin") return { "market-title": ctx.get("market_title", ""), "top-slug": ctx.get("top_slug", ""), "sub-slug": ctx.get("sub_slug", ""), "link-href": url_for("defpage_market_home"), "categories": cat_data, "hx-select": hx_select, "select-colours": select_colours, "all-href": all_href, "all-active": ctx.get("category_label", "") == "All Products", "admin-href": admin_href, } def _market_header_sx(ctx: dict, *, oob: bool = False) -> str: """Build market header as sx — delegates to .sx defcomp.""" data = _market_header_data(ctx) return sx_call("market-header-from-data", oob=oob, **data) def _product_header_data(ctx: dict, d: dict) -> dict: """Extract product header data for .sx composition.""" from quart import url_for from shared.browser.app.csrf import generate_csrf_token slug = d.get("slug", "") hx_select = ctx.get("hx_select_search", "#main-panel") cart = ctx.get("cart", []) rights = ctx.get("rights", {}) # Price data pr = _set_prices(d) sp_str = _price_str(pr["sp_val"], pr["sp_raw"], pr["sp_cur"]) if pr["sp_val"] else "" rp_str = _price_str(pr["rp_val"], pr["rp_raw"], pr["rp_cur"]) if pr["rp_val"] else "" # RRP rrp_str = "" rrp_raw = d.get("rrp_raw") rrp_val = d.get("rrp") case_size = d.get("case_size_count") or 1 if rrp_raw and rrp_val: rrp_str = f"{rrp_raw[0]}{rrp_val * case_size:.2f}" # Cart state csrf = generate_csrf_token() cart_action = url_for("market.browse.product.cart", product_slug=slug) quantity = sum(ci.quantity for ci in cart if ci.product.slug == slug) if cart else 0 cart_url_fn = ctx.get("cart_url") cart_href = cart_url_fn("/") if callable(cart_url_fn) else "/" admin_href = "" if rights and rights.get("admin"): admin_href = url_for("market.browse.product.admin", product_slug=slug) return { "title": d.get("title", ""), "link-href": url_for("market.browse.product.product_detail", product_slug=slug), "hx-select": hx_select, "price-data": { "cart-id": f"cart-{slug}", "cart-action": cart_action, "csrf": csrf, "quantity": quantity, "cart-href": cart_href, "sp-val": pr["sp_val"] or "", "sp-str": sp_str, "rp-val": pr["rp_val"] or "", "rp-str": rp_str, "rrp-str": rrp_str, }, "admin-href": admin_href, } def _product_header_sx(ctx: dict, d: dict, *, oob: bool = False) -> str: """Build product header as sx — delegates to .sx defcomp.""" data = _product_header_data(ctx, d) return sx_call("market-product-header-from-data", oob=oob, **data) def _product_admin_header_sx(ctx: dict, d: dict, *, oob: bool = False) -> str: """Build product admin header as sx — delegates to .sx defcomp.""" from quart import url_for slug = d.get("slug", "") link_href = url_for("market.browse.product.admin", product_slug=slug) return sx_call("market-product-admin-header-from-data", link_href=link_href, oob=oob) # --------------------------------------------------------------------------- # Mobile nav panel data extraction # --------------------------------------------------------------------------- def _mobile_nav_data(ctx: dict) -> dict: """Extract mobile nav panel data for .sx composition.""" from quart import url_for from shared.utils import route_prefix prefix = route_prefix() categories = ctx.get("categories", {}) qs = ctx.get("qs", "") top_slug = ctx.get("top_slug", "") sub_slug = ctx.get("sub_slug", "") hx_select = ctx.get("hx_select_search", "#main-panel") select_colours = ctx.get("select_colours", "") all_href = prefix + url_for("market.browse.browse_all") + qs cat_data = [] for cat, data in categories.items(): cat_slug = data.get("slug", "") cat_active = top_slug == cat_slug.lower() if top_slug else False cat_href = prefix + url_for("market.browse.browse_top", top_slug=cat_slug) + qs subs = data.get("subs", []) sub_data = [] if subs: for sub in subs: sub_href = prefix + url_for("market.browse.browse_sub", top_slug=cat_slug, sub_slug=sub["slug"]) + qs sub_active = cat_active and sub_slug == sub.get("slug") sub_label = sub.get("html_label") or sub.get("name", "") sub_data.append({ "href": sub_href, "active": sub_active, "label": sub_label, "count": sub.get("count", 0), }) cat_data.append({ "name": cat, "href": cat_href, "active": cat_active, "count": data.get("count", 0), "subs": sub_data if sub_data else None, }) return { "categories": cat_data, "all-href": all_href, "all-active": ctx.get("category_label", "") == "All Products", "hx-select": hx_select, "select-colours": select_colours, } def _mobile_nav_panel_sx(ctx: dict) -> str: """Build mobile nav panel as sx — delegates to .sx defcomp.""" data = _mobile_nav_data(ctx) return sx_call("market-mobile-nav-from-data", **data) # --------------------------------------------------------------------------- # Layout registration — all layouts delegate to .sx defcomps # --------------------------------------------------------------------------- def _register_market_layouts() -> None: from shared.sx.layouts import register_sx_layout register_sx_layout("market", "market-browse-layout-full", "market-browse-layout-oob", "market-browse-layout-mobile") register_sx_layout("market-admin", "market-admin-layout-full", "market-admin-layout-oob")