(function () { /* Comparable KVI baskets and saved advisory strategy. All values come from /pricing/market. */ const {useState: pmState, useEffect: pmEffect} = React; const pmMoney = c => c == null ? "—" : "$" + (c / 100).toLocaleString("en-AU",{minimumFractionDigits:2,maximumFractionDigits:2}); const pmPct = p => p == null ? "—" : (p > 0 ? "+" : "") + p.toFixed(1) + "%"; function PricingMarket() { const {setScreen, setScreenState} = window.useOffice(); const [data,setData] = pmState(null); const [selected,setSelected] = pmState(null); const [loading,setLoading] = pmState(true); const [saving,setSaving] = pmState(false); const [error,setError] = pmState(null); const [notice,setNotice] = pmState(null); const [reload,setReload] = pmState(0); const [showAdd,setShowAdd] = pmState(false); pmEffect(()=>{const refresh=()=>setReload(k=>k+1);window.addEventListener("office-pricing-refresh",refresh);return()=>window.removeEventListener("office-pricing-refresh",refresh);},[]); const [showAll,setShowAll] = pmState(false); const [search,setSearch] = pmState(""); const [page,setPage] = pmState(0); pmEffect(()=>setPage(0),[search]); pmEffect(() => { let alive = true; setLoading(true); setError(null); window.OfficeAPI.pricingMarket(selected ? {strategy:selected} : undefined) .then(d => { if(alive) setData(d); }) .catch(e => { if(alive) setError(e.message || "Couldn't load the market basket."); }) .finally(() => { if(alive) setLoading(false); }); return () => {alive=false;}; },[selected,reload]); const preview = !!data && data.strategy.id !== data.savedStrategyId; const ready = !!data && !loading && (!selected || data.strategy.id === selected); const choose = id => {setSelected(id); setNotice(null);}; const save = async () => { if(!ready || !preview || saving) return; setSaving(true); setError(null); setNotice(null); try { await window.OfficeAPI.savePricingStrategy({id:data.strategy.id}); setNotice("Saved. This stance now guides advisory recommendations for this scope. Shelf prices are unchanged."); setSelected(null); setReload(k=>k+1); } catch(e) {setError(e.message || "Couldn't save this stance.");} finally {setSaving(false);} }; const open = r => { setScreenState(st=>({...st,priceProductId:r.productId,priceFrom:"pricePosition",priceMethod:undefined,priceStrategy:preview ? data.strategy.id : undefined})); setScreen("priceDetail"); }; const s=data && data.summary, c=data && data.coverage; const rows=data ? data.rows.filter(r=>!search.trim() || [r.name,r.sku,r.brand].some(v=>(v||"").toLowerCase().includes(search.trim().toLowerCase()))) : []; const Kpi=window.KpiCard; return
{c.missingObservations || 0} without comparable observations · {c.missingOwnPrice || 0} without a shelf price · {c.missingCost || 0} without a usable cost · {c.excludedPackComparisons || 0} pack comparisons excluded · {c.excludedBasisComparisons || 0} incompatible price bases excluded.
{data.scopeNote}
| Product | You | Cheapest observed | Gap | Recommended | Gap then |
|---|---|---|---|---|---|
| {r.sku || "No SKU"}{r.category ? " · " + r.category : ""} | {pmMoney(r.ownCents)} | {pmMoney(r.cheapestCents)}{typeof r.cheapestRetailer === "string" ? r.cheapestRetailer : r.cheapestRetailer.name} | 0 ? "off-pricing-up" : "off-pricing-down")}>{pmPct(r.gapPct)} | {loading ? "…" : pmMoney(r.recommendedCents)}{r.recommendedCents == null && Needs cost / evidence} | {loading ? "…" : pmPct(r.gapThenPct)} |