1import{j as e,c1 as gs,c2 as ze,c3 as Ve,ab as q,c4 as qe,B as D,L as $e,aC as Ge,r as i,T as _e,aI as I,c8 as Ts,c9 as Ps,ca as Bs,cb as Is,cc as Us,I as Ce,m as Ms,X as Os,x as js,bj as oe,as as ne,a_ as Fs,l as _s,ah as He,o as T,an as zs,c0 as Vs,S as is,ao as qs,ap as Hs,aq as Ks,ar as Gs,b as Ws,$ as M,a0 as O,a1 as F,a2 as z,a3 as c,W as Xs,aV as Qs,bt as fs,d as ee,e as pe,f as ge,g as Ys,h as se,au as bs,n as Zs,bk as Js,bl as ea,bq as ls,bo as cs,aB as sa,aA as aa}from"./index-K4f5-ZQX.js";import{I as vs}from"./info-OA1F6XvB.js";import{u as ta,r as na}from"./useSearchRunLog-DqWKAxPJ.js";import{T as We,a as Xe,b as de,c as g,d as Qe,e as j}from"./table-D0egvJgs.js";import{T as ra}from"./textarea-CK7l6Qu8.js";import{S as we}from"./separator-Db73bcCE.js";import{D as ia}from"./database-kHYVbHv2.js";import{R as Te}from"./ResponsiveContainer-H1-fTj4Q.js";import{L as os,a as Pe}from"./LineChart-SDnoqCqU.js";import{C as Be}from"./CartesianGrid-CqxLV5As.js";import{X as Ie,Y as Ue,T as Me,L as ds,B as la}from"./generateCategoricalChart-M6QrsUi4.js";import{B as ca}from"./BarChart-Dkd5x08a.js";import{M as oa}from"./minus-Dwvz1zO0.js";import"./index-91cxZt_C.js";import"./index-Dh4i1-J3.js";const da="RCM remains the source of truth for rates. Nothing on this page changes a live price - every recommendation is a suggestion built from Simba's own captured search pricing, availability and bookings.";function ua({subline:s,onRefresh:n,refreshing:r}){return e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0 flex items-center gap-3 flex-wrap",children:[e.jsx(gs,{children:e.jsxs(ze,{children:[e.jsx(Ve,{asChild:!0,children:e.jsxs(q,{variant:"secondary",className:"gap-1 cursor-help font-normal rounded-full",children:[e.jsx(vs,{className:"h-3 w-3"})," Advisory only"]})}),e.jsx(qe,{className:"max-w-sm text-xs",children:da})]})}),e.jsx("p",{className:"text-xs text-muted-foreground",children:s})]}),e.jsxs(D,{size:"sm",onClick:n,disabled:r,variant:"outline",className:"rounded-md shadow-sm",children:[r?e.jsx($e,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(Ge,{className:"h-4 w-4 mr-2"}),"Refresh recommendations"]})]})}const ma=s=>s?new Intl.DateTimeFormat("en-AU",{timeZone:"Australia/Sydney",day:"2-digit",month:"short",hour:"2-digit",minute:"2-digit"}).format(new Date(s)):"-";function xa({onRefreshed:s}){const n=ta(),[r,b]=i.useState(!1),o=n.data,m=async()=>{b(!0);try{await na(),await n.refetch(),s==null||s(),I.success("Pricing data refreshed")}catch(l){I.error(`Refresh failed: ${l.message}`)}finally{b(!1)}};return o?e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-xs",children:[e.jsxs("span",{className:o.is_stale?"text-destructive flex items-center gap-1":"text-muted-foreground",children:[o.is_stale?e.jsx(_e,{className:"h-3.5 w-3.5"}):null,"Data current to ",ma(o.processed_through)," Sydney",o.lag_minutes!==null?` (${o.lag_minutes} min behind)`:""]}),e.jsxs(D,{size:"sm",variant:"ghost",className:"h-7 px-2",onClick:m,disabled:r,children:[e.jsx(Ge,{className:`h-3.5 w-3.5 mr-1 ${r?"animate-spin":""}`}),r?"Refreshing...":"Refresh now"]})]}):null}const us=[{value:"1",label:"1 day",min:1,max:1},{value:"2",label:"2 days",min:2,max:2},{value:"3",label:"3 days",min:3,max:3},{value:"4",label:"4 days",min:4,max:4},{value:"5-7",label:"5-7 days",min:5,max:7},{value:"8-10",label:"8-10 days",min:8,max:10},{value:"11-14",label:"11-14 days",min:11,max:14},{value:"15-21",label:"15-21 days",min:15,max:21},{value:"22-30",label:"22-30 days",min:22,max:30},{value:"31+",label:"31+ days",min:31,max:3650}],ha={pay_now_before_discount:"Pay Now, before discount",pay_now_undiscounted:"Pay Now, before discount (legacy label)"},pa={none:"No discount",user_campaign:"Customer-entered code",auto_promo:"Automatic promotion",utilisation_adjustment:"Utilisation adjustment",unclassified_discount:"Discount of unknown origin",legacy_unverified:"Legacy capture, basis unverified"},ga="Rates are calculated for the exact hire length. Bands only group the screen - selecting 5-7 days still shows separate 5, 6 and 7 day recommendations.",ae=s=>s==null||s<=0?"Unknown length":`${s}-day hire`,Ae={act_now:"Act now",review:"Review manually",monitor:"Monitor",insufficient_evidence:"Insufficient evidence",expired:"Expired"},ja={act_now:"bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300",review:"bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-300",monitor:"bg-sky-100 text-sky-800 dark:bg-sky-900/30 dark:text-sky-300",insufficient_evidence:"bg-muted text-muted-foreground",expired:"bg-muted text-muted-foreground"},Ye={high:"High",medium:"Medium",low:"Low",insufficient:"Insufficient"},_a={high:"bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300",medium:"bg-sky-100 text-sky-800 dark:bg-sky-900/30 dark:text-sky-300",low:"bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-300",insufficient:"bg-muted text-muted-foreground"},Ke={applied:"Applied",dismissed:"Dismissed",review_later:"Review later"},fa="An observation is a captured Simba rate for the same airport and vehicle category under comparable weekday and booking lead-time conditions. Repeated captures of the same unchanged rate are discounted, so they do not inflate the evidence.",ba="Advisory only. Built from genuine customer searches (one search run counts once), Pay Now price before discount, Mackay excluded. Re-quotes, price rechecks during Insurance and Add-ons, and internal system checks are stored for diagnostics but never counted as extra evidence. Bookings are used only to show whether a price converted. Nothing here changes a customer price or anything in RCM.",w=s=>s==null?"-":new Intl.NumberFormat("en-AU",{style:"currency",currency:"AUD",minimumFractionDigits:2}).format(Number(s)),te=s=>s==null?"-":`${Number(s)>=0?"+":""}${Number(s).toFixed(1)}%`,Ze=s=>{if(!s)return"never";const n=Math.max(0,Math.round((Date.now()-new Date(s).getTime())/6e4));if(n<1)return"just now";if(n<60)return`${n} min ago`;const r=Math.round(n/60);return r<24?`${r} h ago`:`${Math.round(r/24)} d ago`},va=s=>(Array.isArray(s.reasoning)?s.reasoning:[]).slice(0,3),ya=s=>Array.isArray(s.calculation)?s.calculation:[],je=s=>s.status!=="insufficient_evidence"&&s.status!=="expired",y=({label:s,value:n})=>e.jsxs("div",{className:"flex items-baseline justify-between gap-4 py-1 text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:s}),e.jsx("span",{className:"font-medium tabular-nums",children:n})]}),xe=({title:s,children:n})=>e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground mb-1",children:s}),n]});function Na({row:s,open:n,onOpenChange:r,onDecide:b}){const[o,m]=i.useState(""),[l,p]=i.useState(""),[v,V]=i.useState(null);if(!s)return null;const R=async h=>{V(h);const C=h==="applied"?Number(o)||Number(s.recommended_rate):null;await b(s,h,C,l),V(null),p(""),m(""),r(!1)},H=ya(s),P=je(s);return e.jsx(Ts,{open:n,onOpenChange:r,children:e.jsxs(Ps,{className:"w-full sm:max-w-lg overflow-y-auto",children:[e.jsxs(Bs,{className:"text-left",children:[e.jsxs(Is,{className:"text-base",children:[s.pickup_location_name.replace(" Airport","")," · ",s.category_name]}),e.jsxs(Us,{children:["Pickup ",s.pickup_date," · ",s.lead_days," day",s.lead_days===1?"":"s"," away · ",ae(s.rental_days)]}),e.jsxs("div",{className:"flex flex-wrap gap-2 pt-1",children:[e.jsx(q,{className:ja[s.status],variant:"secondary",children:Ae[s.status]}),e.jsxs(q,{className:_a[s.evidence_level],variant:"secondary",children:["Evidence: ",Ye[s.evidence_level]]}),s.is_estimated&&e.jsx(q,{variant:"outline",className:"text-[11px]",children:"Estimated"})]})]}),e.jsxs("div",{className:"space-y-5 mt-5",children:[e.jsx("div",{className:"flex flex-wrap gap-1.5",children:va(s).map(h=>e.jsx(q,{variant:"outline",className:"text-[11px] font-normal whitespace-nowrap",children:h},h))}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Based on ",s.observations.toLocaleStr
1ing()," comparable rates captured across ",s.unique_pickup_dates," pickup date",s.unique_pickup_dates===1?"":"s"," (",s.effective_observations.toLocaleString()," counted after discounting repeated identical captures)."," ",s.duration_basis==="exact"?`All comparable rates are for ${ae(s.rental_days).toLowerCase()}s.`:s.duration_basis==="none"?"No comparable hire-length history is available yet.":`${s.duration_basis_label??"Estimated from nearby hire lengths"} - this result is estimated and cannot be rated High evidence or Act now.`]}),e.jsxs(xe,{title:"Current situation",children:[e.jsx(y,{label:"Original Pay Now rate",value:w(s.current_avg_rate)}),s.current_is_discounted&&e.jsxs(e.Fragment,{children:[e.jsx(y,{label:"Customer-visible rate",value:w(s.current_rate_after_discount)}),e.jsx(y,{label:"Discount",value:`${w(s.current_discount_amount==null||!s.rental_days?s.current_discount_amount:Number(s.current_discount_amount)/s.rental_days)} per day${s.current_discount_percent==null?"":` (${Number(s.current_discount_percent).toFixed(1)}%)`}${s.current_discount_amount==null?"":` - ${w(s.current_discount_amount)} over the ${ae(s.rental_days).toLowerCase()}`}`}),e.jsx(y,{label:"Discount source",value:`${pa[s.current_discount_source??""]??s.current_discount_source??"-"}${s.current_campaign_code?` · ${s.current_campaign_code}`:""}`})]}),e.jsx(y,{label:"Hire length",value:ae(s.rental_days)}),e.jsx(y,{label:"Rate basis",value:ha[s.rate_basis]??s.rate_basis}),e.jsx(y,{label:"Captures in window",value:s.current_capture_count.toLocaleString()}),e.jsx(y,{label:"Average vehicles available",value:s.avg_availability==null?"-":Number(s.avg_availability).toFixed(1)}),e.jsx(y,{label:"Pickup",value:`In ${s.lead_days} day${s.lead_days===1?"":"s"}`}),e.jsx(y,{label:"Last rate captured",value:Ze(s.last_capture_at)})]}),e.jsx(we,{}),e.jsxs(xe,{title:"Demand",children:[e.jsx(y,{label:"Searches",value:s.searches.toLocaleString()}),e.jsx(y,{label:"Normal searches",value:s.searches_normal==null?"-":Number(s.searches_normal).toFixed(1)}),e.jsx(y,{label:"Demand change",value:s.demand_change_pct==null?"-":te(s.demand_change_pct)}),e.jsx(y,{label:"Booking pressure (not conversion)",value:`${s.bookings_count} booking${s.bookings_count===1?"":"s"} for this vehicle`}),e.jsx(y,{label:"Bookings linked to a recorded search",value:s.attributed_bookings==null?"Not available":`${s.attributed_bookings} of ${s.bookings_count}${s.attribution_coverage_pct==null?"":` (${Number(s.attribution_coverage_pct).toFixed(0)}% linked)`}`}),e.jsx(y,{label:"Conversion (linked bookings only)",value:s.conversion_rate==null?"Not available - no booking could be linked to a recorded search":`${Number(s.conversion_rate).toFixed(1)}%`})]}),e.jsx(we,{}),e.jsxs(xe,{title:"Comparable pricing",children:[e.jsx(y,{label:"Comparable observations",value:s.observations.toLocaleString()}),e.jsx(y,{label:"Unique pickup dates",value:String(s.unique_pickup_dates)}),e.jsx(y,{label:"Median comparable rate",value:w(s.median_comparable_rate)}),e.jsx(y,{label:"Typical range",value:s.range_low_rate==null||s.range_high_rate==null?"-":`${w(s.range_low_rate)} - ${w(s.range_high_rate)}`})]}),e.jsx(we,{}),e.jsxs(xe,{title:"Recommendation calculation",children:[H.map((h,C)=>e.jsx(y,{label:h.label,value:h.kind==="money"?w(h.value):te(h.value)},`${h.label}-${C}`)),s.was_capped&&e.jsxs("p",{className:"text-xs text-amber-700 dark:text-amber-400 mt-2",children:["The uncapped model figure (",w(s.raw_recommended_rate)," · ",te(s.raw_delta_pct),") exceeds the safety limit, so it is shown here as a technical value only. The controlled test rate is what staff should use."]})]}),!P&&e.jsx("p",{className:"text-sm text-muted-foreground border rounded-md p-3",children:s.status==="expired"?"This pickup date has passed. No action is possible.":"Insufficient evidence - continue monitoring. There are not enough comparable observations to responsibly suggest a rate."}),P&&e.jsxs(e.Fragment,{children:[e.jsx(we,{}),e.jsxs(xe,{title:"Decision",children:[e.jsxs("p",{className:"text-sm mb-2",children:["Recommended test rate ",e.jsx("span",{className:"font-semibold",children:w(s.recommended_rate)})," ","(",te(s.delta_pct)," from ",w(s.current_avg_rate),")"]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(Ce,{inputMode:"decimal",placeholder:`Applied rate (defaults to ${w(s.recommended_rate)})`,value:o,onChange:h=>m(h.target.value)}
1),e.jsx(ra,{rows:2,placeholder:"Optional reason",value:l,onChange:h=>p(h.target.value)}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(D,{size:"sm",onClick:()=>R("applied"),disabled:v!==null,children:[v==="applied"?e.jsx($e,{className:"h-4 w-4 mr-1.5 animate-spin"}):e.jsx(Ms,{className:"h-4 w-4 mr-1.5"}),"Mark as applied"]}),e.jsxs(D,{size:"sm",variant:"outline",onClick:()=>R("dismissed"),disabled:v!==null,children:[e.jsx(Os,{className:"h-4 w-4 mr-1.5"})," Dismiss"]}),e.jsxs(D,{size:"sm",variant:"ghost",onClick:()=>R("review_later"),disabled:v!==null,children:[e.jsx(js,{className:"h-4 w-4 mr-1.5"})," Review later"]})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Recording a decision is an internal note only. It never changes a price in RCM."})]})]})]})]})]})})}const wa=[{key:"act_now",label:"Act now",icon:Fs,dot:"bg-emerald-500",active:"border-emerald-500"},{key:"review",label:"Review manually",icon:_e,dot:"bg-amber-500",active:"border-amber-500"},{key:"monitor",label:"Monitor",icon:_s,dot:"bg-sky-500",active:"border-sky-500"},{key:"insufficient_evidence",label:"No evidence",icon:He,dot:"bg-muted-foreground",active:"border-muted-foreground"}];function ka({counts:s,selected:n,onSelect:r,freshness:b,loading:o}){return o?e.jsx(oe,{className:"h-20 w-full rounded-2xl"}):e.jsxs("div",{className:"flex items-stretch gap-0 overflow-x-auto rounded-2xl border bg-card shadow-sm",children:[wa.map(m=>{const l=n===m.key,p=m.icon;return e.jsxs("button",{type:"button",onClick:()=>r(l?"actionable":m.key),"aria-pressed":l,className:ne("flex-1 min-w-[9.5rem] text-left px-4 py-4 border-b-2 border-r last:border-r-0 transition-colors","hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",l?m.active:"border-b-transparent"),children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-muted-foreground",children:[e.jsx("span",{className:ne("h-1.5 w-1.5 rounded-full",m.dot)}),e.jsx(p,{className:"h-3 w-3"}),m.label]}),e.jsx("span",{className:"block text-2xl font-semibold tabular-nums mt-1",children:(s[m.key]??0).toLocaleString()})]},m.key)}),e.jsxs("div",{className:"min-w-[9.5rem] px-4 py-4 border-l bg-muted/30",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-muted-foreground",children:[e.jsx(js,{className:"h-3 w-3"})," Data freshness"]}),e.jsx("span",{className:"block text-sm font-medium mt-1.5",children:b})]})]})}const ce=s=>(s??0).toLocaleString("en-AU"),ke=s=>s?new Date(s).toLocaleDateString("en-AU",{day:"2-digit",month:"short",year:"numeric"}):"-";function Sa(){var V,R,H,P,h;const[s,n]=i.useState(null),[r,b]=i.useState(!0),[o,m]=i.useState(!1),l=i.useCallback(async()=>{b(!0);const{data:C,error:A}=await T.rpc("get_pricing_data_health");A?I.error(`Pricing data health: ${A.message}`):n(C),b(!1)},[]);i.useEffect(()=>{l()},[l]);const p=(s==null?void 0:s.pending_days)??[],v=p.length===0&&!((V=s==null?void 0:s.last_run)!=null&&V.error);return e.jsxs(zs,{open:o,onOpenChange:m,children:[e.jsx(Vs,{asChild:!0,children:e.jsxs(D,{variant:"outline",size:"sm",className:"h-8 gap-1.5 text-xs",children:[r?e.jsx($e,{className:"h-3.5 w-3.5 animate-spin"}):v?e.jsx(is,{className:"h-3.5 w-3.5 text-emerald-600"}):e.jsx(_e,{className:"h-3.5 w-3.5 text-amber-600"}),e.jsx(ia,{className:"h-3.5 w-3.5"}),"Pricing data health",!r&&e.jsx(q,{variant:v?"secondary":"destructive",className:"ml-1 h-4 px-1 text-[10px]",children:v?"OK":`${p.length} pending`})]})}),e.jsxs(qs,{className:"max-w-2xl",children:[e.jsxs(Hs,{children:[e.jsxs(Ks,{className:"flex items-center gap-2 text-base",children:[v?e.jsx(is,{className:"h-5 w-5 text-emerald-600"}):e.jsx(_e,{className:"h-5 w-5 text-amber-600"}),"Pricing data health"]}),e.jsx(Gs,{children:"Raw price captures are only ever deleted after their day's totals reconcile exactly with the permanent daily aggregate, so machine-learning history is never lost."})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"flex justify-end",children:e.jsx(D,{variant:"ghost",size:"sm",onClick:l,disabled:r,children:r?e.jsx($e,{className:"h-4 w-4 animate-spin"}):e.jsx(Ge,{className:"h-4 w-4"})})}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:"Permanent history"}),e.jsxs("div",{className:"text-sm font-medium",children:[ke(s==null?void 0:s.aggregate_first_day)," - ",ke(s==null?void 0:s.aggregate_last_day)]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[ce(s==null?void 0:s.aggregate_rows)," aggregate rows"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:"Raw captures retained"}),e.jsx("div",{className:"text-sm font-medium",children:ce(s==null?void 0:s.raw_rows)}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:["since ",ke(s==null?void 0:s.raw_first_day)," (120-day
1window)"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:"Days awaiting rollup"}),e.jsxs("div",{className:"text-sm font-medium",children:[p.length," ",p.length===0?e.jsx(q,{variant:"secondary",className:"ml-1",children:"All reconciled"}):e.jsx(q,{variant:"destructive",className:"ml-1",children:"Protected from deletion"})]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:"Last nightly run"}),e.jsx("div",{className:"text-sm font-medium",children:(R=s==null?void 0:s.last_run)!=null&&R.started_at?new Date(s.last_run.started_at).toLocaleString("en-AU"):"Not run yet"}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[ce((H=s==null?void 0:s.last_run)==null?void 0:H.aggregate_rows_written)," rolled up, ",ce((P=s==null?void 0:s.last_run)==null?void 0:P.raw_rows_deleted)," raw rows purged"]})]})]}),((h=s==null?void 0:s.last_run)==null?void 0:h.error)&&e.jsxs("div",{className:"rounded-md border border-destructive/40 bg-destructive/5 p-3 text-xs text-destructive",children:["Last run failed: ",s.last_run.error]}),p.length>0&&e.jsxs("div",{className:"rounded-md border p-3",children:[e.jsx("div",{className:"text-xs font-medium mb-2",children:"Days not yet fully aggregated (kept in full)"}),e.jsx("div",{className:"space-y-1 max-h-40 overflow-auto",children:p.slice(0,30).map(C=>e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{children:ke(C.day)}),e.jsxs("span",{className:"text-muted-foreground",children:[ce(C.raw)," raw / ",ce(C.aggregated)," aggregated"]})]},C.day))})]})]})]})]})}const ms={act_now:"bg-emerald-500",review:"bg-amber-500",monitor:"bg-sky-500",insufficient_evidence:"bg-muted-foreground",expired:"bg-muted-foreground"},Ca={high:3,medium:2,low:1,insufficient:0};function xs({level:s}){const n=Ca[s]??0;return e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx("span",{className:"inline-flex gap-0.5","aria-hidden":!0,children:[1,2,3].map(r=>e.jsx("span",{className:ne("h-3 w-1 rounded-sm",r<=n?n===3?"bg-emerald-500":n===2?"bg-amber-500":"bg-muted-foreground":"bg-muted")},r))}),e.jsx("span",{className:"text-xs text-muted-foreground",children:Ye[s]})]})}function Aa({location:s,airports:n,onLocationChange:r,evidenceWindowDays:b,onEvidenceWindowChange:o,reloadKey:m=0,onFreshnessChange:l}){var ts;const[p,v]=i.useState([]),[V,R]=i.useState(!0),[H,P]=i.useState(null),[h,C]=Ws(),A=(a,d)=>h.get(`pi_${a}`)??d,B=(a,d,_)=>{const S=new URLSearchParams(h);d===_?S.delete(`pi_${a}`):S.set(`pi_${a}`,d),C(S,{replace:!0})},K=A("status","actionable"),Y=A("cat","all"),G=A("ev","all"),W=A("dir","all"),Z=A("dec","all"),re=A("from",""),U=A("to",""),J=A("q",""),X=A("dur","all"),[fe,ue]=i.useState(null),[ie,be]=i.useState(!1),[ve,ye]=i.useState({}),[t,x]=i.useState([]),[N,E]=i.useState(0),[k,Q]=i.useState(!1),[ys,Ns]=i.useState(null),ws=100,[Je,ks]=i.useState(J);i.useEffect(()=>{const a=setTimeout(()=>ks(J),300);return()=>clearTimeout(a)},[J]);const me=i.useMemo(()=>{const a=X==="all"?null:us.find(d=>d.value===X)??null;return{p_location:s==="all"?null:s,p_category:Y==="all"?null:Y,p_evidence:G==="all"?null:G,p_direction:W==="all"?null:W,p_decision:Z==="all"?null:Z,p_days_min:a?a.min:null,p_days_max:a?a.max:null,p_from:re||null,p_to:U||null,p_query:Je.trim()||null}},[s,Y,G,W,Z,X,re,U,Je]),Le=i.useCallback(async a=>{var f;const{data:d,error:_}=await T.rpc("get_pricing_recommendations_page",{...me,p_status:K,p_limit:ws,p_offset:a});if(_)throw _;const S=d??[];return{page:S,total:Number(((f=S[0])==null?void 0:f.total_count)??0)}},[me,K]),Ne=i.useCallback(async()=>{var a;R(!0),P(null);try{const[{page:d,total:_},S]=await Promise.all([Le(0),T.rpc("get_pricing_recommendation_facets",me)]);v(d),E(_);const f=S.data??{};ye({act_now:Number(f.act_now??0),review:Number(f.review??0),monitor:Number(f.monitor??0),insufficient_evidence:Number(f.insufficient_evidence??0),expired:Number(f.expired??0)}),x(Array.isArray(f.categories)?f.categories:[]);const u=f.generated_at??((a=d[0])==null?void 0:a.generated_at)??null;Ns(u),l==null||l(u,Number(f.total??_))}catch(d){const _=d instanceof Error?d.message:"Unknown error";P(_),I.error(`Recommendations: ${_}`)}R(!1)},[Le,me]);i.useEffect(()=>{Ne()},[Ne,m]);const Ss=async()=>{Q(!0);try{const{page:a}=await Le(p.length);v(d=>[...d,...a])}catch(a){I.error(`Could not load more: ${a instanceof Error?a.message:"Unknown error"}`)}Q(!1)},Cs=async(a,d,_,S)=>{const{error:f}=await T.rpc("record_pricing_recommendation_decision",{p_location:a.pickup_location_name,p_category:a.category_name,p_pickup_date:a.pickup_date,p_rental_days:a.rental_days,p_decision:d,p_applied_rate:_??void 0,p_reason:S||void 0});if(f){I.error(`Could not record decision: ${f.message}`);return}I.success(`Recorded as ${Ke[d].toLowerCase()}`),await Ne()},As=t,$s=i.useMemo(()=>{const a={act_now:0,review:0,monitor:0,insufficient_evidence:0,expired:0};
1return Object.keys(a).forEach(d=>{a[d]=ve[d]??0}),a},[ve]),le=p,Ls=fe==null?null:le[fe]??null,Rs=ys??((ts=p[0])==null?void 0:ts.generated_at)??null;i.useEffect(()=>{if(!ie)return;const a=d=>{d.key!=="ArrowDown"&&d.key!=="ArrowUp"||(d.preventDefault(),ue(_=>{if(_==null)return _;const S=d.key==="ArrowDown"?_+1:_-1;return S<0||S>=le.length?_:S}))};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[ie,le.length]);const Re=[K!=="actionable",Y!=="all",X!=="all",G!=="all",W!=="all",Z!=="all",!!re,!!U,!!J].filter(Boolean).length,es=()=>{const a=new URLSearchParams(h);["status","cat","dur","ev","dir","dec","from","to","q"].forEach(d=>a.delete(`pi_${d}`)),C(a,{replace:!0})},[ss,as]=i.useState(!1),Ds=async()=>{as(!0);const a=[];try{for(let Ee=0;Ee<1e5;Ee+=1e3){const{data:Es,error:ns}=await T.rpc("get_pricing_recommendations_page",{...me,p_status:K,p_limit:1e3,p_offset:Ee});if(ns)throw ns;const rs=Es??[];if(a.push(...rs),rs.length<1e3)break}}catch(u){as(!1),I.error(`Export failed: ${u instanceof Error?u.message:"Unknown error"}`);return}const d=["status","airport","category","pickup_date","hire_days","lead_days","availability","current_rate","customer_visible_rate","discount_amount","discount_percent","discount_source","campaign_code","rate_basis","evidence_basis","estimated","recommended_test_rate","move_pct","evidence","observations","unique_dates","uncapped_pct","decision"],_=a.map(u=>[Ae[u.status],u.pickup_location_name,u.category_name,u.pickup_date,u.rental_days,u.lead_days,u.avg_availability??"",u.current_avg_rate,u.current_rate_after_discount??"",u.current_discount_amount??"",u.current_discount_percent??"",u.current_discount_source??"",u.current_campaign_code??"",u.rate_basis,u.duration_basis,u.is_estimated?"yes":"no",je(u)?u.recommended_rate:"",je(u)?u.delta_pct:"",Ye[u.evidence_level],u.observations,u.unique_pickup_dates,u.raw_delta_pct??"",u.decision??""].join(",")),S=new Blob([[d.join(","),..._].join(` 2`)],{type:"text/csv"}),f=document.createElement("a");f.href=URL.createObjectURL(S),f.download=`rate-recommendations-${new Date().toISOString().slice(0,10)}.csv`,f.click(),URL.revokeObjectURL(f.href)},De=a=>{ue(a),be(!0)};return e.jsxs("div",{className:"space-y-4",children:[e.jsx(ka,{counts:$s,selected:K,onSelect:a=>B("status",a,"actionable"),freshness:Ze(Rs),loading:V&&p.length===0}),e.jsx("div",{className:"sticky top-0 z-10 -mx-1 px-2 py-2.5 bg-background/95 backdrop-blur rounded-2xl",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(M,{value:s,onValueChange:r,children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-52 ",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"all",children:"All airports"}),n.map(a=>e.jsx(c,{value:a,children:a},a))]})]}),e.jsxs(M,{value:Y,onValueChange:a=>B("cat",a,"all"),children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-56 ",children:e.jsx(F,{placeholder:"Category"})}),e.jsxs(z,{children:[e.jsx(c,{value:"all",children:"All categories"}),As.map(a=>e.jsx(c,{value:a,children:a},a))]})]}),e.jsxs(M,{value:X,onValueChange:a=>B("dur",a,"all"),children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-48 ",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"all",children:"Any hire length"}),us.map(a=>e.jsx(c,{value:a.value,children:a.label},a.value))]})]}),e.jsxs(M,{value:K,onValueChange:a=>B("status",a,"actionable"),children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-52 ",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"actionable",children:"Actionable only"}),e.jsx(c,{value:"act_now",children:"Act now"}),e.jsx(c,{value:"review",children:"Review manually"}),e.jsx(c,{value:"monitor",children:"Monitor"}),e.jsx(c,{value:"insufficient_evidence",children:"Insufficient evidence"}),e.jsx(c,{value:"expired",children:"Expired"}),e.jsx(c,{value:"all",children:"All except expired"})]})]}),e.jsxs(M,{value:G,onValueChange:a=>B("ev",a,"all"),children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-48 ",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"all",children:"Any evidence"}),e.jsx(c,{value:"high",children:"High"}),e.jsx(c,{value:"medium",children:"Medium"}),e.jsx(c,{value:"low",children:"Low"}),e.jsx(c,{value:"insufficient",children:"Insufficient"})]})]}),e.jsxs(M,{value:W,onValueChange:a=>B("dir",a,"all"),children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-48 ",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"all",children:"Any movement"}),e.jsx(c,{value:"up",children:"Increase"}),e.jsx(c,{value:"down",children:"Decrease"})]})]}),e.jsxs(M,{value:Z,onValueChange:a=>B("dec",a,"all"),children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-48 ",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"all",children:"Any decision"}),e.jsx(c,{value:"pending",children:"Pending"}),e.jsx(c,{value:"applied",children:"Applied"}),e.jsx(c,{value:"dismissed",children:"Dismissed"}),e.jsx(c,{value:"review_later",children:"Review later"})]})]}),e.jsxs(M,{value:b,onValueChange:o,children:[e.jsx(O,{className:"h-9 rounded-md bg-card shadow-sm text-xs w-60 ",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"14",children:"Evidence window: 14 days"}),e.jsx(c,{value:"30",children:"Evidence window: 30 days"}),e.jsx(c,{value:"60",children:"Evidence window: 60 days"}),e.jsx(c,{value:"90",children:"Evidence window: 90 days"})]})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(Ce,{type:"date","aria-label":"Pickup from",className:"h-9 w-40 rounded-md bg-card shadow-sm text-xs",value:re,onChange:a=>B("from",a.target.value,"")}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"to"}),e.jsx(Ce,{type:"date","aria-label":"Pickup to",className:"h-9 w-40 rounded-md bg-card shadow-sm text-xs",value:U,onChange:a=>B("to",a.target.value,"")})]}),e.jsxs("div",{className:"relative",children:[e.jsx(Xs,{className:"h-3.5 w-3.5 absolute left-3 top-3.5 text-muted-foreground"}),e.jsx(Ce,{className:"h-9 w-64 pl-8 rounded-md bg-card shadow-sm text-xs",placeholder:"Search airport or category",value:J,onChange:a=>B("q",a.target.value,"")})]}),Re>0&&e.jsxs(D,{variant:"ghost",size:"sm",className:"h-9 rounded-md text-xs",onClick:es,children:[e.jsx(Qs,{className:"h-3.5 w-3.5 mr-1.5"})," Clear (",Re,")"]}),e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[e.jsx(Sa,{}),e.jsxs(D,{variant:"outline",size:"sm",className:"h-9 rounded-md text-xs",onClick:Ds,disabled:N===0||ss,children:[e.jsx(fs,{className:"h-3.5 w-3.5 mr-1.5"})," ",ss?"Preparing...":"CSV"]})]})]})}),e.jsx(gs,{children:e.jsxs("p",{className:"text-xs text-muted-foreground flex items-center gap-1.5",children:[e.jsxs(ze,{children:[e.jsx(Ve,{asChild:!0,children:e.jsxs("span",{className:"inline-flex items-center gap-1 underline decoration-dotted cursor-help",children:[e.jsx(He,{className:"h-3.5 w-3.5"})," What counts as an observation?"]})}),e.jsx(qe,{className:"max-w-sm text-xs",children:fa})]}),e.jsxs(ze,{children:[e.jsx(Ve,{asChild:!0,children:e.jsxs("span",{className:"inline-flex items-center gap-1 underline decoration-dotted cursor-help",children:[e.jsx(He,{className:"h-3.5 w-3.5"}
2)," How is hire length handled?"]})}),e.jsx(qe,{className:"max-w-sm text-xs",children:ga})]}),"Showing ",le.length.toLocaleString()," of ",N.toLocaleString()," matching recommendations."]})}),e.jsx("p",{className:"text-xs text-muted-foreground rounded-lg border bg-muted/40 px-3 py-2",children:ba}),V?e.jsx("div",{className:"space-y-1.5",children:Array.from({length:10}).map((a,d)=>e.jsx(oe,{className:"h-9 w-full"},d))}):H?e.jsxs("div",{className:"rounded-2xl border bg-card shadow-sm py-10 text-center space-y-3",children:[e.jsxs("p",{className:"text-sm text-destructive",children:["Could not load recommendations: ",H]}),e.jsx(D,{variant:"outline",size:"sm",onClick:Ne,children:"Retry"})]}):p.length===0?e.jsxs("div",{className:"rounded-2xl border bg-card shadow-sm py-12 text-center space-y-3",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"No recommendations match these filters."}),Re>0&&e.jsx(D,{variant:"outline",size:"sm",onClick:es,children:"Clear filters"})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"hidden md:block rounded-2xl border bg-card shadow-sm overflow-hidden",children:e.jsx("div",{children:e.jsxs(We,{children:[e.jsx(Xe,{className:"bg-muted/60",children:e.jsxs(de,{className:"hover:bg-transparent",children:[e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide",children:"Priority"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide",children:"Airport · Category"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide",children:"Pickup · Hire length"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Current â Test rate"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide",children:"Evidence"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Details"})]})}),e.jsx(Qe,{children:le.map((a,d)=>{const _=je(a),S=Number(a.recommended_rate)-Number(a.current_avg_rate);return e.jsxs(de,{tabIndex:0,onClick:()=>De(d),onKeyDown:f=>{(f.key==="Enter"||f.key===" ")&&(f.preventDefault(),De(d))},className:"cursor-pointer h-12 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",children:[e.jsx(j,{className:"py-2.5 text-[13px] whitespace-nowrap",children:e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx("span",{className:ne("h-1.5 w-1.5 rounded-full",ms[a.status])}),Ae[a.status]]})}),e.jsxs(j,{className:"py-2.5 text-[13px]",children:[e.jsx("span",{className:"font-medium",children:a.pickup_location_name.replace(" Airport","")}),e.jsxs("span",{className:"text-muted-foreground",children:[" · ",a.category_name]})]}),e.jsxs(j,{className:"py-2.5 text-[13px] whitespace-nowrap tabular-nums",children:[a.pickup_date,e.jsxs("span",{className:"text-muted-foreground text-xs",children:[" · ",a.lead_days,"d"]}),e.jsxs("span",{className:"block text-xs text-muted-foreground",children:[ae(a.rental_days),a.is_estimated?" · Estimated":""]})]}),e.jsxs(j,{className:"py-2.5 text-right text-[13px] tabular-nums whitespace-nowrap",children:[w(a.current_avg_rate)," ",_?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-muted-foreground",children:"â"})," ",e.jsx("span",{className:"font-medium",children:w(a.recommended_rate)})," ",e.jsxs("span",{className:Number(a.delta_pct)>=0?"text-xs text-emerald-600":"text-xs text-destructive",children:[S>=0?"+":"-",w(Math.abs(S)).replace("-","")," · ",te(a.delta_pct)]})]}):e.jsx("span",{className:"text-xs text-muted-foreground",children:"· Insufficient evidence"}),e.jsxs("span",{className:"block text-xs text-muted-foreground font-normal",children:["Pay Now before discount · ",ae(a.rental_days),a.current_is_discounted?` · customer saw ${w(a.current_rate_after_discount)}${a.current_campaign_code?` with ${a.current_campaign_code}`:""}`:""]})]}),e.jsx(j,{className:"py-2.5",children:e.jsx(xs,{level:a.evidence_level})}),e.jsxs(j,{className:"py-2.5 text-right whitespace-nowrap",children:[a.decision&&e.jsx(q,{variant:"outline",className:"text-[11px] mr-1.5",children:Ke[a.decision]}),e.jsx(_s,{className:"h-3.5 w-3.5 inline text-muted-foreground"})]})]},`${a.pickup_location_name}-${a.category_name}-${a.pickup_date}-${a.rental_days}`)})})]})})}),e.jsx("div",{className:"md:hidden space-y-2",children:le.map((a,d)=>{const _=je(a);return e.jsxs("button",{onClick:()=>De(d),className:"w-full text-left rounded-2xl border bg-card shadow-sm p-3 space-y-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs",children:[e.jsx("span",{className:ne("h-1.5 w-1.5 rounded-full",ms[a.status])}),Ae[a.status]]}),e.jsx(xs,{level:a.evidence_level})]}),e.jsxs("p",{className:"text-sm font-medium",children:[a.pickup_location_name.replace(" Airport","")," · ",a.category_name]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Pickup ",a.pickup_date," · ",a.lead_days,"d · ",ae(a.rental_days),a.is_estimated?" · Estimated":""," · ",a.searches," customer ",a.searches===1?"search":"searches"]}),e.jsxs("p",{className:"text-sm tabular-nums",children:[w(a.current_avg_rate)," ",_?`â ${w(a.recommended_rate)} (${te(a.delta_pct)})`:"· Insufficient evidence"]})]},`${a.pickup_location_name}-${a.category_name}-${a.pickup_date}-${a.rental_days}`)})}),p.length<N&&e.jsx("div",{className:"flex justify-center",children:e.jsx(D,{variant:"outline",size:"sm",onClick:Ss,disabled:k,children:k?"Loading...":`Load more (${(N-p.length).toLocaleStr
2ing()} remaining)`})})]}),e.jsx(Na,{row:Ls,open:ie,onOpenChange:be,onDecide:Cs})]})}const $a=(s,n)=>s==null||n==null||Number(s)===0?null:(Number(n)-Number(s))/Number(s)*100,Se=({before:s,after:n})=>{const r=$a(s,n);return r==null?e.jsx("span",{className:"text-muted-foreground",children:"-"}):e.jsx("span",{className:r>=0?"text-emerald-600":"text-destructive",children:te(r)})};function La(){const[s,n]=i.useState([]),[r,b]=i.useState(!0),[o,m]=i.useState("60");return i.useEffect(()=>{let l=!1;return(async()=>{b(!0);const{data:p,error:v}=await T.rpc("get_pricing_decision_outcomes",{p_days:Number(o)});l||(v?I.error(`Outcomes: ${v.message}`):n(p??[]),b(!1))})(),()=>{l=!0}},[o]),e.jsxs(ee,{children:[e.jsx(pe,{className:"pb-3",children:e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("div",{children:[e.jsx(ge,{className:"text-base",children:"Shadow mode outcomes"}),e.jsx(Ys,{children:"What happened after staff recorded a decision. Observation only - no rate is written to RCM."})]}),e.jsxs(M,{value:o,onValueChange:m,children:[e.jsx(O,{className:"h-9 w-40",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"14",children:"Last 14 days"}),e.jsx(c,{value:"30",children:"Last 30 days"}),e.jsx(c,{value:"60",children:"Last 60 days"}),e.jsx(c,{value:"120",children:"Last 120 days"})]})]})]})}),e.jsx(se,{children:r?e.jsx(oe,{className:"h-56 w-full"}):s.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-8 text-center",children:"No decisions recorded yet. Mark recommendations as applied or dismissed to start building the shadow-mode record."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(We,{children:[e.jsx(Xe,{children:e.jsxs(de,{children:[e.jsx(g,{children:"Decision"}),e.jsx(g,{children:"Airport"}),e.jsx(g,{children:"Category"}),e.jsx(g,{children:"Pickup"}),e.jsx(g,{className:"text-right",children:"Previous"}),e.jsx(g,{className:"text-right",children:"Applied"}),e.jsx(g,{className:"text-right",children:"Searches"}),e.jsx(g,{className:"text-right",children:"Bookings"}),e.jsx(g,{className:"text-right",children:"Revenue"}),e.jsx(g,{className:"text-right",children:"Availability"}),e.jsx(g,{children:"By"})]})}),e.jsx(Qe,{children:s.map((l,p)=>{var v;return e.jsxs(de,{children:[e.jsx(j,{className:"py-2",children:e.jsx(q,{variant:"outline",className:"text-[11px]",children:Ke[l.decision]??l.decision})}),e.jsx(j,{className:"py-2 text-sm",children:(v=l.pickup_location_name)==null?void 0:v.replace(" Airport","")}),e.jsx(j,{className:"py-2 text-sm",children:l.category_name}),e.jsx(j,{className:"py-2 text-sm",children:l.pickup_date}),e.jsx(j,{className:"py-2 text-right text-sm tabular-nums",children:w(l.previous_rate)}),e.jsx(j,{className:"py-2 text-right text-sm tabular-nums",children:w(l.applied_rate)}),e.jsx(j,{className:"py-2 text-right text-sm",children:e.jsx(Se,{before:l.searches_before,after:l.searches_after})}),e.jsx(j,{className:"py-2 text-right text-sm",children:e.jsx(Se,{before:l.bookings_before,after:l.bookings_after})}),e.jsx(j,{className:"py-2 text-right text-sm",children:e.jsx(Se,{before:l.revenue_before,after:l.revenue_after})}),e.jsx(j,{className:"py-2 text-right text-sm",children:e.jsx(Se,{before:l.availability_before,after:l.availability_after})}),e.jsx(j,{className:"py-2 text-xs text-muted-foreground",children:l.decided_by_email??"-"})]},`${l.pickup_location_name}-${l.category_name}-${l.pickup_date}-${p}`)})})]})})})]})}const Ra={website_pricing_bookings_match_canonical:"Website pricing bookings match the authoritative booking figures",no_excluded_airport_in_recommendations:"Mackay stays out of every pricing figure",recommendations_use_pay_now_before_discount:"Recommendations use the Pay Now price before discount",estimated_rows_never_act_now_or_high:"Estimated rows are never marked act now or high confidence",recommendations_backed_by_genuine_searches:"Every recommendation is backed by genuine customer searches"};function Da(){const{data:s}=bs({queryKey:["pricing-reconciliation-health"],queryFn:async()=>{const{data:o,error:m}=await T.rpc("get_pricing_reconciliation_health");if(m)throw m;return o},staleTime:6e5}),n=(s==null?void 0:s.checks)??[];if(n.length===0)return null;const r=n.filter(o=>!o.passed),b=s!=null&&s.last_run?new Date(s.last_run).toLocaleStr
2ing("en-AU"):"not run yet";return e.jsx(ee,{className:"rounded-2xl shadow-sm",children:e.jsxs(se,{className:"p-4 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[r.length===0?e.jsx(Zs,{className:"h-4 w-4 text-emerald-600"}):e.jsx(_e,{className:"h-4 w-4 text-destructive"}),e.jsx("p",{className:"text-sm font-medium",children:r.length===0?"All pricing figures reconcile":`${r.length} pricing figure${r.length===1?"":"s"} no longer reconcile`}),e.jsxs("span",{className:"ml-auto text-xs text-muted-foreground",children:["Last checked ",b]})]}),e.jsx("ul",{className:"space-y-1",children:n.map(o=>e.jsxs("li",{className:"flex items-start gap-2 text-xs",children:[e.jsx("span",{className:ne("mt-1 h-1.5 w-1.5 shrink-0 rounded-full",o.passed?"bg-emerald-500":"bg-destructive")}),e.jsxs("span",{className:ne(o.passed?"text-muted-foreground":"text-foreground"),children:[Ra[o.check_name]??o.check_name,!o.passed&&o.difference!=null?` - off by ${Number(o.difference).toLocaleString()}`:""]})]},o.check_name))}),e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Each figure is recalculated overnight straight from the raw records, not from the same calculation that produced the number on screen."})]})})}function L({label:s,value:n,note:r}){return e.jsxs("div",{className:"flex items-start justify-between gap-4 text-xs",children:[e.jsxs("span",{className:"text-muted-foreground",children:[s,r?e.jsx("span",{className:"block text-[11px] opacity-80",children:r}):null]}),e.jsx("span",{className:"font-medium tabular-nums",children:n})]})}const $=s=>s==null?"-":Number(s).toLocaleString("en-AU");function Ea(){const{data:s}=bs({queryKey:["pricing-attribution-health"],queryFn:async()=>{const{data:o,error:m}=await T.rpc("get_pricing_attribution_health");if(m)throw m;return o},staleTime:6e5});if(!s)return null;const n=s.bookings,r=s.recommendations,b=s.canonical_freshness_at?new Date(s.canonical_freshness_at).toLocaleString("en-AU"):"no captures yet";return e.jsx(ee,{className:"rounded-2xl shadow-sm",children:e.jsxs(se,{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(vs,{className:"h-4 w-4 text-muted-foreground"}),e.jsx("p",{className:"text-sm font-medium",children:"What these pricing figures are built on"}),e.jsx("span",{className:"ml-auto text-xs text-muted-foreground",children:s.advisory_only?"Advice only - never changes a price":"Advisory flag off"})]}),e.jsxs("div",{className:"grid gap-x-8 gap-y-1.5 sm:grid-cols-2",children:[e.jsx(L,{label:`Genuine customer searches (last ${s.window_days} days)`,value:$(s.eligible_runs)}),e.jsx(L,{label:"Prices recorded from those searches",value:$(s.eligible_offer_rows)}),e.jsx(L,{label:"Cars shown as available with no price recorded",value:$(s.available_missing_rate),note:"Reported, never guessed"}),e.jsx(L,{label:"Rows with an unusable hire length",value:$(s.invalid_duration_rows)}),e.jsx(L,{label:"Bookings measured",value:$(n.total)}),e.jsx(L,{label:"Bookings tied to a recorded search",value:`${$(n.attributed)}${n.attribution_coverage_pct==null?"":` (${n.attribution_coverage_pct}%)`}`,note:`${$(n.direct_verified)} direct, ${$(n.session_match_verified)} matched by visit`}),e.jsx(L,{label:"Bookings that could match more than one search",value:$(n.ambiguous)}),e.jsx(L,{label:"Bookings with no search we can tie them to",value:$(n.unlinked)}),e.jsx(L,{label:"Bookings with a rejected search tag",value:$(n.invalid_direct_link)}),e.jsx(L,{label:"Bookings with no vehicle type we recognise",value:$(n.unclassified_vehicle_type)}),e.jsx(L,{label:"Rate suggestions",value:$(r.rows_total)}),e.jsx(L,{label:"Marked act now",value:$(r.act_now),note:`Needs at least ${s.act_now_min_searches} genuine searches`}),e.jsx(L,{label:"Not enough evidence",value:$(r.insufficient_evidence)}),e.jsx(L,{label:"Held back by the safety limit",value:$(r.capped)}),e.jsx(L,{label:"Suggestions with real linked conversion",value:$(r.with_linked_conversion)}),e.jsx(L,{label:"Most recent price captured",value:b})]})]})})}const hs=["Sydney Airport","Melbourne Airport","Brisbane Airport","Perth Airport","Adelaide Airport","Cairns Airport","Hobart Airport","Sunshine Coast Airport"],he=s=>s==null?"-":new Intl.NumberFormat("en-AU",{style:"currency",currency:"AUD",minimumFractionDigits:2}).format(Number(s)),Oe=s=>new Date(Date.now()-s*864e5).toISOString().split("T")[0],ps=["#2B3990","#e11d48","#0f766e","#b45309","#7c3aed","#0284c7","#65a30d","#db2777"];function Fe({onRetry:s}){return e.jsxs("div",{className:"py-8 text-center space-y-3",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"This chart took too long to build from the pricing history. Your data is fine - try again, or narrow the date range or airport."}),e.jsx(D,{variant:"outline",size:"sm",className:"rounded-md",onClick:s,children:"Try again"})]})}function Xa(){var ye;const[s,n]=i.useState("30"),[r,b]=i.useState("all"),[o,m]=i.useState([]),[l,p]=i.useState([]),[v,V]=i.useState([]),[R,H]=i.useState([]),[P,h]=i.useState(!0),[C,A]=i.useState({}),[B,K]=i.useState(!1),[Y,G]=i.useState(0),[W,Z]=i.useState({generatedAt:null,count:0}),re=i.useCallback((t,x)=>{Z({generatedAt:t,count:x})},[]),U=i.useCallback(async()=>{h(!0),A({});const t=r==="all"?void 0:r,x=await T.rpc("get_pricing_rate_trend",{p_
2start:Oe(Number(s)),p_end:Oe(0),p_location:t});x.error?A(Q=>({...Q,trend:!0})):m(x.data??[]);const N=await T.rpc("get_pricing_airport_comparison",{p_days:7});N.error?A(Q=>({...Q,comparison:!0})):p(N.data??[]);const E=await T.rpc("get_pricing_pickup_curve",{p_location:t,p_horizon_days:120});E.error?A(Q=>({...Q,curve:!0})):V(E.data??[]);const k=await T.rpc("get_pricing_recommendations",{p_location:t,p_limit:300});k.error?I.error(`Recommendations: ${k.error.message}`):H(k.data??[]),h(!1)},[s,r]);i.useEffect(()=>{U()},[U]);const J=async()=>{K(!0);const{data:t,error:x}=await T.functions.invoke("pricing-recommendations-refresh",{body:{}}),N=(t==null?void 0:t.error)??(x?x.message:null);if(N){const E=/timeout|57014|canceling statement/i.test(N)?"Rebuild is taking longer than expected - please try again in a few minutes.":N;I.error(`Could not refresh: ${E}`)}else I.success("Recommendations refreshed"),G(E=>E+1),await U();K(!1)},X=i.useMemo(()=>{const t=new Map;return o.forEach(x=>{const N=t.get(x.snapshot_date)??{date:x.snapshot_date};N[x.pickup_location_name]=Number(x.avg_rate),t.set(x.snapshot_date,N)}),Array.from(t.values()).sort((x,N)=>String(x.date).localeCompare(String(N.date)))},[o]),fe=i.useMemo(()=>Array.from(new Set(o.map(t=>t.pickup_location_name))).sort(),[o]),ue=i.useMemo(()=>v.map(t=>({...t,avg_rate:Number(t.avg_rate),min_rate:Number(t.min_rate)})),[v]),ie=W.generatedAt??((ye=R[0])==null?void 0:ye.generated_at)??null,be=W.count||R.length,ve=()=>{const t=["airport","category","pickup_date","lead_days","current_rate","recommended_rate","floor","ceiling","delta_pct","confidence","bookings","searches"],x=R.map(k=>[k.pickup_location_name,k.category_name,k.pickup_date,k.lead_days,k.current_avg_rate,k.recommended_rate,k.floor_rate,k.ceiling_rate,k.delta_pct,k.confidence,k.bookings_count,k.searches].join(",")),N=new Blob([[t.join(","),...x].join(` 3`)],{type:"text/csv"}),E=document.createElement("a");E.href=URL.createObjectURL(N),E.download=`rate-recommendations-${Oe(0)}.csv`,E.click(),URL.revokeObjectURL(E.href)};return e.jsx("div",{className:"space-y-5",children:e.jsxs(Js,{defaultValue:"decisions",className:"space-y-5",children:[e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs(ea,{className:"rounded-full bg-muted/60 p-1",children:[e.jsx(ls,{value:"decisions",className:"rounded-full px-5 text-sm",children:"Decisions"}),e.jsx(ls,{value:"analysis",className:"rounded-full px-5 text-sm",children:"Analysis"})]}),e.jsx(ua,{subline:ie?`Last built ${Ze(ie)} · ${be.toLocaleString()} recommendations loaded`:"Advisory rate recommendations built from Simba captured pricing, availability and bookings.",onRefresh:J,refreshing:B})]}),e.jsx(xa,{onRefreshed:()=>G(t=>t+1)}),e.jsx(Da,{}),e.jsx(Ea,{})]}),e.jsx(cs,{value:"decisions",children:e.jsx(Aa,{location:r,airports:hs,onLocationChange:b,evidenceWindowDays:s,onEvidenceWindowChange:n,reloadKey:Y,onFreshnessChange:re})}),e.jsxs(cs,{value:"analysis",className:"space-y-5",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs(M,{value:r,onValueChange:b,children:[e.jsx(O,{className:"h-9 w-[200px] rounded-md bg-card shadow-sm px-4 text-sm font-medium",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"all",children:"All airports"}),hs.map(t=>e.jsx(c,{value:t,children:t},t))]})]}),e.jsxs(M,{value:s,onValueChange:n,children:[e.jsx(O,{className:"h-9 w-[180px] rounded-md bg-card shadow-sm px-4 text-sm font-medium",children:e.jsx(F,{})}),e.jsxs(z,{children:[e.jsx(c,{value:"14",children:"Last 14 days"}),e.jsx(c,{value:"30",children:"Last 30 days"}),e.jsx(c,{value:"60",children:"Last 60 days"}),e.jsx(c,{value:"90",children:"Last 90 days"})]})]}),e.jsxs(D,{variant:"outline",size:"sm",className:"ml-auto rounded-md shadow-sm",onClick:ve,disabled:R.length===0,children:[e.jsx(fs,{className:"h-3.5 w-3.5 mr-1.5"})," Export recommendations"]})]}),e.jsxs(ee,{className:"rounded-2xl shadow-sm",children:[e.jsxs(pe,{className:"pb-3",children:[e.jsx(ge,{className:"text-base",children:"Average searched daily rate by capture date"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Prices shown to customers, not completed rentals. Undiscounted Pay N
3ow rates from genuine first searches in the shared pricing dataset, exact category names. Mackay excluded."})]}),e.jsx(se,{children:P?e.jsx(oe,{className:"h-72 w-full"}):C.trend?e.jsx(Fe,{onRetry:U}):X.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-8 text-center",children:"No pricing history for this range yet."}):e.jsx(Te,{width:"100%",height:300,children:e.jsxs(os,{data:X,children:[e.jsx(Be,{strokeDasharray:"3 3",className:"stroke-muted"}),e.jsx(Ie,{dataKey:"date",tick:{fontSize:11}}),e.jsx(Ue,{tick:{fontSize:11},tickFormatter:t=>`$${t}`}),e.jsx(Me,{formatter:t=>he(t)}),e.jsx(ds,{wrapperStyle:{fontSize:11}}),fe.map((t,x)=>e.jsx(Pe,{type:"monotone",dataKey:t,stroke:ps[x%ps.length],dot:!1,strokeWidth:2},t))]})})})]}),e.jsxs(ee,{className:"rounded-2xl shadow-sm",children:[e.jsxs(pe,{className:"pb-3",children:[e.jsx(ge,{className:"text-base",children:"Airport comparison (last 7 captured days)"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Rates are undiscounted Pay Now. Searches count each customer search once."})]}),e.jsx(se,{children:P?e.jsx(oe,{className:"h-72 w-full"}):C.comparison?e.jsx(Fe,{onRetry:U}):e.jsxs(e.Fragment,{children:[e.jsx(Te,{width:"100%",height:240,children:e.jsxs(ca,{data:l.map(t=>({name:t.pickup_location_name.replace(" Airport",""),rate:Number(t.avg_rate)})),children:[e.jsx(Be,{strokeDasharray:"3 3",className:"stroke-muted"}),e.jsx(Ie,{dataKey:"name",tick:{fontSize:11}}),e.jsx(Ue,{tick:{fontSize:11},tickFormatter:t=>`$${t}`}),e.jsx(Me,{formatter:t=>he(t)}),e.jsx(la,{dataKey:"rate",fill:"#2B3990",radius:[4,4,0,0]})]})}),e.jsxs(We,{className:"mt-4",children:[e.jsx(Xe,{children:e.jsxs(de,{children:[e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide",children:"Airport"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Avg rate"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Lowest"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Week change"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Avg discount"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Available"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"Unique searches"}),e.jsx(g,{className:"h-9 text-[11px] uppercase tracking-wide text-right",children:"No price recorded"})]})}),e.jsx(Qe,{children:l.map(t=>{const x=Number(t.change_pct),N=x>.5?sa:x<-.5?aa:oa;return e.jsxs(de,{className:"h-[34px]",children:[e.jsx(j,{className:"py-1.5 text-[13px]",children:t.pickup_location_name}),e.jsx(j,{className:"py-1.5 text-right text-[13px] font-medium tabular-nums",children:he(t.avg_rate)}),e.jsx(j,{className:"py-1.5 text-right text-[13px] tabular-nums",children:he(t.min_rate)}),e.jsx(j,{className:"py-1.5 text-right text-[13px] tabular-nums",children:e.jsxs("span",{className:`inline-flex items-center gap-1 ${x>.5?"text-emerald-600":x<-.5?"text-destructive":"text-muted-foreground"}`,children:[e.jsx(N,{className:"h-3 w-3"}),x.toFixed(1),"%"]})}),e.jsxs(j,{className:"py-1.5 text-right text-[13px] tabular-nums",children:[Number(t.avg_discount).toFixed(1),"%"]}),e.jsxs(j,{className:"py-1.5 text-right text-[13px] tabular-nums",children:[Number(t.avg_availability).toFixed(1),"%"]}),e.jsx(j,{className:"py-1.5 text-right text-[13px] tabular-nums",children:t.searches}),e.jsx(j,{className:"py-1.5 text-right text-[13px] tabular-nums text-muted-foreground",children:Number(t.unpriced_available??0).toLocaleString()})]},t.pickup_location_name)})})]})]})})]}),e.jsxs(ee,{className:"rounded-2xl shadow-sm",children:[e.jsxs(pe,{className:"pb-3",children:[e.jsx(ge,{className:"text-base",children:"Rate by pickup date (next 120 days)"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Based on the last 7 days of undiscounted Pay Now captures."})]}),e.jsx(se,{children:P?e.jsx(oe,{className:"h-72 w-full"}):C.curve?e.jsx(Fe,{onRetry:U}):ue.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-8 text-center",children:"No forward pricing captured yet."}):e.jsx(Te,{width:"100%",height:300,children:e.jsxs(os,{data:ue,children:[e.jsx(Be,{strokeDasharray:"3 3",className:"stroke-muted"}),e.jsx(Ie,{dataKey:"pickup_date",tick:{fontSize:11}}),e.jsx(Ue,{tick:{fontSize:11}
3,tickFormatter:t=>`$${t}`}),e.jsx(Me,{formatter:t=>he(t)}),e.jsx(ds,{wrapperStyle:{fontSize:11}}),e.jsx(Pe,{type:"monotone",dataKey:"avg_rate",name:"Average rate",stroke:"#2B3990",dot:!1,strokeWidth:2}),e.jsx(Pe,{type:"monotone",dataKey:"min_rate",name:"Lowest rate",stroke:"#65a30d",dot:!1,strokeWidth:1.5})]})})})]}),e.jsxs(ee,{className:"rounded-2xl shadow-sm",children:[e.jsx(pe,{className:"pb-3",children:e.jsx(ge,{className:"text-base",children:"Applied changes and outcomes"})}),e.jsx(se,{children:e.jsx(La,{})})]})]})]})})}export{Xa as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.