1import{e as W,r as b,j as e}from"./vendor-react-CcKkUfnx.js";import{a as P,u as v}from"./vendor-query-CJvMTFvr.js";import{M as Q}from"./MobileShell-DjHPeMYK.js";import{u as I,I as O,a9 as T,L as C,P as L,c7 as B,J,a7 as _}from"./index-BNIXr27Q.js";import{S as z}from"./ScreenState-KbBuUQQN.js";import{S as Y}from"./Sheet-BEeu1ppP.js";import{S as H}from"./SpikeReasonSheet-DPOuKjKi.js";import"./vendor-radix-BU3ADp7c.js";import"./vendor-utils-1ueOzUbR.js";import"./vendor-ui-Rp8Pe-x-.js";import"./useLockBodyScroll-BZdTgVN6.js";import"./useViewportMode-jtN6pFkb.js";import"./tokens-soak1_6f.js";import"./reasonIcons-X0gmKzFK.js";function f(t,...a){for(const r of a){const n=t?.[r];if(n==null)continue;const i=typeof n=="number"?n:Number(n);if(Number.isFinite(i))return i}return 0}function F(t){return{carbs:f(t,"carbs_g","carbs","carbohydrates_g"),protein:f(t,"protein_g","protein"),fat:f(t,"fat_g","fat"),fiber:f(t,"fiber_g","fiber"),grams:f(t,"quantity_g","serving_g","quantity","portion_g","weight_g")}}const m=t=>Math.round(t*10)/10;function U(t){return(Array.isArray(t)?t:[]).reduce((r,n)=>{const i=F(n);return{carbs:m(r.carbs+i.carbs),protein:m(r.protein+i.protein),fat:m(r.fat+i.fat),fiber:m(r.fiber+i.fiber),grams:m(r.grams+i.grams)}},{carbs:0,protein:0,fat:0,fiber:0,grams:0})}function q(t){const a=t?.name??t?.food_name??"";return String(a).trim()}function V(t){const a=F(t),r=[];return a.grams>0&&r.push(`${m(a.grams)} g`),r.push(`${m(a.carbs)} g carbs`),r.join(" · ")}function X(t){if(!t)return null;if(t.asleep)return"You were asleep when this happened.";const a=t.hours_since_wake;return typeof a=="number"&&Number.isFinite(a)&&a>=0?a<1?"This was just after you woke up.":`About ${Math.round(a)}h after waking.`:null}const Z={low:"slate",medium:"blue",high:"green"};function N(t){return t.peak_at??t.started_at}function p(t){return t.kind==="drop"||(t.delta_mg_dl??0)<0}
1function y(t){return p(t)?"Glucose drop":t.meal_scan_id?"Meal-linked rise":"Glucose rise"}function ee(t){if(!t)return"Recent";const a=new Date(t).getTime();if(!Number.isFinite(a))return"Recent";const r=Math.max(0,Math.round((Date.now()-a)/6e4));if(r<1)return"Just now";if(r<60)return`${r}m ago`;const n=Math.round(r/60);return n<24?`${n}h ago`:new Date(t).toLocaleDateString(void 0,{month:"short",day:"numeric"})}function D(t){const a=ee(N(t)),r=t.extreme_mg_dl==null?null:`${p(t)?"low":"peak"} ${Math.round(t.extreme_mg_dl)} mg/dL`;return[a,r].filter(Boolean).join(" · ")||"Detected from connected glucose data"}function ge(){const{user:t}=I(),a=W(),r=P(),[n,i]=b.useState(null),[w,k]=b.useState(null),[l,R]=b.useState(7),d=v({queryKey:["glucose","excursions","recent",t?.id,l],queryFn:async()=>{const[s,o]=await Promise.allSettled([_.list("detected",l),_.list("annotated",l)]);if(s.status==="rejected"&&o.status==="rejected")throw s.reason??o.reason??new Error("Could not load glucose events");const c=u=>u.status==="fulfilled"?u.value.excursions??[]:[],g=new Set;return{rows:[...c(s),...c(o)].filter(u=>!g.has(u.id)&&!!g.add(u.id)).sort((u,K)=>new Date(N(K)??0).getTime()-new Date(N(u)??0).getTime()).slice(0,l===7?12:60),incomplete:s.status==="rejected"||o.status==="rejected"}},enabled:!!t?.id,staleTime:6e4}),j=v({queryKey:["glucose","excursion-context",n?.id],queryFn:()=>_.context(n.id),enabled:!!n?.id,staleTime:5*6e4}),x=j.data?.meal_scan?.foods??[],h=b.useMemo(()=>U(x),[x]),S=X(j.data?.sleep),$=v({queryKey:["glucose","excursion-insights",t?.id],queryFn:()=>_.insights(30),enabled:!!t?.id,staleTime:5*6e4}),A={isLoading:d.isLoading,isError:d.isError,data:d.data?.rows,retry:d.refetch,isStale:d.isFetched&&d.isStale},M=b.useMemo(()=>$.data?.patterns??[],[$.data]),E=s=>{i(null),k({id:s.id,peak_at:s.peak_at??void 0,started_at:s.started_at??void 0,delta:Math.round(s.delta_mg_dl??0),title:y(s),reason_tag:s.reason_tag??null,reason_notes:s.reason_notes??null,meal_scan_
1id:s.meal_scan_id??null})},G=()=>{r.invalidateQueries({queryKey:["glucose","excursions","recent",t?.id]}),r.invalidateQueries({queryKey:["glucose","excursion-insights",t?.id]})};return e.jsxs(Q,{tab:"glucose",children:[e.jsxs(O,{children:[e.jsxs("header",{className:"px-1 pb-2",children:[e.jsx("div",{className:"text-[11px] font-bold uppercase tracking-[0.14em] text-orange-700",children:"Glucose events"}),e.jsx("h1",{className:"font-serif text-3xl font-semibold text-stone-900",children:"What changed?"}),e.jsx("p",{className:"mt-1 text-sm leading-snug text-stone-600",children:"Add context to a detected rise or drop. A possible reason is not a diagnosis or a confirmed cause."})]}),e.jsx("div",{className:"mb-3 flex items-center gap-2 px-1",role:"group","aria-label":"Time range",children:[7,30].map(s=>e.jsxs("button",{type:"button",onClick:()=>R(s),"aria-pressed":l===s,className:`min-h-11 rounded-full px-4 text-[13px] font-bold transition ${l===s?"bg-orange-600 text-white":"bg-white text-stone-600 ring-1 ring-stone-200"}`,children:["Last ",s," days"]},s))}),d.data?.incomplete&&e.jsxs("div",{role:"status",className:"mb-3 rounded-xl border border-amber-200 bg-amber-50 p-3 text-sm text-amber-950",children:["Some event sources could not load. This list may be incomplete; saved reasons and available events are still shown.",e.jsx("button",{type:"button",onClick:()=>{d.refetch()},className:"mt-2 block min-h-11 rounded-xl border border-amber-300 px-4 font-semibold",children:"Retry event sources"})]}),e.jsx(z,{query:A,empty:{title:d.data?.incomplete?"No events from the available source":`No events in the last ${l} days`,body:l===7?"When connected glucose data shows a notable rise or drop, it will appear here with its time and source values. Try the last 30 days for older events.":"When connected glucose data shows a notable rise or drop, it will appear here with its time and source values."},children:s=>e.jsx(T,{label:`Recent events · last ${l} days`,children:s.map(o=>{const c=p(o),g=Math.round(o.delta_mg_dl??0);return e.jsx(C,{onClick:()=>i(o),iconName:c?"glucose-drop":"chart",tone:c?"amber":"orange",title:y(o),subtitle:D(o),trailing:e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsxs("b",{className:`tabular-nums ${c?"text-amber-700":"text-orange-700"}`,children:[g>0?"+":"",g]}),e.jsx(L,{tone:c?"amber":"orange",children:o.reason_tag?"context added":"add context"})]})},o.id)})})}),M.length>0&&e.jsx(B,{sectionKey:"spikes-learned",title:"Patterns worth checking",children:e.jsx(T,{children:M.slice(0,4).map((s,o)=>e.jsx(C,{iconName:"sparkle",tone:"violet",title:s.tag?.replace(/_/g," ")||"Glucose pattern",subtitle:s.recommendation||`${s.frequency??0} comparable events · average ${s.avg_delta!=null?`+${Math.round(s.avg_delta)} mg/dL`:"change unavailable"}`,trailing:s.confidence?e.jsxs(L,{tone:Z[s.confidence],children:[s.confidence," confidence"]}):void 0},`${s.tag??"pattern"}-${o}`))})})]}),e.jsx(Y,{open:!!n,onClose:()=>i(null),title:"Glucose event",children:n&&e.jsxs("div",{className:"space-y-4 px-4 pb-6",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(J,{name:p(n)?"glucose-drop":"chart",tone:p(n)?"amber":"orange",size:"md"}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-bold text-stone-900",children:y(n)}),e.jsx("p",{className:"text-sm text-stone-600",children:D(n)})]})]}),e.jsxs("dl",{className:"grid grid-cols-2 gap-2 rounded-2xl bg-orange-50 p-3 text-sm",children:[e.jsxs("div",{children:[e.jsx("dt",{className:"text-[11px] font-bold uppercase tracking-wide text-stone-500",children:"Change"}),e.jsx("dd",{className:"mt-0.5 font-bold text-stone-900",children:n.delta_mg_dl==null?"Not available":`${n.delta_mg_dl>0?"+":""}${Math.round(n.delta_mg_dl)} mg/dL`})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-[11px] font-bold uppercase tracking-wide text-stone-500",children:"Source value"}),e.jsx("dd",{className:"mt-0.5 font-bold text-stone-900",children:n.extreme_mg_dl==null?"Not available":`${Math.round(n.extreme_mg_dl)} mg/dL`})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-[11px] font-bold uppercase tracking-wide text-stone-500",children:"Baseline"}),e.jsx("dd",{className:"mt-0.5 font-bold text-stone-900",children:n.baseline_mg_dl==null?"Not available":`${Math.round(n.baseline_mg_dl)} mg/dL`})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-[11px] font-bold uppercase tracking-wide text-stone-500",children:"Status"}),e.jsx("dd",{className:"mt-0.5 font-bold text-stone-900",children:n.reason_tag?"Context added":"Needs context"})]})]}
1),n.meal_scan_id!=null&&x.length>0&&e.jsxs("div",{className:"rounded-2xl border border-stone-200 bg-white p-3",children:[e.jsx("div",{className:"text-[11px] font-bold uppercase tracking-wide text-stone-500",children:"What you ate before this"}),e.jsx("p",{className:"mt-0.5 text-sm font-bold text-stone-900",children:j.data?.meal_scan?.meal_name||"Scanned meal"}),e.jsxs("p",{className:"mt-0.5 text-sm text-stone-600",children:[h.carbs," g carbs · ",h.protein," g protein · ",h.fat," g fat",h.fiber>0?` · ${h.fiber} g fibre`:""]}),e.jsx("ul",{className:"mt-2 space-y-1",children:x.slice(0,6).map((s,o)=>e.jsxs("li",{className:"flex items-baseline justify-between gap-3 text-sm",children:[e.jsx("span",{className:"min-w-0 truncate text-stone-800",children:q(s)||"Item"}),e.jsx("span",{className:"shrink-0 tabular-nums text-stone-500",children:V(s)})]},`${q(s)}-${o}`))}),x.length>6&&e.jsxs("p",{className:"mt-1 text-xs text-stone-500",children:["+",x.length-6," more"]})]}),S&&e.jsx("p",{className:"rounded-2xl bg-stone-100 px-3 py-2 text-sm text-stone-700",children:S}),e.jsx("div",{className:"rounded-2xl border border-stone-200 bg-white p-3 text-sm leading-snug text-stone-600",children:n.ai_explanation||"The app detected a change in glucose data. Add the context you remember; it stays an observation, not proof of a cause."}),e.jsx("button",{type:"button",onClick:()=>E(n),className:"min-h-11 w-full rounded-2xl bg-orange-600 px-4 text-sm font-bold text-white active:scale-[0.99]",children:n.reason_tag?"Edit context":"Add a possible reason"}),p(n)&&e.jsx("button",{type:"button",onClick:()=>a("/m/care-plan"),className:"min-h-11 w-full rounded-2xl border border-stone-300 px-4 text-sm font-bold text-stone-800",children:"Review my care plan"})]})}),e.jsx(H,{open:!!w,spike:w,onClose:()=>k(null),onDone:G})]})}export{ge 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.