/* Exported promotion-detail composition, backed by persisted promotion snapshots. */
(function(){
const {useState,useEffect,useRef}=React;
const money=c=>c==null?'—':'$'+(c/100).toFixed(2);
const date=s=>s?String(s).slice(0,10).split('-').reverse().join('/'):'—';
const ACTION={publish:['Publish','Publish this promotion? It writes prices or rules to the register sync feed.'],pause:['Pause','Pause it? The registers stop applying it until you resume.'],resume:['Resume'],endEarly:['End early','End it now? Prices revert on the registers and it cannot be resumed.'],extend:['Extend'],cancel:['Cancel','Cancel it? It will not start.'],startNow:['Start now','Start today instead of the scheduled date?'],rerun:['Run it again'],edit:['Edit'],discard:['Discard','Discard this draft?']};
const API_ACTION={endEarly:'end',startNow:'start-now'};
const CHANNELS={pos:'Register & receipt',esl:'Electronic shelf labels',ticket:'Printed tickets',cfd:'Customer display',online:'Online & click-collect',cat:'Catalogue export',prompt:'Staff prompt at the till'};
const Fact=({label,children})=>
{label}{children}
;
const Card=({title,children})=>
{title}
{children};
function Detail(){
const {screenState={},setScreen,setScreenState,pushToast}=window.useOffice();const id=screenState.promotionId;
const [d,setD]=useState(null),[error,setError]=useState(null),[busy,setBusy]=useState(false),[loading,setLoading]=useState(true),[extendTo,setExtendTo]=useState('');
const inFlight=useRef(false),mounted=useRef(false),currentId=useRef(id);currentId.current=id;
useEffect(()=>{mounted.current=true;return()=>{mounted.current=false;};},[]);
useEffect(()=>{let alive=true;setD(null);setError(null);setLoading(true);if(!id){setError('No promotion selected.');setLoading(false);return;}
window.OfficeAPI.promotion(id).then(value=>{if(alive){if(!value)throw Error('Promotion not found.');setD(value);setExtendTo(value.endsOn);}}).catch(e=>{if(alive)setError(e.message||"Couldn't load this promotion.");}).finally(()=>{if(alive)setLoading(false);});return()=>{alive=false;};
},[id]);
const act=async key=>{
if(inFlight.current||!d?.actions?.includes(key))return;
if(key==='edit'||key==='rerun'){setScreenState(s=>({...s,promotionEditId:key==='edit'?id:null,promotionRerunOf:key==='rerun'?id:null}));setScreen('promotionNew');return;}
if(key==='extend'&&(!extendTo||extendTo<=d.endsOn)){setError('Pick a later end date first.');return;}
if(ACTION[key]?.[1]&&!window.confirm(ACTION[key][1]))return;
inFlight.current=true;setBusy(true);setError(null);const actionId=id;
try{
if(key==='discard'){await window.OfficeAPI.discardPromotion(id);if(mounted.current&¤tId.current===actionId){pushToast?.({kind:'ok',text:'Draft discarded.'});setScreen('promotions');}}
else{await window.OfficeAPI.promotionAction(id,API_ACTION[key]||key,key==='extend'?{endsOn:extendTo}:undefined);const fresh=await window.OfficeAPI.promotion(id);if(mounted.current&¤tId.current===actionId){setD(fresh);setExtendTo(fresh.endsOn);pushToast?.({kind:'ok',text:(ACTION[key]?.[0]||key)+' — done.'});}}
}catch(e){if(mounted.current&¤tId.current===actionId)setError(e.message||"That didn't work.");}
finally{inFlight.current=false;if(mounted.current)setBusy(false);}
};
const lines=d?.lines||[],holds=d?.tillHolds,channels=d?.channels||['pos'];
return
{d.where==='price'?'A promotional unit price in the register pricing profile.':'A basket rule evaluated when the qualifying quantity is bought.'}
{d.mechanicLabel}{d.scopeLabel}{lines.length}{d.where==='price'?'A price the register receives':'A rule the register runs'}{date(d.startsOn)} – {date(d.endsOn)}
{d.exclusions?.length>0&&
Selected exclusions: {d.exclusions.join(', ')}. Mandatory exclusions are also enforced at publication.
}{d.why&&
{d.why}
}
{d.where==='price'?'The promotional override expires or is removed. Registers use the shelf price in their current pricing profile; the pre-promotion snapshot is not written back.':'The basket rule stops being evaluated when its window ends or it is disabled. No unit price needs to revert.'}
{d.funded&&
{d.funded.supplier}{d.funded.ref||'—'}{money(d.funded.perCents)} per unit
Documented claims and eligible sales are shown in Supplier funding. This saved funding rate alone does not establish a claim value.
}
What the register holds
Read back from the tables the tills sync. This does not confirm delivery to an individual till.
{holds?
{(d.where==='price'?holds.profilesWithPromoPrice:holds.profilesInGroup)??'—'}{d.where==='basket'&&<>{holds.pricingGroup??'—'}{holds.rule?(holds.rule.isActive?'active':'inactive'):'not written'}{holds.rule&&<>{holds.rule.quantityA} for {money(holds.rule.bundlePriceCents)}{holds.rule.startDate||'—'} → {holds.rule.endDate||'—'}>}>}{d.publishedAt||'not yet'}
:
Register diagnostics are unavailable.
}
{d.state==='draft'?'Nothing has been written yet. Edit the draft to review its current scope and exclusions before publishing.':'These are the saved publication lines. They are historical snapshots, not the effective prices for a different date.'}
{lines.length>0?<>
{['Line','Was','Promo','Margin','Against the market','Note'].map(h=>