/* Shared navigation for the live, advisory competitor-pricing workspace. */ function CompetitorPricingNav() { const { screen, screenState = {}, setScreen } = window.useOffice(); const active = screen === "priceDetail" ? screenState.priceFrom || "pricing" : screen; return ; } function CompetitorPricingHeader({copyRows} = {}) { const { stores = [], activeStoreId } = window.useOffice(); const store = stores.find(s => s.id === activeStoreId); const [capture, setCapture] = React.useState(false); const [copying, setCopying] = React.useState(false); const [message, setMessage] = React.useState(null); const [copyText, setCopyText] = React.useState(null); const refresh = () => window.dispatchEvent(new Event("office-pricing-refresh")); const copy = async () => { setCopying(true); setMessage(null); try { const data = copyRows?.length ? {rows:copyRows,generatedAt:new Date().toISOString()} : await window.OfficeAPI.pricingQueue(); const clean = v => String(v == null ? "" : v).replace(/[\t\r\n]/g," "); const text = [["Advisory recommendations", "Generated", data.generatedAt], ["Product","SKU","Current ($)","Recommended ($)","Reason"], ...data.rows.map(r => [r.name,r.sku,r.currentCents == null ? "" : (r.currentCents/100).toFixed(2),r.recommendedCents == null ? "" : (r.recommendedCents/100).toFixed(2),r.reasonDetail])].map(row => row.map(clean).join("\t")).join("\n"); if (navigator.clipboard && navigator.clipboard.writeText) { await navigator.clipboard.writeText(text); setMessage("Copied " + data.rows.length + " advisory row" + (data.rows.length===1 ? "" : "s") + ". Shelf prices are unchanged."); } else { setCopyText(text); } } catch (e) { setMessage(e.message || "Couldn't copy the pricing list."); } finally { setCopying(false); } }; return <>
Pricing{store ? " · " + store.name : " · current organisation"}

Competitor pricing

Observed prices in, recommendations out. Each store runs its own method, and every number carries the working behind it.

{message &&
{message}
} {(capture || copyText) &&

{capture ? "Capture an observed competitor price" : "Copy advisory recommendations"}

{capture ? <>

Enter a price you have checked. The existing automated feed runs separately.

{setCapture(false);refresh();setMessage("Competitor price saved. Recommendations refreshed.");}} onCancel={() => setCapture(false)} /> :