forge-openclaw-plugin 0.2.100 → 0.2.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{activity-page-5oyCFOns.js → activity-page-CpjuNSHw.js} +1 -1
- package/dist/assets/{ai-surface-workspace-qgk_B57-.js → ai-surface-workspace-DEAFZruS.js} +1 -1
- package/dist/assets/{atlas-panel-rfH2qOez.js → atlas-panel-CdVNPotj.js} +1 -1
- package/dist/assets/{calendar-page-Bo2iua-a.js → calendar-page-DNNt6lfz.js} +1 -1
- package/dist/assets/{calendar-rules-DA1g3QUk.js → calendar-rules-DNJFNsxi.js} +1 -1
- package/dist/assets/{calendar-week-toolbar-DU1Q4RYj.js → calendar-week-toolbar-BbPwYeN0.js} +1 -1
- package/dist/assets/{companion-sync-lab-page-CosNknOK.js → companion-sync-lab-page-KxEDigM6.js} +1 -1
- package/dist/assets/{daily-metrics-dashboard-LjuGAB3f.js → daily-metrics-dashboard-B3cqJgDt.js} +1 -1
- package/dist/assets/{entity-note-count-link-BmGDB572.js → entity-note-count-link-DrhjJZ4i.js} +1 -1
- package/dist/assets/{entity-notes-surface-DgEgicaE.js → entity-notes-surface-CkcRsKJQ.js} +1 -1
- package/dist/assets/{execution-board-CDRXQB85.js → execution-board-D07gOocB.js} +1 -1
- package/dist/assets/{faceted-token-search-CE1YauRd.js → faceted-token-search-BxRRcM3q.js} +1 -1
- package/dist/assets/{flagship-signal-deck-DDds90Gl.js → flagship-signal-deck-cmy82b8_.js} +1 -1
- package/dist/assets/{floating-action-menu-CJkI2iFy.js → floating-action-menu-Fs_ZiUMo.js} +1 -1
- package/dist/assets/{goal-detail-page-cJvHaLMQ.js → goal-detail-page-CqLiNz4f.js} +1 -1
- package/dist/assets/{goals-page-f_39hvUV.js → goals-page-BTk7mg_T.js} +1 -1
- package/dist/assets/{habits-page-DKb96_mj.js → habits-page-BJxagdzx.js} +1 -1
- package/dist/assets/{index-BHTUu_4M.js → index-CF4J4R9L.js} +2 -2
- package/dist/assets/{insight-flow-dialog-pzAzyayN.js → insight-flow-dialog-8f3D0GuC.js} +1 -1
- package/dist/assets/{insights-page-Dc9oFltJ.js → insights-page-D6rOa7uk.js} +1 -1
- package/dist/assets/{kanban-page-JAxerYh6.js → kanban-page-XQ7Se6dH.js} +1 -1
- package/dist/assets/{knowledge-graph-page-UQ3skqEi.js → knowledge-graph-page-BtAg8iv3.js} +1 -1
- package/dist/assets/{life-force-page-BGDbQuVh.js → life-force-page-Dy0JTS2G.js} +1 -1
- package/dist/assets/{life-force-workspace-B1fYSXRC.js → life-force-workspace-OfyB9HJM.js} +1 -1
- package/dist/assets/{metric-tile-DX6TclqM.js → metric-tile-DKpo-8xw.js} +1 -1
- package/dist/assets/{movement-page-6HP6nGJx.js → movement-page-Bg_T_Stx.js} +1 -1
- package/dist/assets/{note-markdown-DiW2-5d3.js → note-markdown-N-uxD3Xt.js} +1 -1
- package/dist/assets/{note-tags-input-DDLXf54U.js → note-tags-input-Cdu7wiw6.js} +1 -1
- package/dist/assets/{notes-page-BuguDjhz.js → notes-page-CKXnF_KU.js} +1 -1
- package/dist/assets/{open-in-graph-button-Cg5VrKsC.js → open-in-graph-button-IXe9SGth.js} +1 -1
- package/dist/assets/{orbit-map-GD05-0oS.js → orbit-map-Dzi6KliQ.js} +1 -1
- package/dist/assets/{overview-page-DuOs2OCB.js → overview-page-1miYqaVS.js} +1 -1
- package/dist/assets/{page-hero-CQWo1Mm_.js → page-hero-DRy5b2MU.js} +1 -1
- package/dist/assets/{pill-cluster-BJogDRDJ.js → pill-cluster-C9QczVJ2.js} +1 -1
- package/dist/assets/{preference-entity-handoff-button-D4WAs9pC.js → preference-entity-handoff-button-5PzUn42S.js} +1 -1
- package/dist/assets/{preferences-page-BaJTMU1I.js → preferences-page-DtNaF5Q3.js} +1 -1
- package/dist/assets/{project-collections-DvaX20q_.js → project-collections-xPz2mlRr.js} +1 -1
- package/dist/assets/{project-detail-page-drPIFZGb.js → project-detail-page-BXK5-4xW.js} +1 -1
- package/dist/assets/{project-management-hierarchy-page-BUbRXvny.js → project-management-hierarchy-page-DtRpMABw.js} +1 -1
- package/dist/assets/{project-management-section-nav-C2Ud8Zdd.js → project-management-section-nav-P3ixzPa-.js} +1 -1
- package/dist/assets/{projects-page-BGzEZUtg.js → projects-page-C5ViRuf4.js} +1 -1
- package/dist/assets/{psyche-behaviors-page-Dmm_Io9D.js → psyche-behaviors-page-Dco46sC4.js} +1 -1
- package/dist/assets/{psyche-flashcards-page-BgNKJ6QJ.js → psyche-flashcards-page-ZcoEB8gV.js} +1 -1
- package/dist/assets/{psyche-goal-map-page-DXJs98Vr.js → psyche-goal-map-page-CLBAQOI0.js} +1 -1
- package/dist/assets/{psyche-graph-CFgs_Bqc.js → psyche-graph-k4tX2tdp.js} +1 -1
- package/dist/assets/{psyche-metrics-page-zYTJDbyZ.js → psyche-metrics-page-CuR9oqEy.js} +1 -1
- package/dist/assets/{psyche-mode-guide-page-XPgRfCOf.js → psyche-mode-guide-page-hIVXcCnE.js} +1 -1
- package/dist/assets/{psyche-modes-page-B-GA8oRF.js → psyche-modes-page-0lYtBlhO.js} +1 -1
- package/dist/assets/{psyche-page--r6a3e1t.js → psyche-page-VZ9k9ISp.js} +1 -1
- package/dist/assets/{psyche-patterns-page-BM5-3bMm.js → psyche-patterns-page-gx5nmdGq.js} +1 -1
- package/dist/assets/{psyche-questionnaire-builder-page-CJshQ-mg.js → psyche-questionnaire-builder-page-Bn0TOISd.js} +1 -1
- package/dist/assets/{psyche-questionnaire-detail-page-USmR5G5A.js → psyche-questionnaire-detail-page-CmVzSd_s.js} +1 -1
- package/dist/assets/{psyche-questionnaire-run-detail-page-D7iBCmTi.js → psyche-questionnaire-run-detail-page-BsMbmXCG.js} +1 -1
- package/dist/assets/{psyche-questionnaire-run-page-Cpil-kDh.js → psyche-questionnaire-run-page-CgkRL2vi.js} +1 -1
- package/dist/assets/{psyche-questionnaires-page-C-_y3VwS.js → psyche-questionnaires-page-D7V8uLXM.js} +1 -1
- package/dist/assets/{psyche-report-detail-page--dkSPRaj.js → psyche-report-detail-page-OlFq57eL.js} +1 -1
- package/dist/assets/{psyche-reports-page-CUaOXmIN.js → psyche-reports-page-dVUZjna1.js} +1 -1
- package/dist/assets/{psyche-schemas-beliefs-page-BX6xaap3.js → psyche-schemas-beliefs-page-BCgc8FUd.js} +1 -1
- package/dist/assets/{psyche-screen-time-page-CAAI4mD7.js → psyche-screen-time-page-B_6BT_WN.js} +1 -1
- package/dist/assets/{psyche-self-observation-page-BZ6FLuwa.js → psyche-self-observation-page-CEG5mluK.js} +1 -1
- package/dist/assets/{psyche-values-page-yEV6MGt8.js → psyche-values-page-DRbRfEd6.js} +1 -1
- package/dist/assets/{report-chain-fields-fZ8Xd4H6.js → report-chain-fields-CALCV3V5.js} +1 -1
- package/dist/assets/{rewards-page-C2HQjIAf.js → rewards-page-DmC4R_Ps.js} +1 -1
- package/dist/assets/{scheduling-rules-editor-BHOpHOrV.js → scheduling-rules-editor-D02s70hr.js} +1 -1
- package/dist/assets/{schema-badge-DyKbxb51.js → schema-badge-BZO-qNhO.js} +1 -1
- package/dist/assets/{select-menu-BX-pZNqL.js → select-menu-fYyreSdQ.js} +1 -1
- package/dist/assets/{settings-agents-page-VuYXTiyc.js → settings-agents-page-C_v_hMJF.js} +1 -1
- package/dist/assets/{settings-bin-page-BNzvYaOk.js → settings-bin-page-DY5bg81n.js} +1 -1
- package/dist/assets/{settings-calendar-page-CjSFB53S.js → settings-calendar-page-D1CzE6cg.js} +1 -1
- package/dist/assets/{settings-data-page-CGSlryuI.js → settings-data-page-CHRQFU9H.js} +1 -1
- package/dist/assets/{settings-logs-page-BTK5fine.js → settings-logs-page-B04pUwEv.js} +1 -1
- package/dist/assets/{settings-mobile-page-CRaObOGo.js → settings-mobile-page-D9kTlYDS.js} +1 -1
- package/dist/assets/{settings-models-page-DFshpYF8.js → settings-models-page-D26270R2.js} +1 -1
- package/dist/assets/{settings-page-BP81Mb5R.js → settings-page-DYDTFlnv.js} +1 -1
- package/dist/assets/{settings-rewards-page-CDJ1PH2G.js → settings-rewards-page-cl4vqqO_.js} +1 -1
- package/dist/assets/{settings-section-nav-CCFm27r2.js → settings-section-nav-DSOuht_F.js} +1 -1
- package/dist/assets/{settings-users-page-TdUocFPa.js → settings-users-page-BU79JB_T.js} +1 -1
- package/dist/assets/{settings-wiki-page-B2zX0QQG.js → settings-wiki-page-DwAUlyA3.js} +1 -1
- package/dist/assets/{sleep-page-cI1GMVzk.js → sleep-page-D8NbdhyS.js} +1 -1
- package/dist/assets/{sports-page-06LTqp0V.js → sports-page-CV4Cnzwn.js} +1 -1
- package/dist/assets/{strategies-page-DXP9Kx8s.js → strategies-page-C4qvXnql.js} +1 -1
- package/dist/assets/{strategy-detail-page-D6mx_Mik.js → strategy-detail-page-DJLo5rfy.js} +1 -1
- package/dist/assets/{strategy-dialog-BvzomTaF.js → strategy-dialog-D3AuUlVz.js} +1 -1
- package/dist/assets/{task-detail-page-BIWIggdp.js → task-detail-page-z-9u9rF0.js} +1 -1
- package/dist/assets/{timebox-planning-dialog-CaCnoslG.js → timebox-planning-dialog-DB6FLqmI.js} +1 -1
- package/dist/assets/{today-page-DO2mRPT2.js → today-page-BKlu6gx5.js} +1 -1
- package/dist/assets/{training-load-page-CyZ0mlEr.js → training-load-page-CyJQqo_3.js} +1 -1
- package/dist/assets/{vitals-page-BQvEjTc6.js → vitals-page-qre17Nw8.js} +1 -1
- package/dist/assets/{weekly-review-page-Tp6Q9CRj.js → weekly-review-page-Cz4vkRcx.js} +1 -1
- package/dist/assets/weight-loss-page-BQrnOI0y.js +1 -0
- package/dist/assets/{wiki-article-markdown-DQYohmW2.js → wiki-article-markdown-DdiR2TJE.js} +1 -1
- package/dist/assets/{wiki-editor-page-Dem_3eZv.js → wiki-editor-page-DqwoqVFb.js} +1 -1
- package/dist/assets/{wiki-ingest-history-page-BxoOcCoJ.js → wiki-ingest-history-page--evBLbOw.js} +1 -1
- package/dist/assets/{wiki-ingest-modal-DhguKk3J.js → wiki-ingest-modal--ohzFnj2.js} +1 -1
- package/dist/assets/{wiki-page-BLRxVXkl.js → wiki-page-B_VJFBPA.js} +1 -1
- package/dist/assets/{workbench-flow-page-DqMkCCTy.js → workbench-flow-page-Du62mtJU.js} +1 -1
- package/dist/assets/{workbench-page-BWd02wPw.js → workbench-page-4MKr3iRm.js} +1 -1
- package/dist/assets/{workout-detail-page-BD8u7GyL.js → workout-detail-page-DfUbYYw1.js} +1 -1
- package/dist/index.html +1 -1
- package/dist/server/server/src/watch-mobile.js +22 -10
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/dist/assets/weight-loss-page-BBzlhLVV.js +0 -1
package/dist/assets/{timebox-planning-dialog-CaCnoslG.js → timebox-planning-dialog-DB6FLqmI.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as y,j as e,aG as Ae}from"./vendor-DHkYh85p.js";import{S as Pe}from"./scheduling-rules-editor-BHOpHOrV.js";import{aS as De,C as ge,B as U,K as ee,k as Q,F as w,c as m,h as Y,I as D,j as Ce,d as te,Q as Ie,cM as Re,N as Me}from"./index-BHTUu_4M.js";import{i as fe}from"./state-B-4sS1xO.js";import{f as Ee}from"./calendar-ui-Cy1XRwzV.js";function qe({open:s,onOpenChange:o,tasks:h,onSave:x}){const c=y.useMemo(()=>h.filter(p=>p.status!=="done"),[h]),[C,b]=y.useState("");y.useEffect(()=>{if(s){if(c.length===0){b("");return}b(p=>p&&c.some(g=>g.id===p)?p:c[0].id)}},[c,s]);const N=c.find(p=>p.id===C)??null;return e.jsx(De,{open:s,onOpenChange:o,eyebrow:"Calendar",title:"Adjust task scheduling rules",description:"Choose a task, then tell Forge which work blocks, calendar conditions, or keywords should allow or block that work.",children:e.jsxs("div",{className:"grid gap-4",children:[e.jsx(ge,{className:"rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(18,28,38,0.98),rgba(11,17,28,0.98))]",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"rounded-[18px] bg-[var(--primary)]/14 p-3 text-[var(--primary)]",children:e.jsx(Ae,{className:"size-4"})}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:"Guided rule editing"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:"Use this when a task should only run in certain blocks such as Secondary Activity, or should stay blocked during clinic, rest, or other provider events."})]})]})}),c.length>0?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/58",children:"Task"}),e.jsx("select",{value:C,onChange:p=>b(p.target.value),className:"rounded-[22px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:c.map(p=>e.jsx("option",{value:p.id,children:p.title},p.id))})]}),N?e.jsx(Pe,{title:"Task rules",subtitle:"These rules are saved directly on the task. They drive blocked-now checks and future timebox recommendations.",initialRules:N.schedulingRules,initialPlannedDurationSeconds:N.plannedDurationSeconds,allowPlannedDuration:!0,saveLabel:"Save task rules",onSave:async({schedulingRules:p,plannedDurationSeconds:g})=>{await x({taskId:N.id,schedulingRules:p,plannedDurationSeconds:g===void 0?N.plannedDurationSeconds:g??null}),o(!1)}}):null]}):e.jsxs(ge,{className:"rounded-[28px] border border-white/8 bg-white/[0.04]",children:[e.jsx("div",{className:"font-medium text-white",children:"No schedulable tasks yet"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:"Create or reopen a task first, then come back here to define work-block and calendar eligibility."}),e.jsx("div",{className:"mt-4",children:e.jsx(U,{variant:"secondary",onClick:()=>o(!1),children:"Close"})})]})]})})}function M(s){return s.slice(0,10)}function Fe(s){return new Date(`${s}T00:00:00`).toISOString()}function Ke(s){return new Date(`${s}T23:59:59.999`).toISOString()}function ae(s,o,h){return s<o?o:s>h?h:s}function we(s,o){const h=M(s),x=M(o),c=new Date(`${h}T12:00:00`);return c.setDate(c.getDate()+1),ae(M(c.toISOString()),h,x)}function ye(s){return String(s).padStart(2,"0")}function q(s){return`${ye(s.getHours())}:${ye(s.getMinutes())}`}function ve(s,o){if(!s||!o)return null;const h=new Date(`${s}T${o}:00`);return Number.isNaN(h.getTime())?null:h}function G(s,o,h){if(h){const b=new Date(h.startsAt),N=new Date(h.endsAt);return{startTime:q(b),endTime:q(N)}}const x=new Date(`${s}T09:00:00`),c=Math.max(1800,Math.min(o??3600,360*60)),C=new Date(x.getTime()+c*1e3);return{startTime:q(x),endTime:q(C)}}function je(s,o){return`${new Date(s).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})} - ${new Date(o).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`}function z(s,o){return`${Ee(new Date(s))} · ${je(s,o)}`}function T({title:s,subtitle:o,emptyLabel:h,children:x}){const c=Array.isArray(x)?x:x?[x]:[];return e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:s}),e.jsx("div",{className:"mt-1 text-sm text-white/54",children:o})]}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:c.length})]}),e.jsx("div",{className:"mt-3 grid gap-2",children:c.length>0?c:e.jsx("div",{className:"rounded-[18px] border border-dashed border-white/8 bg-white/[0.03] px-3 py-3 text-sm text-white/46",children:h})})]})}function He({event:s}){return e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] px-3 py-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:s.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/70",children:s.availability})]}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:z(s.startAt,s.endAt)})]})}function Le({block:s}){return e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] px-3 py-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:s.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/70",children:s.blockingState})]}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:z(s.startAt,s.endAt)})]})}function $e({timebox:s}){const o=ee(s);return e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] px-3 py-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:s.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/70",children:s.source})]}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:z(s.startsAt,s.endsAt)}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:te(o.rateApPerHour)}),e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:Y(o.totalAp)})]})]})}function Ge({open:s,onOpenChange:o,tasks:h,from:x,to:c,onCreateTimebox:C,onUpdateTimebox:b,onDeleteTimebox:N,initialTaskId:p,lockedTaskId:g,editingTimebox:t,userIds:se}){var ce,ue,he,me,pe,xe;const E=!!t,v=y.useMemo(()=>{const a=g??(t==null?void 0:t.taskId)??null,d=h.filter(u=>u.status!=="done"||u.id===a);if(!a)return d;const r=d.find(u=>u.id===a);return r?[r]:[]},[t==null?void 0:t.taskId,g,h]),F=M(x),K=M(c),re=t?ae(M(t.startsAt),F,K):we(x,c),ne=g??(t==null?void 0:t.taskId)??p??((ce=v[0])==null?void 0:ce.id)??"",H=v.find(a=>a.id===ne)??v[0]??null,le=G(re,H==null?void 0:H.plannedDurationSeconds,t?{startsAt:t.startsAt,endsAt:t.endsAt}:null),[i,B]=y.useState({taskId:ne,preferredDate:re,plannerMode:t?"manual":"suggested",selectedTimeboxId:"",activityPresetKey:((ue=t==null?void 0:t.actionProfile)==null?void 0:ue.profileKey)??"task_inherited",customSustainRateApPerHour:((he=t==null?void 0:t.actionProfile)==null?void 0:he.sourceMethod)==="manual"?t.actionProfile.sustainRateApPerHour:null,manualStartTime:le.startTime,manualEndTime:le.endTime,manualTitle:(t==null?void 0:t.title)??(H==null?void 0:H.title)??"",overrideReason:(t==null?void 0:t.overrideReason)??""}),[be,j]=y.useState(null),[Ne,W]=y.useState(!1),[Se,ie]=y.useState(!1);y.useEffect(()=>{var R,$,_;if(!s)return;const a=g??p??((R=v[0])==null?void 0:R.id)??"",d=(t==null?void 0:t.taskId)??a,r=v.find(f=>f.id===d)??v[0]??null,u=t?ae(M(t.startsAt),F,K):we(x,c),n=G(u,r==null?void 0:r.plannedDurationSeconds,t?{startsAt:t.startsAt,endsAt:t.endsAt}:null);j(null),B({taskId:d,preferredDate:u,plannerMode:t?"manual":"suggested",selectedTimeboxId:"",activityPresetKey:(($=t==null?void 0:t.actionProfile)==null?void 0:$.profileKey)??"task_inherited",customSustainRateApPerHour:((_=t==null?void 0:t.actionProfile)==null?void 0:_.sourceMethod)==="manual"?t.actionProfile.sustainRateApPerHour:null,manualStartTime:n.startTime,manualEndTime:n.endTime,manualTitle:(t==null?void 0:t.title)??(r==null?void 0:r.title)??"",overrideReason:(t==null?void 0:t.overrideReason)??""})},[v,t,x,p,g,K,F,s,c]);const l=v.find(a=>a.id===i.taskId)??null,A=y.useMemo(()=>({from:Fe(i.preferredDate),to:Ke(i.preferredDate)}),[i.preferredDate]),P=fe({queryKey:["forge-calendar-suggestions-dialog",i.taskId,A.from,A.to],queryFn:()=>Re({taskId:i.taskId,from:A.from,to:A.to,limit:8}),enabled:s&&i.taskId.length>0}),J=fe({queryKey:["forge-calendar-timebox-dialog-day",A.from,A.to,...se??[]],queryFn:()=>Me({from:A.from,to:A.to,userIds:se}),enabled:s});y.useEffect(()=>{var d;if(!s)return;const a=((d=P.data)==null?void 0:d.timeboxes)??[];if(!a.length){B(r=>r.selectedTimeboxId?{...r,selectedTimeboxId:""}:r);return}B(r=>r.selectedTimeboxId&&a.some(u=>u.id===r.selectedTimeboxId)?r:{...r,selectedTimeboxId:a[0].id})},[s,P.data]);const k=(me=J.data)==null?void 0:me.calendar,X=(k==null?void 0:k.events)??[],Z=(k==null?void 0:k.workBlockInstances)??[],V=(k==null?void 0:k.timeboxes)??[],L=(((pe=P.data)==null?void 0:pe.timeboxes)??[]).find(a=>a.id===i.selectedTimeboxId),S=ve(i.preferredDate,i.manualStartTime),I=ve(i.preferredDate,i.manualEndTime),O=S&&I?ee({startsAt:S.toISOString(),endsAt:I.toISOString(),actionProfile:i.customSustainRateApPerHour!==null||i.activityPresetKey!=="task_inherited"?{id:"manual-preview",profileKey:"manual-preview",title:i.manualTitle||(l==null?void 0:l.title)||"Manual timebox",entityType:"task_timebox",mode:"container",startupAp:0,totalCostAp:0,expectedDurationSeconds:null,sustainRateApPerHour:i.customSustainRateApPerHour??((xe=Q().find(a=>a.key===i.activityPresetKey))==null?void 0:xe.defaultRateApPerHour)??100/24,demandWeights:{activation:.1,focus:.3,vigor:.1,composure:.1,flow:.4},doubleCountPolicy:"container_only",sourceMethod:"manual",costBand:"light",recoveryEffect:0,metadata:{},createdAt:S.toISOString(),updatedAt:S.toISOString()}:null}):null,oe=E?"Review the task tied to this scheduled block":g?"Review the task you are planning":"Choose the task you want to place into the calendar",de=E?"The timebox stays linked to this task. Update the day, hours, title, or AP profile without leaving the planning flow.":g?"Forge will use this task's current duration target and scheduling rules while it looks for viable slots.":"Forge will use the task's current planned duration and scheduling rules when it searches for valid slots.",ke=y.useMemo(()=>[{id:"task",eyebrow:"Planning",title:oe,description:de,render:(a,d)=>e.jsxs("div",{className:"grid gap-4",children:[g?null:e.jsx(w,{label:"Task",children:e.jsx("select",{value:a.taskId,onChange:r=>(()=>{const u=v.find(R=>R.id===r.target.value),n=G(a.preferredDate,u==null?void 0:u.plannedDurationSeconds);d({taskId:r.target.value,selectedTimeboxId:"",activityPresetKey:"task_inherited",customSustainRateApPerHour:null,manualStartTime:n.startTime,manualEndTime:n.endTime,manualTitle:(u==null?void 0:u.title)??a.manualTitle})})(),className:"rounded-[22px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:v.map(r=>e.jsx("option",{value:r.id,children:r.title},r.id))})}),l?e.jsxs("div",{className:"rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(28,36,54,0.78),rgba(15,22,34,0.78))] p-5 shadow-[0_18px_40px_rgba(5,12,24,0.22)]",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Time Box"}),e.jsx("div",{className:"mt-2 font-display text-[1.4rem] leading-tight text-white",children:l.title})]}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:l.status})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:l.plannedDurationSeconds?`${Math.round(l.plannedDurationSeconds/60)} min target`:"No duration yet"}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:l.schedulingRules?"Task-specific rules":"Uses project rules"}),e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[l.points," xp"]}),l.plannedDurationSeconds?e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[Y(l.plannedDurationSeconds/3600/24*100)," ","target load"]}):null]}),e.jsx("p",{className:"mt-4 text-sm leading-6 text-white/60",children:"Pick a day first, then either accept one of Forge's suggested slots or set the block manually."}),E&&t&&N?e.jsxs("div",{className:"mt-4 flex flex-wrap items-center justify-between gap-3 rounded-[20px] border border-rose-400/18 bg-rose-400/8 px-4 py-3",children:[e.jsx("div",{className:"text-sm leading-6 text-rose-100/84",children:"Remove this planned timebox if you no longer want it in the calendar."}),e.jsx(U,{type:"button",variant:"ghost",className:"text-rose-100 hover:bg-rose-500/12",pending:Se,pendingLabel:"Deleting",onClick:()=>void(async()=>{j(null),ie(!0);try{await N(t.id),o(!1)}catch(r){j(r instanceof Error?r.message:"Forge could not delete this timebox.")}finally{ie(!1)}})(),children:"Delete timebox"})]}):null]}):null]})},{id:"day",eyebrow:"Calendar",title:"Choose the day and review what is already there",description:"Forge reads the real day first so the timebox stays grounded in your provider events, work blocks, and already-planned work.",render:(a,d)=>e.jsx("div",{className:"grid gap-5",children:e.jsxs("div",{className:"grid gap-4 lg:grid-cols-[minmax(0,16rem)_minmax(0,1fr)]",children:[e.jsxs("div",{className:"grid gap-4",children:[e.jsx(w,{label:"Date",description:"Choose the day you want to protect for this task.",children:e.jsx(D,{type:"date",min:F,max:K,value:a.preferredDate,onChange:r=>{const u=G(r.target.value,l==null?void 0:l.plannedDurationSeconds,t?{startsAt:`${r.target.value}T${a.manualStartTime}:00`,endsAt:`${r.target.value}T${a.manualEndTime}:00`}:null);d({preferredDate:r.target.value,selectedTimeboxId:"",manualStartTime:u.startTime,manualEndTime:u.endTime})}})}),e.jsx(w,{label:"Planning style",description:"Take Forge's slot recommendation when it fits, or set the block yourself.",children:e.jsx(Ce,{value:a.plannerMode,onChange:r=>d({plannerMode:r}),options:[{value:"suggested",label:"Use suggestions",description:"Forge proposes slots that fit the task rules and the selected day."},{value:"manual",label:"Set it manually",description:"You choose the exact start and end time yourself."}]})})]}),e.jsxs("div",{className:"rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(21,31,44,0.86),rgba(11,17,28,0.86))] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Selected day"}),e.jsx("div",{className:"mt-2 font-display text-[1.3rem] leading-tight text-white",children:a.preferredDate?new Date(`${a.preferredDate}T12:00:00`).toLocaleDateString([],{weekday:"long",month:"long",day:"numeric"}):"Choose a day"})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[X.length," events"]}),e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[Z.length," work blocks"]}),e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[V.length," timeboxes"]})]})]}),e.jsx("p",{className:"mt-3 text-sm leading-6 text-white/58",children:"This is the context Forge will use while recommending a slot. You can still place the block manually if you want something more exact."}),J.isLoading?e.jsx("div",{className:"mt-4 rounded-[18px] border border-white/8 bg-white/[0.04] px-4 py-4 text-sm text-white/56",children:"Loading the selected day…"}):e.jsxs("div",{className:"mt-4 grid gap-4 xl:grid-cols-3",children:[e.jsx(T,{title:"Provider events",subtitle:"Busy or free events already on the day.",emptyLabel:"No mirrored events on this day.",children:X.slice(0,4).map(r=>e.jsx(He,{event:r},r.id))}),e.jsx(T,{title:"Work blocks",subtitle:"Recurring allowed or blocked containers.",emptyLabel:"No work blocks land on this day.",children:Z.slice(0,4).map(r=>e.jsx(Le,{block:r},r.id))}),e.jsx(T,{title:"Planned timeboxes",subtitle:"Existing owned work already placed there.",emptyLabel:"No other planned timeboxes yet.",children:V.slice(0,4).map(r=>e.jsx($e,{timebox:r},r.id))})]})]})]})})},{id:"slot",eyebrow:i.plannerMode==="suggested"?"Suggestion":"Manual",title:i.plannerMode==="suggested"?"Choose one of Forge's suggested slots":"Set the exact timebox yourself",description:i.plannerMode==="suggested"?"Forge proposes slots that fit the selected day, the task rules, and the current calendar picture.":"Use manual mode when the right block is obvious to you or when you want to place the timebox despite imperfect recommendations.",render:(a,d)=>{var u;if(a.plannerMode==="manual")return e.jsxs("div",{className:"grid gap-5",children:[e.jsxs("div",{className:"grid gap-4 md:grid-cols-3",children:[e.jsx(w,{label:"Day",description:"Pick the day for the block. Forge defaults to a future day, but you can move it.",children:e.jsx(D,{type:"date",min:F,max:K,value:a.preferredDate,onChange:n=>d({preferredDate:n.target.value})})}),e.jsx(w,{label:"Start time",description:"Choose when the protected work block should begin.",children:e.jsx(D,{type:"time",step:300,value:a.manualStartTime,onChange:n=>d({manualStartTime:n.target.value})})}),e.jsx(w,{label:"End time",description:"Choose when the work block should end.",children:e.jsx(D,{type:"time",step:300,value:a.manualEndTime,onChange:n=>d({manualEndTime:n.target.value})})})]}),e.jsx(w,{label:"Title",description:"By default Forge uses the task title. Tighten it only if a shorter calendar label would help.",children:e.jsx(D,{value:a.manualTitle,onChange:n=>d({manualTitle:n.target.value}),placeholder:(l==null?void 0:l.title)??"Task timebox"})}),e.jsx(w,{label:"Override reason",description:"Optional. Add a short reason only if you are intentionally placing the block despite the normal rules or calendar shape.",children:e.jsx(D,{value:a.overrideReason,onChange:n=>d({overrideReason:n.target.value}),placeholder:"Protected writing block before clinic."})}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsx(w,{label:"Activity profile",children:e.jsx("select",{value:a.activityPresetKey??"task_inherited",onChange:n=>d({activityPresetKey:n.target.value}),className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:Q().map(n=>e.jsx("option",{value:n.key,children:n.label},n.key))})}),e.jsx(w,{label:"Custom AP per hour",children:e.jsx(D,{type:"number",min:0,step:.5,value:a.customSustainRateApPerHour??"",onChange:n=>d({customSustainRateApPerHour:n.target.value.trim()===""?null:Number(n.target.value)}),placeholder:"Leave empty to use the activity profile"})})]}),e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:a.manualTitle||(l==null?void 0:l.title)||"Manual timebox"}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:S&&I?`${S.toLocaleDateString([],{weekday:"long",month:"short",day:"numeric"})} · ${je(S.toISOString(),I.toISOString())}`:"Choose a start and end time."})]}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:"manual"})]}),O?e.jsxs("div",{className:"mt-3 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:te(O.rateApPerHour)}),e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:Y(O.totalAp)})]}):null]})]});const r=((u=P.data)==null?void 0:u.timeboxes)??[];return P.isLoading?e.jsx("div",{className:"text-sm text-white/62",children:"Looking for valid slots on the selected day…"}):r.length?e.jsx("div",{className:"grid gap-3",children:r.map(n=>{var _;const R=a.selectedTimeboxId===n.id,$=ee({...n,actionProfile:a.customSustainRateApPerHour!==null||a.activityPresetKey!=="task_inherited"?{id:"suggested-preview",profileKey:"suggested-preview",title:n.title,entityType:"task_timebox",mode:"container",startupAp:0,totalCostAp:0,expectedDurationSeconds:null,sustainRateApPerHour:a.customSustainRateApPerHour??((_=Q().find(f=>f.key===a.activityPresetKey))==null?void 0:_.defaultRateApPerHour)??100/24,demandWeights:{activation:.1,focus:.3,vigor:.1,composure:.1,flow:.4},doubleCountPolicy:"container_only",sourceMethod:"manual",costBand:"light",recoveryEffect:0,metadata:{},createdAt:n.startsAt,updatedAt:n.startsAt}:null});return e.jsxs("button",{type:"button",onClick:()=>d({selectedTimeboxId:n.id}),className:`rounded-[24px] border px-4 py-4 text-left transition ${R?"border-[rgba(192,193,255,0.28)] bg-[rgba(192,193,255,0.14)] text-white shadow-[0_18px_36px_rgba(5,12,24,0.24)]":"border-white/8 bg-white/[0.04] text-white/72 hover:bg-white/[0.07]"}`,children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium",children:n.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/76",children:n.source})]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/58",children:z(n.startsAt,n.endsAt)}),e.jsxs("div",{className:"mt-3 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:te($.rateApPerHour)}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:Y($.totalAp)})]}),R?e.jsxs("div",{className:"mt-4 grid gap-4 md:grid-cols-2",children:[e.jsx(w,{label:"Activity profile",children:e.jsx("select",{value:a.activityPresetKey??"task_inherited",onChange:f=>d({activityPresetKey:f.target.value}),className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:Q().map(f=>e.jsx("option",{value:f.key,children:f.label},f.key))})}),e.jsx(w,{label:"Custom AP per hour",children:e.jsx(D,{type:"number",min:0,step:.5,value:a.customSustainRateApPerHour??"",onChange:f=>d({customSustainRateApPerHour:f.target.value.trim()===""?null:Number(f.target.value)}),placeholder:"Leave empty to use the activity profile"})})]}):null]},n.id)})}):e.jsxs("div",{className:"grid gap-3",children:[e.jsx("div",{className:"rounded-[24px] border border-amber-400/20 bg-amber-400/10 px-4 py-4 text-sm leading-6 text-amber-100/86",children:"Forge could not find a valid slot on this day. Try another day, adjust the task rules, or switch to manual placement if you already know the right block."}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(U,{variant:"secondary",onClick:()=>void P.refetch(),children:"Refresh suggestions"}),e.jsx(U,{variant:"secondary",onClick:()=>d({plannerMode:"manual"}),children:"Switch to manual"})]})]})}}],[v,J.isLoading,Z,X,V,i.plannerMode,t,x,g,K,O,F,l,P.data,P.isLoading,de,oe,c]);return e.jsx(Ie,{open:s,onOpenChange:o,eyebrow:"Calendar",title:E?"Edit timebox":"Plan work",description:E?"Update the day, hour range, title, and AP profile for this scheduled block without leaving the task or calendar view.":"Review the day, let Forge recommend valid slots, and place a real timebox on the task without leaving the detail view.",value:i,onChange:B,draftPersistenceKey:t?`calendar.timebox.${t.id}`:`calendar.timebox.new.${(l==null?void 0:l.id)??"unscoped"}`,steps:ke,submitLabel:E?"Save timebox":"Schedule timebox",pending:Ne,pendingLabel:"Scheduling",error:be,contentClassName:"md:w-[min(70rem,calc(100vw-1.5rem))]",onSubmit:async()=>{if(!l){j("Choose a task before scheduling a timebox.");return}if(i.plannerMode==="manual"){if(!S||!I){j("Choose a valid manual start and end time.");return}if(I<=S){j("The manual timebox needs an end time after the start time.");return}j(null),W(!0);try{const a={title:i.manualTitle.trim()||l.title,startsAt:S.toISOString(),endsAt:I.toISOString(),overrideReason:i.overrideReason.trim()||null,activityPresetKey:i.activityPresetKey,customSustainRateApPerHour:i.customSustainRateApPerHour};t&&b?await b(t.id,a):await C({taskId:l.id,projectId:l.projectId,...a,source:"manual"}),o(!1)}catch(a){j(a instanceof Error?a.message:"Forge could not create the manual timebox.")}finally{W(!1)}return}if(!L){j("Pick one suggested slot before scheduling the timebox.");return}j(null),W(!0);try{const a={title:L.title,startsAt:L.startsAt,endsAt:L.endsAt,activityPresetKey:i.activityPresetKey,customSustainRateApPerHour:i.customSustainRateApPerHour};t&&b?await b(t.id,a):await C({taskId:l.id,projectId:l.projectId,...a,source:L.source}),o(!1)}catch(a){j(a instanceof Error?a.message:"Forge could not create the selected timebox.")}finally{W(!1)}}})}export{qe as T,Ge as a};
|
|
1
|
+
import{r as y,j as e,aG as Ae}from"./vendor-DHkYh85p.js";import{S as Pe}from"./scheduling-rules-editor-D02s70hr.js";import{aS as De,C as ge,B as U,K as ee,k as Q,F as w,c as m,h as Y,I as D,j as Ce,d as te,Q as Ie,cM as Re,N as Me}from"./index-CF4J4R9L.js";import{i as fe}from"./state-B-4sS1xO.js";import{f as Ee}from"./calendar-ui-Cy1XRwzV.js";function qe({open:s,onOpenChange:o,tasks:h,onSave:x}){const c=y.useMemo(()=>h.filter(p=>p.status!=="done"),[h]),[C,b]=y.useState("");y.useEffect(()=>{if(s){if(c.length===0){b("");return}b(p=>p&&c.some(g=>g.id===p)?p:c[0].id)}},[c,s]);const N=c.find(p=>p.id===C)??null;return e.jsx(De,{open:s,onOpenChange:o,eyebrow:"Calendar",title:"Adjust task scheduling rules",description:"Choose a task, then tell Forge which work blocks, calendar conditions, or keywords should allow or block that work.",children:e.jsxs("div",{className:"grid gap-4",children:[e.jsx(ge,{className:"rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(18,28,38,0.98),rgba(11,17,28,0.98))]",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"rounded-[18px] bg-[var(--primary)]/14 p-3 text-[var(--primary)]",children:e.jsx(Ae,{className:"size-4"})}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:"Guided rule editing"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:"Use this when a task should only run in certain blocks such as Secondary Activity, or should stay blocked during clinic, rest, or other provider events."})]})]})}),c.length>0?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/58",children:"Task"}),e.jsx("select",{value:C,onChange:p=>b(p.target.value),className:"rounded-[22px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:c.map(p=>e.jsx("option",{value:p.id,children:p.title},p.id))})]}),N?e.jsx(Pe,{title:"Task rules",subtitle:"These rules are saved directly on the task. They drive blocked-now checks and future timebox recommendations.",initialRules:N.schedulingRules,initialPlannedDurationSeconds:N.plannedDurationSeconds,allowPlannedDuration:!0,saveLabel:"Save task rules",onSave:async({schedulingRules:p,plannedDurationSeconds:g})=>{await x({taskId:N.id,schedulingRules:p,plannedDurationSeconds:g===void 0?N.plannedDurationSeconds:g??null}),o(!1)}}):null]}):e.jsxs(ge,{className:"rounded-[28px] border border-white/8 bg-white/[0.04]",children:[e.jsx("div",{className:"font-medium text-white",children:"No schedulable tasks yet"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:"Create or reopen a task first, then come back here to define work-block and calendar eligibility."}),e.jsx("div",{className:"mt-4",children:e.jsx(U,{variant:"secondary",onClick:()=>o(!1),children:"Close"})})]})]})})}function M(s){return s.slice(0,10)}function Fe(s){return new Date(`${s}T00:00:00`).toISOString()}function Ke(s){return new Date(`${s}T23:59:59.999`).toISOString()}function ae(s,o,h){return s<o?o:s>h?h:s}function we(s,o){const h=M(s),x=M(o),c=new Date(`${h}T12:00:00`);return c.setDate(c.getDate()+1),ae(M(c.toISOString()),h,x)}function ye(s){return String(s).padStart(2,"0")}function q(s){return`${ye(s.getHours())}:${ye(s.getMinutes())}`}function ve(s,o){if(!s||!o)return null;const h=new Date(`${s}T${o}:00`);return Number.isNaN(h.getTime())?null:h}function G(s,o,h){if(h){const b=new Date(h.startsAt),N=new Date(h.endsAt);return{startTime:q(b),endTime:q(N)}}const x=new Date(`${s}T09:00:00`),c=Math.max(1800,Math.min(o??3600,360*60)),C=new Date(x.getTime()+c*1e3);return{startTime:q(x),endTime:q(C)}}function je(s,o){return`${new Date(s).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})} - ${new Date(o).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`}function z(s,o){return`${Ee(new Date(s))} · ${je(s,o)}`}function T({title:s,subtitle:o,emptyLabel:h,children:x}){const c=Array.isArray(x)?x:x?[x]:[];return e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:s}),e.jsx("div",{className:"mt-1 text-sm text-white/54",children:o})]}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:c.length})]}),e.jsx("div",{className:"mt-3 grid gap-2",children:c.length>0?c:e.jsx("div",{className:"rounded-[18px] border border-dashed border-white/8 bg-white/[0.03] px-3 py-3 text-sm text-white/46",children:h})})]})}function He({event:s}){return e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] px-3 py-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:s.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/70",children:s.availability})]}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:z(s.startAt,s.endAt)})]})}function Le({block:s}){return e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] px-3 py-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:s.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/70",children:s.blockingState})]}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:z(s.startAt,s.endAt)})]})}function $e({timebox:s}){const o=ee(s);return e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] px-3 py-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:s.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/70",children:s.source})]}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:z(s.startsAt,s.endsAt)}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:te(o.rateApPerHour)}),e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:Y(o.totalAp)})]})]})}function Ge({open:s,onOpenChange:o,tasks:h,from:x,to:c,onCreateTimebox:C,onUpdateTimebox:b,onDeleteTimebox:N,initialTaskId:p,lockedTaskId:g,editingTimebox:t,userIds:se}){var ce,ue,he,me,pe,xe;const E=!!t,v=y.useMemo(()=>{const a=g??(t==null?void 0:t.taskId)??null,d=h.filter(u=>u.status!=="done"||u.id===a);if(!a)return d;const r=d.find(u=>u.id===a);return r?[r]:[]},[t==null?void 0:t.taskId,g,h]),F=M(x),K=M(c),re=t?ae(M(t.startsAt),F,K):we(x,c),ne=g??(t==null?void 0:t.taskId)??p??((ce=v[0])==null?void 0:ce.id)??"",H=v.find(a=>a.id===ne)??v[0]??null,le=G(re,H==null?void 0:H.plannedDurationSeconds,t?{startsAt:t.startsAt,endsAt:t.endsAt}:null),[i,B]=y.useState({taskId:ne,preferredDate:re,plannerMode:t?"manual":"suggested",selectedTimeboxId:"",activityPresetKey:((ue=t==null?void 0:t.actionProfile)==null?void 0:ue.profileKey)??"task_inherited",customSustainRateApPerHour:((he=t==null?void 0:t.actionProfile)==null?void 0:he.sourceMethod)==="manual"?t.actionProfile.sustainRateApPerHour:null,manualStartTime:le.startTime,manualEndTime:le.endTime,manualTitle:(t==null?void 0:t.title)??(H==null?void 0:H.title)??"",overrideReason:(t==null?void 0:t.overrideReason)??""}),[be,j]=y.useState(null),[Ne,W]=y.useState(!1),[Se,ie]=y.useState(!1);y.useEffect(()=>{var R,$,_;if(!s)return;const a=g??p??((R=v[0])==null?void 0:R.id)??"",d=(t==null?void 0:t.taskId)??a,r=v.find(f=>f.id===d)??v[0]??null,u=t?ae(M(t.startsAt),F,K):we(x,c),n=G(u,r==null?void 0:r.plannedDurationSeconds,t?{startsAt:t.startsAt,endsAt:t.endsAt}:null);j(null),B({taskId:d,preferredDate:u,plannerMode:t?"manual":"suggested",selectedTimeboxId:"",activityPresetKey:(($=t==null?void 0:t.actionProfile)==null?void 0:$.profileKey)??"task_inherited",customSustainRateApPerHour:((_=t==null?void 0:t.actionProfile)==null?void 0:_.sourceMethod)==="manual"?t.actionProfile.sustainRateApPerHour:null,manualStartTime:n.startTime,manualEndTime:n.endTime,manualTitle:(t==null?void 0:t.title)??(r==null?void 0:r.title)??"",overrideReason:(t==null?void 0:t.overrideReason)??""})},[v,t,x,p,g,K,F,s,c]);const l=v.find(a=>a.id===i.taskId)??null,A=y.useMemo(()=>({from:Fe(i.preferredDate),to:Ke(i.preferredDate)}),[i.preferredDate]),P=fe({queryKey:["forge-calendar-suggestions-dialog",i.taskId,A.from,A.to],queryFn:()=>Re({taskId:i.taskId,from:A.from,to:A.to,limit:8}),enabled:s&&i.taskId.length>0}),J=fe({queryKey:["forge-calendar-timebox-dialog-day",A.from,A.to,...se??[]],queryFn:()=>Me({from:A.from,to:A.to,userIds:se}),enabled:s});y.useEffect(()=>{var d;if(!s)return;const a=((d=P.data)==null?void 0:d.timeboxes)??[];if(!a.length){B(r=>r.selectedTimeboxId?{...r,selectedTimeboxId:""}:r);return}B(r=>r.selectedTimeboxId&&a.some(u=>u.id===r.selectedTimeboxId)?r:{...r,selectedTimeboxId:a[0].id})},[s,P.data]);const k=(me=J.data)==null?void 0:me.calendar,X=(k==null?void 0:k.events)??[],Z=(k==null?void 0:k.workBlockInstances)??[],V=(k==null?void 0:k.timeboxes)??[],L=(((pe=P.data)==null?void 0:pe.timeboxes)??[]).find(a=>a.id===i.selectedTimeboxId),S=ve(i.preferredDate,i.manualStartTime),I=ve(i.preferredDate,i.manualEndTime),O=S&&I?ee({startsAt:S.toISOString(),endsAt:I.toISOString(),actionProfile:i.customSustainRateApPerHour!==null||i.activityPresetKey!=="task_inherited"?{id:"manual-preview",profileKey:"manual-preview",title:i.manualTitle||(l==null?void 0:l.title)||"Manual timebox",entityType:"task_timebox",mode:"container",startupAp:0,totalCostAp:0,expectedDurationSeconds:null,sustainRateApPerHour:i.customSustainRateApPerHour??((xe=Q().find(a=>a.key===i.activityPresetKey))==null?void 0:xe.defaultRateApPerHour)??100/24,demandWeights:{activation:.1,focus:.3,vigor:.1,composure:.1,flow:.4},doubleCountPolicy:"container_only",sourceMethod:"manual",costBand:"light",recoveryEffect:0,metadata:{},createdAt:S.toISOString(),updatedAt:S.toISOString()}:null}):null,oe=E?"Review the task tied to this scheduled block":g?"Review the task you are planning":"Choose the task you want to place into the calendar",de=E?"The timebox stays linked to this task. Update the day, hours, title, or AP profile without leaving the planning flow.":g?"Forge will use this task's current duration target and scheduling rules while it looks for viable slots.":"Forge will use the task's current planned duration and scheduling rules when it searches for valid slots.",ke=y.useMemo(()=>[{id:"task",eyebrow:"Planning",title:oe,description:de,render:(a,d)=>e.jsxs("div",{className:"grid gap-4",children:[g?null:e.jsx(w,{label:"Task",children:e.jsx("select",{value:a.taskId,onChange:r=>(()=>{const u=v.find(R=>R.id===r.target.value),n=G(a.preferredDate,u==null?void 0:u.plannedDurationSeconds);d({taskId:r.target.value,selectedTimeboxId:"",activityPresetKey:"task_inherited",customSustainRateApPerHour:null,manualStartTime:n.startTime,manualEndTime:n.endTime,manualTitle:(u==null?void 0:u.title)??a.manualTitle})})(),className:"rounded-[22px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:v.map(r=>e.jsx("option",{value:r.id,children:r.title},r.id))})}),l?e.jsxs("div",{className:"rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(28,36,54,0.78),rgba(15,22,34,0.78))] p-5 shadow-[0_18px_40px_rgba(5,12,24,0.22)]",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Time Box"}),e.jsx("div",{className:"mt-2 font-display text-[1.4rem] leading-tight text-white",children:l.title})]}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:l.status})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:l.plannedDurationSeconds?`${Math.round(l.plannedDurationSeconds/60)} min target`:"No duration yet"}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:l.schedulingRules?"Task-specific rules":"Uses project rules"}),e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[l.points," xp"]}),l.plannedDurationSeconds?e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[Y(l.plannedDurationSeconds/3600/24*100)," ","target load"]}):null]}),e.jsx("p",{className:"mt-4 text-sm leading-6 text-white/60",children:"Pick a day first, then either accept one of Forge's suggested slots or set the block manually."}),E&&t&&N?e.jsxs("div",{className:"mt-4 flex flex-wrap items-center justify-between gap-3 rounded-[20px] border border-rose-400/18 bg-rose-400/8 px-4 py-3",children:[e.jsx("div",{className:"text-sm leading-6 text-rose-100/84",children:"Remove this planned timebox if you no longer want it in the calendar."}),e.jsx(U,{type:"button",variant:"ghost",className:"text-rose-100 hover:bg-rose-500/12",pending:Se,pendingLabel:"Deleting",onClick:()=>void(async()=>{j(null),ie(!0);try{await N(t.id),o(!1)}catch(r){j(r instanceof Error?r.message:"Forge could not delete this timebox.")}finally{ie(!1)}})(),children:"Delete timebox"})]}):null]}):null]})},{id:"day",eyebrow:"Calendar",title:"Choose the day and review what is already there",description:"Forge reads the real day first so the timebox stays grounded in your provider events, work blocks, and already-planned work.",render:(a,d)=>e.jsx("div",{className:"grid gap-5",children:e.jsxs("div",{className:"grid gap-4 lg:grid-cols-[minmax(0,16rem)_minmax(0,1fr)]",children:[e.jsxs("div",{className:"grid gap-4",children:[e.jsx(w,{label:"Date",description:"Choose the day you want to protect for this task.",children:e.jsx(D,{type:"date",min:F,max:K,value:a.preferredDate,onChange:r=>{const u=G(r.target.value,l==null?void 0:l.plannedDurationSeconds,t?{startsAt:`${r.target.value}T${a.manualStartTime}:00`,endsAt:`${r.target.value}T${a.manualEndTime}:00`}:null);d({preferredDate:r.target.value,selectedTimeboxId:"",manualStartTime:u.startTime,manualEndTime:u.endTime})}})}),e.jsx(w,{label:"Planning style",description:"Take Forge's slot recommendation when it fits, or set the block yourself.",children:e.jsx(Ce,{value:a.plannerMode,onChange:r=>d({plannerMode:r}),options:[{value:"suggested",label:"Use suggestions",description:"Forge proposes slots that fit the task rules and the selected day."},{value:"manual",label:"Set it manually",description:"You choose the exact start and end time yourself."}]})})]}),e.jsxs("div",{className:"rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(21,31,44,0.86),rgba(11,17,28,0.86))] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Selected day"}),e.jsx("div",{className:"mt-2 font-display text-[1.3rem] leading-tight text-white",children:a.preferredDate?new Date(`${a.preferredDate}T12:00:00`).toLocaleDateString([],{weekday:"long",month:"long",day:"numeric"}):"Choose a day"})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[X.length," events"]}),e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[Z.length," work blocks"]}),e.jsxs(m,{className:"bg-white/[0.08] text-white/74",children:[V.length," timeboxes"]})]})]}),e.jsx("p",{className:"mt-3 text-sm leading-6 text-white/58",children:"This is the context Forge will use while recommending a slot. You can still place the block manually if you want something more exact."}),J.isLoading?e.jsx("div",{className:"mt-4 rounded-[18px] border border-white/8 bg-white/[0.04] px-4 py-4 text-sm text-white/56",children:"Loading the selected day…"}):e.jsxs("div",{className:"mt-4 grid gap-4 xl:grid-cols-3",children:[e.jsx(T,{title:"Provider events",subtitle:"Busy or free events already on the day.",emptyLabel:"No mirrored events on this day.",children:X.slice(0,4).map(r=>e.jsx(He,{event:r},r.id))}),e.jsx(T,{title:"Work blocks",subtitle:"Recurring allowed or blocked containers.",emptyLabel:"No work blocks land on this day.",children:Z.slice(0,4).map(r=>e.jsx(Le,{block:r},r.id))}),e.jsx(T,{title:"Planned timeboxes",subtitle:"Existing owned work already placed there.",emptyLabel:"No other planned timeboxes yet.",children:V.slice(0,4).map(r=>e.jsx($e,{timebox:r},r.id))})]})]})]})})},{id:"slot",eyebrow:i.plannerMode==="suggested"?"Suggestion":"Manual",title:i.plannerMode==="suggested"?"Choose one of Forge's suggested slots":"Set the exact timebox yourself",description:i.plannerMode==="suggested"?"Forge proposes slots that fit the selected day, the task rules, and the current calendar picture.":"Use manual mode when the right block is obvious to you or when you want to place the timebox despite imperfect recommendations.",render:(a,d)=>{var u;if(a.plannerMode==="manual")return e.jsxs("div",{className:"grid gap-5",children:[e.jsxs("div",{className:"grid gap-4 md:grid-cols-3",children:[e.jsx(w,{label:"Day",description:"Pick the day for the block. Forge defaults to a future day, but you can move it.",children:e.jsx(D,{type:"date",min:F,max:K,value:a.preferredDate,onChange:n=>d({preferredDate:n.target.value})})}),e.jsx(w,{label:"Start time",description:"Choose when the protected work block should begin.",children:e.jsx(D,{type:"time",step:300,value:a.manualStartTime,onChange:n=>d({manualStartTime:n.target.value})})}),e.jsx(w,{label:"End time",description:"Choose when the work block should end.",children:e.jsx(D,{type:"time",step:300,value:a.manualEndTime,onChange:n=>d({manualEndTime:n.target.value})})})]}),e.jsx(w,{label:"Title",description:"By default Forge uses the task title. Tighten it only if a shorter calendar label would help.",children:e.jsx(D,{value:a.manualTitle,onChange:n=>d({manualTitle:n.target.value}),placeholder:(l==null?void 0:l.title)??"Task timebox"})}),e.jsx(w,{label:"Override reason",description:"Optional. Add a short reason only if you are intentionally placing the block despite the normal rules or calendar shape.",children:e.jsx(D,{value:a.overrideReason,onChange:n=>d({overrideReason:n.target.value}),placeholder:"Protected writing block before clinic."})}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsx(w,{label:"Activity profile",children:e.jsx("select",{value:a.activityPresetKey??"task_inherited",onChange:n=>d({activityPresetKey:n.target.value}),className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:Q().map(n=>e.jsx("option",{value:n.key,children:n.label},n.key))})}),e.jsx(w,{label:"Custom AP per hour",children:e.jsx(D,{type:"number",min:0,step:.5,value:a.customSustainRateApPerHour??"",onChange:n=>d({customSustainRateApPerHour:n.target.value.trim()===""?null:Number(n.target.value)}),placeholder:"Leave empty to use the activity profile"})})]}),e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:a.manualTitle||(l==null?void 0:l.title)||"Manual timebox"}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:S&&I?`${S.toLocaleDateString([],{weekday:"long",month:"short",day:"numeric"})} · ${je(S.toISOString(),I.toISOString())}`:"Choose a start and end time."})]}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:"manual"})]}),O?e.jsxs("div",{className:"mt-3 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:te(O.rateApPerHour)}),e.jsx(m,{className:"bg-white/[0.08] text-white/72",children:Y(O.totalAp)})]}):null]})]});const r=((u=P.data)==null?void 0:u.timeboxes)??[];return P.isLoading?e.jsx("div",{className:"text-sm text-white/62",children:"Looking for valid slots on the selected day…"}):r.length?e.jsx("div",{className:"grid gap-3",children:r.map(n=>{var _;const R=a.selectedTimeboxId===n.id,$=ee({...n,actionProfile:a.customSustainRateApPerHour!==null||a.activityPresetKey!=="task_inherited"?{id:"suggested-preview",profileKey:"suggested-preview",title:n.title,entityType:"task_timebox",mode:"container",startupAp:0,totalCostAp:0,expectedDurationSeconds:null,sustainRateApPerHour:a.customSustainRateApPerHour??((_=Q().find(f=>f.key===a.activityPresetKey))==null?void 0:_.defaultRateApPerHour)??100/24,demandWeights:{activation:.1,focus:.3,vigor:.1,composure:.1,flow:.4},doubleCountPolicy:"container_only",sourceMethod:"manual",costBand:"light",recoveryEffect:0,metadata:{},createdAt:n.startsAt,updatedAt:n.startsAt}:null});return e.jsxs("button",{type:"button",onClick:()=>d({selectedTimeboxId:n.id}),className:`rounded-[24px] border px-4 py-4 text-left transition ${R?"border-[rgba(192,193,255,0.28)] bg-[rgba(192,193,255,0.14)] text-white shadow-[0_18px_36px_rgba(5,12,24,0.24)]":"border-white/8 bg-white/[0.04] text-white/72 hover:bg-white/[0.07]"}`,children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium",children:n.title}),e.jsx(m,{className:"bg-white/[0.08] text-white/76",children:n.source})]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/58",children:z(n.startsAt,n.endsAt)}),e.jsxs("div",{className:"mt-3 flex flex-wrap gap-2",children:[e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:te($.rateApPerHour)}),e.jsx(m,{className:"bg-white/[0.08] text-white/74",children:Y($.totalAp)})]}),R?e.jsxs("div",{className:"mt-4 grid gap-4 md:grid-cols-2",children:[e.jsx(w,{label:"Activity profile",children:e.jsx("select",{value:a.activityPresetKey??"task_inherited",onChange:f=>d({activityPresetKey:f.target.value}),className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-[15px] text-white outline-none",children:Q().map(f=>e.jsx("option",{value:f.key,children:f.label},f.key))})}),e.jsx(w,{label:"Custom AP per hour",children:e.jsx(D,{type:"number",min:0,step:.5,value:a.customSustainRateApPerHour??"",onChange:f=>d({customSustainRateApPerHour:f.target.value.trim()===""?null:Number(f.target.value)}),placeholder:"Leave empty to use the activity profile"})})]}):null]},n.id)})}):e.jsxs("div",{className:"grid gap-3",children:[e.jsx("div",{className:"rounded-[24px] border border-amber-400/20 bg-amber-400/10 px-4 py-4 text-sm leading-6 text-amber-100/86",children:"Forge could not find a valid slot on this day. Try another day, adjust the task rules, or switch to manual placement if you already know the right block."}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(U,{variant:"secondary",onClick:()=>void P.refetch(),children:"Refresh suggestions"}),e.jsx(U,{variant:"secondary",onClick:()=>d({plannerMode:"manual"}),children:"Switch to manual"})]})]})}}],[v,J.isLoading,Z,X,V,i.plannerMode,t,x,g,K,O,F,l,P.data,P.isLoading,de,oe,c]);return e.jsx(Ie,{open:s,onOpenChange:o,eyebrow:"Calendar",title:E?"Edit timebox":"Plan work",description:E?"Update the day, hour range, title, and AP profile for this scheduled block without leaving the task or calendar view.":"Review the day, let Forge recommend valid slots, and place a real timebox on the task without leaving the detail view.",value:i,onChange:B,draftPersistenceKey:t?`calendar.timebox.${t.id}`:`calendar.timebox.new.${(l==null?void 0:l.id)??"unscoped"}`,steps:ke,submitLabel:E?"Save timebox":"Schedule timebox",pending:Ne,pendingLabel:"Scheduling",error:be,contentClassName:"md:w-[min(70rem,calc(100vw-1.5rem))]",onSubmit:async()=>{if(!l){j("Choose a task before scheduling a timebox.");return}if(i.plannerMode==="manual"){if(!S||!I){j("Choose a valid manual start and end time.");return}if(I<=S){j("The manual timebox needs an end time after the start time.");return}j(null),W(!0);try{const a={title:i.manualTitle.trim()||l.title,startsAt:S.toISOString(),endsAt:I.toISOString(),overrideReason:i.overrideReason.trim()||null,activityPresetKey:i.activityPresetKey,customSustainRateApPerHour:i.customSustainRateApPerHour};t&&b?await b(t.id,a):await C({taskId:l.id,projectId:l.projectId,...a,source:"manual"}),o(!1)}catch(a){j(a instanceof Error?a.message:"Forge could not create the manual timebox.")}finally{W(!1)}return}if(!L){j("Pick one suggested slot before scheduling the timebox.");return}j(null),W(!0);try{const a={title:L.title,startsAt:L.startsAt,endsAt:L.endsAt,activityPresetKey:i.activityPresetKey,customSustainRateApPerHour:i.customSustainRateApPerHour};t&&b?await b(t.id,a):await C({taskId:l.id,projectId:l.projectId,...a,source:L.source}),o(!1)}catch(a){j(a instanceof Error?a.message:"Forge could not create the selected timebox.")}finally{W(!1)}}})}export{qe as T,Ge as a};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e,aC as f,b8 as E,bB as b,bE as H,b5 as P,r as T,aV as B,cA as L}from"./vendor-DHkYh85p.js";import{i as X}from"./state-B-4sS1xO.js";import{A as _}from"./ai-surface-workspace-qgk_B57-.js";import{P as I,aq as C,c as x,_ as F,b as k,V as S,B as O,u as $,a as U,eR as M,eS as V,C as v,W as z,eT as q,eU as K,eV as Q,bG as G,bH as J,bI as Y,bJ as Z,bK as ee,N as te}from"./index-BHTUu_4M.js";import{E as W}from"./entity-note-count-link-BmGDB572.js";import{a as se}from"./life-force-workspace-B1fYSXRC.js";import{P as R}from"./page-hero-CQWo1Mm_.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";import"./floating-action-menu-CJkI2iFy.js";import"./charts-P7EVhIog.js";function D(s,t){return t.find(c=>c.id===s.goalId)??null}function ae(s,t){return s.tagIds.map(c=>t.find(o=>o.id===c)).filter(Boolean)}function ie(s,t){(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),t())}function ne(s,t){switch(s.status){case"backlog":return{label:t.backlog,action:"start",icon:b};case"focus":return{label:t.focus,action:"start",icon:b};case"in_progress":return{label:t.in_progress,nextStatus:"done",action:"move",icon:H};case"blocked":return{label:t.blocked,action:"start",icon:b};default:return null}}function re({tasks:s,timeline:t,goals:c,tags:o,notesSummaryByEntity:j,selectedTaskId:w,onSelectTask:r,onMove:p,onStartTask:u}){const{t:l,formatDate:y}=I(),N={backlog:l("common.dailyRunway.actionBacklog"),focus:l("common.dailyRunway.actionFocus"),in_progress:l("common.dailyRunway.actionProgress"),blocked:l("common.dailyRunway.actionBlocked")};return e.jsxs("div",{className:"grid min-w-0 gap-4 2xl:grid-cols-[minmax(0,1.3fr)_minmax(17rem,0.9fr)]",children:[e.jsxs("div",{className:"min-w-0 rounded-[24px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:l("common.dailyRunway.runwayEyebrow")}),e.jsx(C,{content:"These are the tasks that matter most for today. Click a card to open the task details. Use Start to begin work immediately."})]}),e.jsx("h4",{className:"mt-2 font-display text-2xl text-white",children:l("common.dailyRunway.runwayTitle")})]}),e.jsx(x,{className:"shrink-0 text-[var(--primary)]",children:l(s.length===1?"common.dailyRunway.prioritiesOne":"common.dailyRunway.prioritiesOther",{count:s.length})})]}),e.jsx("div",{className:"mt-4 grid min-w-0 gap-3",children:s.map((a,g)=>{const d=ne(a,N),i=ae(a,o).slice(0,2),n=D(a,c),h=w===a.id,A=F(j,"task",a.id).count;return e.jsxs("article",{role:"button",tabIndex:0,"aria-pressed":h,className:`grid w-full gap-3 rounded-[22px] px-4 py-4 text-left transition ${h?"bg-[linear-gradient(180deg,rgba(192,193,255,0.16),rgba(192,193,255,0.05))] shadow-[inset_0_0_0_1px_rgba(192,193,255,0.2)]":"bg-white/[0.03] hover:bg-white/[0.06]"}`,onClick:()=>r(a.id),onKeyDown:m=>ie(m,()=>r(a.id)),children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:l("common.dailyRunway.runwayItem",{index:g+1})}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[n?e.jsx(f,{to:`/goals/${n.id}`,className:"min-w-0 max-w-full transition hover:opacity-85",onClick:m=>m.stopPropagation(),children:e.jsx(k,{kind:"goal",label:n.title,compact:!0,gradient:!1})}):e.jsx(k,{kind:"goal",label:l("common.dailyRunway.unassigned"),compact:!0,gradient:!1}),a.time.activeRunCount>0?e.jsx(x,{className:"bg-emerald-500/12 text-emerald-200",children:"Live"}):null]}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{to:`/tasks/${a.id}`,className:"block min-w-0 max-w-full transition hover:opacity-85",onClick:m=>m.stopPropagation(),children:e.jsx(S,{kind:"task",label:a.title,variant:"heading",size:"md"})})}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:a.description||l("common.dailyRunway.noNote")})]}),e.jsx(x,{className:"shrink-0 self-start",children:a.status.replaceAll("_"," ")})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(x,{className:"bg-[var(--primary)]/14 text-[var(--primary)]",children:[a.points," xp"]}),e.jsx(W,{entityType:"task",entityId:a.id,count:A}),a.time.totalCreditedSeconds>0?e.jsxs(x,{className:"bg-white/[0.08] text-white/70",children:[Math.floor(a.time.totalCreditedSeconds/60)," min tracked"]}):null,e.jsx(x,{className:"bg-white/[0.08] text-white/70",children:a.effort}),e.jsx(x,{className:"bg-white/[0.08] text-white/70",children:y(a.dueDate)}),i.map(m=>e.jsx(x,{className:"bg-white/[0.08]",style:{color:m.color},children:m.name},m.id))]}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/40",children:a.owner}),d?e.jsxs(O,{variant:d.action==="start"?"primary":"secondary",className:"px-3 py-2 text-[11px] uppercase tracking-[0.16em]",onClick:async m=>{if(m.stopPropagation(),d.action==="start"){await u(a.id);return}d.nextStatus&&await p(a.id,d.nextStatus)},children:[e.jsx(d.icon,{className:"mr-2 size-3.5"}),d.label]}):null]})]},a.id)})})]}),e.jsxs("div",{className:"min-w-0 rounded-[24px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:l("common.dailyRunway.timelineEyebrow")}),e.jsx(C,{content:"This groups today's tasks by status, so you can see what is already moving, what is ready to start, what is blocked, and what is done."})]}),e.jsx("h4",{className:"mt-2 font-display text-2xl text-white",children:l("common.dailyRunway.timelineTitle")}),e.jsx("div",{className:"mt-4 grid min-w-0 gap-3",children:t.map(a=>e.jsxs("div",{className:"min-w-0 overflow-hidden rounded-[20px] bg-white/[0.03] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:a.label}),e.jsx(x,{className:"bg-white/[0.08] text-white/65",children:a.tasks.length})]}),e.jsxs("div",{className:"mt-3 grid gap-2",children:[a.tasks.slice(0,3).map(g=>{const d=D(g,c);return e.jsxs(f,{to:`/tasks/${g.id}`,className:"flex min-w-0 items-center justify-between gap-3 overflow-hidden rounded-[16px] bg-white/[0.03] px-3 py-3 text-left transition hover:bg-white/[0.06]",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx(S,{kind:"task",label:g.title,className:"max-w-full",labelClassName:"[overflow-wrap:anywhere]"}),e.jsx("div",{className:"mt-2",children:e.jsx(k,{kind:"goal",label:(d==null?void 0:d.title)??l("common.dailyRunway.unassigned"),compact:!0,gradient:!1})})]}),e.jsx(E,{className:"size-4 shrink-0 text-white/35"})]},g.id)}),a.tasks.length===0?e.jsx("div",{className:"text-sm text-white/42",children:l("common.dailyRunway.emptyBucket")}):null]})]},a.id))})]})]})}const le=5;function de(){const s=new Date;s.setHours(0,0,0,0);const t=new Date(s);return t.setDate(t.getDate()+1),{start:s,end:t,from:s.toISOString(),to:t.toISOString()}}function oe(s,t){const c=new Date(s.startAt),o=new Date(s.endAt);return c<t.end&&o>t.start}function ce(s){if(s.isAllDay)return"All day";const t=new Intl.DateTimeFormat(void 0,{hour:"numeric",minute:"2-digit"});return`${t.format(new Date(s.startAt))} - ${t.format(new Date(s.endAt))}`}function Te(){var d;const{t:s}=I(),t=$(),c=P(),o=T.useMemo(()=>de(),[]),j=Array.isArray(t.selectedUserIds)?t.selectedUserIds:[],w=X({queryKey:["forge-calendar-overview",o.from,o.to,...j],queryFn:()=>te({from:o.from,to:o.to,userIds:j})}),r=t.snapshot.today.directive.task,p=t.snapshot.today.milestoneRewards.find(i=>!i.completed)??t.snapshot.today.milestoneRewards[0]??null,u=t.snapshot.risk.blockedTasks[0]??t.snapshot.risk.overdueTasks[0]??null,l=Math.max(0,t.snapshot.metrics.nextLevelXp-t.snapshot.metrics.currentLevelXp),y=T.useMemo(()=>{var i;return(((i=w.data)==null?void 0:i.calendar.events)??[]).filter(n=>!n.deletedAt&&n.status!=="cancelled"&&oe(n,o)).sort((n,h)=>new Date(n.startAt).getTime()-new Date(h.startAt).getTime())},[(d=w.data)==null?void 0:d.calendar.events,o]),N=y.slice(0,le);if(!(t.snapshot.lifeForce!==void 0||r!==null||t.snapshot.overview.topTasks.length>0||t.snapshot.today.dueHabits.length>0||t.snapshot.today.dailyQuests.length>0||t.snapshot.today.milestoneRewards.length>0||y.length>0)&&!w.isLoading)return e.jsxs("div",{className:"grid gap-4",children:[e.jsx(R,{title:"Today",titleText:"Today",description:"Start a task, earn XP, and keep today's work clear.",badge:`${t.snapshot.metrics.weeklyXp} weekly xp`}),e.jsx(U,{eyebrow:s("common.todayPage.heroEyebrow"),title:s("common.todayPage.emptyTitle"),description:s("common.todayPage.emptyDescription"),action:e.jsx(f,{to:"/goals",className:"inline-flex min-h-10 min-w-max shrink-0 items-center justify-center rounded-full bg-[var(--primary)] px-4 py-2 text-sm font-medium whitespace-nowrap text-slate-950 transition hover:opacity-90",children:s("common.todayPage.emptyAction")})})]});const g=[{id:"hero",title:"Today",description:"Compact page header.",defaultWidth:12,defaultHeight:2,removable:!1,surfaceChrome:"none",defaultTitleVisible:!1,defaultDescriptionVisible:!1,render:()=>e.jsx(M,{children:e.jsx(R,{title:"Today",titleText:"Today",description:(r==null?void 0:r.description)??"Start one real task, collect XP, and keep today's work moving.",badge:`${t.snapshot.metrics.weeklyXp} weekly xp`})})},{id:"life-force",title:"Life Force",description:"Instant headroom, AP use today, and tiredness signals.",defaultWidth:12,defaultHeight:3,minWidth:5,render:()=>e.jsx(se,{selectedUserIds:t.selectedUserIds,fallbackLifeForce:t.snapshot.lifeForce,onRefresh:t.refresh})},{id:"metrics",title:"Live metrics",description:"XP, level, and momentum stay visible but lighter than before.",defaultWidth:5,defaultHeight:4,minWidth:4,render:({compact:i})=>e.jsx(V,{children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Weekly XP"}),e.jsx("div",{className:"mt-2 font-display text-4xl text-[var(--primary)]",children:t.snapshot.metrics.weeklyXp}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[t.snapshot.metrics.totalXp," total XP"]})]}),e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Level"}),e.jsx("div",{className:"mt-2 font-display text-4xl text-white",children:t.snapshot.metrics.level}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[l," xp to the next level"]}),i?null:e.jsx("div",{className:"mt-3",children:e.jsx(z,{value:t.snapshot.metrics.currentLevelXp/t.snapshot.metrics.nextLevelXp*100,tone:"tertiary"})})]}),e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Momentum"}),e.jsxs("div",{className:"mt-2 font-display text-4xl text-white",children:[t.snapshot.metrics.momentumScore,"%"]}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[t.snapshot.metrics.streakDays," day streak"]})]}),e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Next reward"}),e.jsx("div",{className:"mt-2 text-base font-semibold text-white",children:(p==null?void 0:p.title)??"Keep showing up"}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:(p==null?void 0:p.progressLabel)??"The next visible win comes from a task completion or aligned habit check-in."})]})]})})},{id:"runway",title:"Runway",description:"The execution lane itself can be widened or narrowed.",defaultWidth:7,defaultHeight:6,minWidth:5,render:()=>e.jsx(q,{children:e.jsx(re,{tasks:t.snapshot.overview.topTasks,timeline:t.snapshot.today.timeline,goals:t.snapshot.goals,tags:t.snapshot.tags,notesSummaryByEntity:t.snapshot.dashboard.notesSummaryByEntity,selectedTaskId:(r==null?void 0:r.id)??null,onSelectTask:i=>c(`/tasks/${i}`),onStartTask:async i=>{await t.startTaskNow(i)},onMove:async(i,n)=>{await t.patchTaskStatus(i,n)}})})},{id:"calendar",title:"Calendar",description:"Today's events stay grouped with their results instead of splitting search from outcome.",defaultWidth:5,defaultHeight:5,minWidth:4,render:({compact:i})=>e.jsx(K,{children:e.jsxs("div",{className:"grid gap-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[e.jsx("div",{className:"inline-flex size-10 shrink-0 items-center justify-center rounded-2xl bg-[var(--primary)]/14 text-[var(--primary)]",children:e.jsx(B,{className:"size-4"})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Today's calendar"}),e.jsx("div",{className:"text-sm font-semibold text-white",children:new Intl.DateTimeFormat(void 0,{weekday:"short",month:"short",day:"numeric"}).format(o.start)}),e.jsxs("div",{className:"text-sm text-white/58",children:[y.length," event",y.length===1?"":"s"]})]})]}),e.jsxs(f,{to:"/calendar",className:"inline-flex shrink-0 items-center gap-2 rounded-full bg-white/[0.06] px-3 py-2 text-xs font-medium text-white/72 transition hover:bg-white/[0.1] hover:text-white",children:["Open calendar",e.jsx(L,{className:"size-3.5"})]})]}),y.length===0?e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-4 text-sm text-white/58",children:"Nothing is scheduled yet for today."}):N.map(n=>e.jsxs("button",{type:"button",className:"grid min-w-0 gap-2 rounded-[18px] bg-white/[0.04] px-3 py-3 text-left transition hover:bg-white/[0.07]",onClick:()=>c("/calendar"),children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("div",{className:"truncate text-sm font-medium text-white",children:n.title}),e.jsx("div",{className:"mt-1 text-sm text-white/58",children:ce(n)})]}),e.jsx(x,{className:"shrink-0 bg-white/[0.08] text-white/72",children:n.originType==="native"?"Forge":n.originType})]}),!i&&n.description?e.jsx("div",{className:"line-clamp-2 text-sm leading-6 text-white/52",children:n.description}):null]},n.id))]})})},{id:"focus",title:"Current focus",description:"Current task, comeback task, and due habits stay in one movable stack.",defaultWidth:12,defaultHeight:4,minWidth:6,render:({compact:i})=>{var n;return e.jsx(Q,{children:e.jsxs("div",{className:"grid min-w-0 gap-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)]",children:[e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Current task"}),r?e.jsx(W,{entityType:"task",entityId:r.id,count:((n=t.snapshot.dashboard.notesSummaryByEntity[`task:${r.id}`])==null?void 0:n.count)??0}):null]}),e.jsx("div",{className:"mt-3 text-base font-semibold text-white",children:(r==null?void 0:r.title)??"Pick a task from the runway"}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/58",children:(r==null?void 0:r.description)??"Once a task is active, the timer rail and this panel stay aligned."}),r?e.jsx("button",{type:"button",className:"mt-4 inline-flex min-h-10 items-center justify-center rounded-2xl bg-[rgba(192,193,255,0.16)] px-3.5 py-2 text-sm font-medium text-[var(--primary)] transition hover:bg-[rgba(192,193,255,0.24)]",onClick:async()=>{await t.startTaskNow(r.id)},children:"Start work"}):null]}),e.jsxs("div",{className:"grid gap-3",children:[e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Recovery task"}),e.jsx("div",{className:"mt-3 text-sm font-semibold text-white",children:(u==null?void 0:u.title)??"No blocked or overdue task is dominating today"}),i?null:e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/56",children:(u==null?void 0:u.description)??"If something slips, it will surface here as the clean comeback move."})]}),e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Due habits"}),e.jsx("div",{className:"mt-3 grid gap-2",children:t.snapshot.today.dueHabits.slice(0,i?2:3).map(h=>e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-[16px] bg-white/[0.04] px-3 py-2.5",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium text-white",children:h.title}),i?null:e.jsx("div",{className:"text-sm text-white/52",children:h.frequency})]}),e.jsxs(x,{className:"bg-[rgba(78,222,163,0.14)] text-[var(--secondary)]",children:[h.rewardXp," xp"]})]},h.id))})]})]})]})})}},{id:"time",title:"Clock",description:"Optional utility widget.",defaultWidth:3,defaultHeight:2,defaultHidden:!0,render:({compact:i})=>e.jsx(G,{compact:i})},{id:"weather",title:"Weather",description:"Optional utility widget.",defaultWidth:3,defaultHeight:2,defaultHidden:!0,render:({compact:i})=>e.jsx(J,{compact:i})},{id:"mini-calendar",title:"Mini calendar",description:"Optional utility widget.",defaultWidth:4,defaultHeight:3,defaultHidden:!0,render:({compact:i})=>e.jsx(Y,{compact:i})},{id:"spotify",title:"Spotify",description:"Optional utility widget.",defaultWidth:4,defaultHeight:2,defaultHidden:!0,render:()=>e.jsx(Z,{surfaceId:"today"})},{id:"quick-capture",title:"Quick capture",description:"Save a note or wiki draft without leaving Today.",defaultWidth:5,defaultHeight:3,defaultHidden:!0,render:({compact:i})=>{var n;return e.jsx(ee,{compact:i,defaultUserId:t.selectedUserIds[0]??((n=t.snapshot.users[0])==null?void 0:n.id)??null})}}];return e.jsx(_,{surfaceId:"today",baseWidgets:g})}export{Te as TodayPage};
|
|
1
|
+
import{j as e,aC as f,b8 as E,bB as b,bE as H,b5 as P,r as T,aV as B,cA as L}from"./vendor-DHkYh85p.js";import{i as X}from"./state-B-4sS1xO.js";import{A as _}from"./ai-surface-workspace-DEAFZruS.js";import{P as I,aq as C,c as x,_ as F,b as k,V as S,B as O,u as $,a as U,eR as M,eS as V,C as v,W as z,eT as q,eU as K,eV as Q,bG as G,bH as J,bI as Y,bJ as Z,bK as ee,N as te}from"./index-CF4J4R9L.js";import{E as W}from"./entity-note-count-link-DrhjJZ4i.js";import{a as se}from"./life-force-workspace-OfyB9HJM.js";import{P as R}from"./page-hero-DRy5b2MU.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";import"./floating-action-menu-Fs_ZiUMo.js";import"./charts-P7EVhIog.js";function D(s,t){return t.find(c=>c.id===s.goalId)??null}function ae(s,t){return s.tagIds.map(c=>t.find(o=>o.id===c)).filter(Boolean)}function ie(s,t){(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),t())}function ne(s,t){switch(s.status){case"backlog":return{label:t.backlog,action:"start",icon:b};case"focus":return{label:t.focus,action:"start",icon:b};case"in_progress":return{label:t.in_progress,nextStatus:"done",action:"move",icon:H};case"blocked":return{label:t.blocked,action:"start",icon:b};default:return null}}function re({tasks:s,timeline:t,goals:c,tags:o,notesSummaryByEntity:j,selectedTaskId:w,onSelectTask:r,onMove:p,onStartTask:u}){const{t:l,formatDate:y}=I(),N={backlog:l("common.dailyRunway.actionBacklog"),focus:l("common.dailyRunway.actionFocus"),in_progress:l("common.dailyRunway.actionProgress"),blocked:l("common.dailyRunway.actionBlocked")};return e.jsxs("div",{className:"grid min-w-0 gap-4 2xl:grid-cols-[minmax(0,1.3fr)_minmax(17rem,0.9fr)]",children:[e.jsxs("div",{className:"min-w-0 rounded-[24px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:l("common.dailyRunway.runwayEyebrow")}),e.jsx(C,{content:"These are the tasks that matter most for today. Click a card to open the task details. Use Start to begin work immediately."})]}),e.jsx("h4",{className:"mt-2 font-display text-2xl text-white",children:l("common.dailyRunway.runwayTitle")})]}),e.jsx(x,{className:"shrink-0 text-[var(--primary)]",children:l(s.length===1?"common.dailyRunway.prioritiesOne":"common.dailyRunway.prioritiesOther",{count:s.length})})]}),e.jsx("div",{className:"mt-4 grid min-w-0 gap-3",children:s.map((a,g)=>{const d=ne(a,N),i=ae(a,o).slice(0,2),n=D(a,c),h=w===a.id,A=F(j,"task",a.id).count;return e.jsxs("article",{role:"button",tabIndex:0,"aria-pressed":h,className:`grid w-full gap-3 rounded-[22px] px-4 py-4 text-left transition ${h?"bg-[linear-gradient(180deg,rgba(192,193,255,0.16),rgba(192,193,255,0.05))] shadow-[inset_0_0_0_1px_rgba(192,193,255,0.2)]":"bg-white/[0.03] hover:bg-white/[0.06]"}`,onClick:()=>r(a.id),onKeyDown:m=>ie(m,()=>r(a.id)),children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:l("common.dailyRunway.runwayItem",{index:g+1})}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[n?e.jsx(f,{to:`/goals/${n.id}`,className:"min-w-0 max-w-full transition hover:opacity-85",onClick:m=>m.stopPropagation(),children:e.jsx(k,{kind:"goal",label:n.title,compact:!0,gradient:!1})}):e.jsx(k,{kind:"goal",label:l("common.dailyRunway.unassigned"),compact:!0,gradient:!1}),a.time.activeRunCount>0?e.jsx(x,{className:"bg-emerald-500/12 text-emerald-200",children:"Live"}):null]}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{to:`/tasks/${a.id}`,className:"block min-w-0 max-w-full transition hover:opacity-85",onClick:m=>m.stopPropagation(),children:e.jsx(S,{kind:"task",label:a.title,variant:"heading",size:"md"})})}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:a.description||l("common.dailyRunway.noNote")})]}),e.jsx(x,{className:"shrink-0 self-start",children:a.status.replaceAll("_"," ")})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(x,{className:"bg-[var(--primary)]/14 text-[var(--primary)]",children:[a.points," xp"]}),e.jsx(W,{entityType:"task",entityId:a.id,count:A}),a.time.totalCreditedSeconds>0?e.jsxs(x,{className:"bg-white/[0.08] text-white/70",children:[Math.floor(a.time.totalCreditedSeconds/60)," min tracked"]}):null,e.jsx(x,{className:"bg-white/[0.08] text-white/70",children:a.effort}),e.jsx(x,{className:"bg-white/[0.08] text-white/70",children:y(a.dueDate)}),i.map(m=>e.jsx(x,{className:"bg-white/[0.08]",style:{color:m.color},children:m.name},m.id))]}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/40",children:a.owner}),d?e.jsxs(O,{variant:d.action==="start"?"primary":"secondary",className:"px-3 py-2 text-[11px] uppercase tracking-[0.16em]",onClick:async m=>{if(m.stopPropagation(),d.action==="start"){await u(a.id);return}d.nextStatus&&await p(a.id,d.nextStatus)},children:[e.jsx(d.icon,{className:"mr-2 size-3.5"}),d.label]}):null]})]},a.id)})})]}),e.jsxs("div",{className:"min-w-0 rounded-[24px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:l("common.dailyRunway.timelineEyebrow")}),e.jsx(C,{content:"This groups today's tasks by status, so you can see what is already moving, what is ready to start, what is blocked, and what is done."})]}),e.jsx("h4",{className:"mt-2 font-display text-2xl text-white",children:l("common.dailyRunway.timelineTitle")}),e.jsx("div",{className:"mt-4 grid min-w-0 gap-3",children:t.map(a=>e.jsxs("div",{className:"min-w-0 overflow-hidden rounded-[20px] bg-white/[0.03] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-medium text-white",children:a.label}),e.jsx(x,{className:"bg-white/[0.08] text-white/65",children:a.tasks.length})]}),e.jsxs("div",{className:"mt-3 grid gap-2",children:[a.tasks.slice(0,3).map(g=>{const d=D(g,c);return e.jsxs(f,{to:`/tasks/${g.id}`,className:"flex min-w-0 items-center justify-between gap-3 overflow-hidden rounded-[16px] bg-white/[0.03] px-3 py-3 text-left transition hover:bg-white/[0.06]",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx(S,{kind:"task",label:g.title,className:"max-w-full",labelClassName:"[overflow-wrap:anywhere]"}),e.jsx("div",{className:"mt-2",children:e.jsx(k,{kind:"goal",label:(d==null?void 0:d.title)??l("common.dailyRunway.unassigned"),compact:!0,gradient:!1})})]}),e.jsx(E,{className:"size-4 shrink-0 text-white/35"})]},g.id)}),a.tasks.length===0?e.jsx("div",{className:"text-sm text-white/42",children:l("common.dailyRunway.emptyBucket")}):null]})]},a.id))})]})]})}const le=5;function de(){const s=new Date;s.setHours(0,0,0,0);const t=new Date(s);return t.setDate(t.getDate()+1),{start:s,end:t,from:s.toISOString(),to:t.toISOString()}}function oe(s,t){const c=new Date(s.startAt),o=new Date(s.endAt);return c<t.end&&o>t.start}function ce(s){if(s.isAllDay)return"All day";const t=new Intl.DateTimeFormat(void 0,{hour:"numeric",minute:"2-digit"});return`${t.format(new Date(s.startAt))} - ${t.format(new Date(s.endAt))}`}function Te(){var d;const{t:s}=I(),t=$(),c=P(),o=T.useMemo(()=>de(),[]),j=Array.isArray(t.selectedUserIds)?t.selectedUserIds:[],w=X({queryKey:["forge-calendar-overview",o.from,o.to,...j],queryFn:()=>te({from:o.from,to:o.to,userIds:j})}),r=t.snapshot.today.directive.task,p=t.snapshot.today.milestoneRewards.find(i=>!i.completed)??t.snapshot.today.milestoneRewards[0]??null,u=t.snapshot.risk.blockedTasks[0]??t.snapshot.risk.overdueTasks[0]??null,l=Math.max(0,t.snapshot.metrics.nextLevelXp-t.snapshot.metrics.currentLevelXp),y=T.useMemo(()=>{var i;return(((i=w.data)==null?void 0:i.calendar.events)??[]).filter(n=>!n.deletedAt&&n.status!=="cancelled"&&oe(n,o)).sort((n,h)=>new Date(n.startAt).getTime()-new Date(h.startAt).getTime())},[(d=w.data)==null?void 0:d.calendar.events,o]),N=y.slice(0,le);if(!(t.snapshot.lifeForce!==void 0||r!==null||t.snapshot.overview.topTasks.length>0||t.snapshot.today.dueHabits.length>0||t.snapshot.today.dailyQuests.length>0||t.snapshot.today.milestoneRewards.length>0||y.length>0)&&!w.isLoading)return e.jsxs("div",{className:"grid gap-4",children:[e.jsx(R,{title:"Today",titleText:"Today",description:"Start a task, earn XP, and keep today's work clear.",badge:`${t.snapshot.metrics.weeklyXp} weekly xp`}),e.jsx(U,{eyebrow:s("common.todayPage.heroEyebrow"),title:s("common.todayPage.emptyTitle"),description:s("common.todayPage.emptyDescription"),action:e.jsx(f,{to:"/goals",className:"inline-flex min-h-10 min-w-max shrink-0 items-center justify-center rounded-full bg-[var(--primary)] px-4 py-2 text-sm font-medium whitespace-nowrap text-slate-950 transition hover:opacity-90",children:s("common.todayPage.emptyAction")})})]});const g=[{id:"hero",title:"Today",description:"Compact page header.",defaultWidth:12,defaultHeight:2,removable:!1,surfaceChrome:"none",defaultTitleVisible:!1,defaultDescriptionVisible:!1,render:()=>e.jsx(M,{children:e.jsx(R,{title:"Today",titleText:"Today",description:(r==null?void 0:r.description)??"Start one real task, collect XP, and keep today's work moving.",badge:`${t.snapshot.metrics.weeklyXp} weekly xp`})})},{id:"life-force",title:"Life Force",description:"Instant headroom, AP use today, and tiredness signals.",defaultWidth:12,defaultHeight:3,minWidth:5,render:()=>e.jsx(se,{selectedUserIds:t.selectedUserIds,fallbackLifeForce:t.snapshot.lifeForce,onRefresh:t.refresh})},{id:"metrics",title:"Live metrics",description:"XP, level, and momentum stay visible but lighter than before.",defaultWidth:5,defaultHeight:4,minWidth:4,render:({compact:i})=>e.jsx(V,{children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Weekly XP"}),e.jsx("div",{className:"mt-2 font-display text-4xl text-[var(--primary)]",children:t.snapshot.metrics.weeklyXp}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[t.snapshot.metrics.totalXp," total XP"]})]}),e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Level"}),e.jsx("div",{className:"mt-2 font-display text-4xl text-white",children:t.snapshot.metrics.level}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[l," xp to the next level"]}),i?null:e.jsx("div",{className:"mt-3",children:e.jsx(z,{value:t.snapshot.metrics.currentLevelXp/t.snapshot.metrics.nextLevelXp*100,tone:"tertiary"})})]}),e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Momentum"}),e.jsxs("div",{className:"mt-2 font-display text-4xl text-white",children:[t.snapshot.metrics.momentumScore,"%"]}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[t.snapshot.metrics.streakDays," day streak"]})]}),e.jsxs(v,{className:"p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Next reward"}),e.jsx("div",{className:"mt-2 text-base font-semibold text-white",children:(p==null?void 0:p.title)??"Keep showing up"}),e.jsx("div",{className:"mt-1 text-sm text-white/56",children:(p==null?void 0:p.progressLabel)??"The next visible win comes from a task completion or aligned habit check-in."})]})]})})},{id:"runway",title:"Runway",description:"The execution lane itself can be widened or narrowed.",defaultWidth:7,defaultHeight:6,minWidth:5,render:()=>e.jsx(q,{children:e.jsx(re,{tasks:t.snapshot.overview.topTasks,timeline:t.snapshot.today.timeline,goals:t.snapshot.goals,tags:t.snapshot.tags,notesSummaryByEntity:t.snapshot.dashboard.notesSummaryByEntity,selectedTaskId:(r==null?void 0:r.id)??null,onSelectTask:i=>c(`/tasks/${i}`),onStartTask:async i=>{await t.startTaskNow(i)},onMove:async(i,n)=>{await t.patchTaskStatus(i,n)}})})},{id:"calendar",title:"Calendar",description:"Today's events stay grouped with their results instead of splitting search from outcome.",defaultWidth:5,defaultHeight:5,minWidth:4,render:({compact:i})=>e.jsx(K,{children:e.jsxs("div",{className:"grid gap-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[e.jsx("div",{className:"inline-flex size-10 shrink-0 items-center justify-center rounded-2xl bg-[var(--primary)]/14 text-[var(--primary)]",children:e.jsx(B,{className:"size-4"})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Today's calendar"}),e.jsx("div",{className:"text-sm font-semibold text-white",children:new Intl.DateTimeFormat(void 0,{weekday:"short",month:"short",day:"numeric"}).format(o.start)}),e.jsxs("div",{className:"text-sm text-white/58",children:[y.length," event",y.length===1?"":"s"]})]})]}),e.jsxs(f,{to:"/calendar",className:"inline-flex shrink-0 items-center gap-2 rounded-full bg-white/[0.06] px-3 py-2 text-xs font-medium text-white/72 transition hover:bg-white/[0.1] hover:text-white",children:["Open calendar",e.jsx(L,{className:"size-3.5"})]})]}),y.length===0?e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-4 text-sm text-white/58",children:"Nothing is scheduled yet for today."}):N.map(n=>e.jsxs("button",{type:"button",className:"grid min-w-0 gap-2 rounded-[18px] bg-white/[0.04] px-3 py-3 text-left transition hover:bg-white/[0.07]",onClick:()=>c("/calendar"),children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("div",{className:"truncate text-sm font-medium text-white",children:n.title}),e.jsx("div",{className:"mt-1 text-sm text-white/58",children:ce(n)})]}),e.jsx(x,{className:"shrink-0 bg-white/[0.08] text-white/72",children:n.originType==="native"?"Forge":n.originType})]}),!i&&n.description?e.jsx("div",{className:"line-clamp-2 text-sm leading-6 text-white/52",children:n.description}):null]},n.id))]})})},{id:"focus",title:"Current focus",description:"Current task, comeback task, and due habits stay in one movable stack.",defaultWidth:12,defaultHeight:4,minWidth:6,render:({compact:i})=>{var n;return e.jsx(Q,{children:e.jsxs("div",{className:"grid min-w-0 gap-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)]",children:[e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Current task"}),r?e.jsx(W,{entityType:"task",entityId:r.id,count:((n=t.snapshot.dashboard.notesSummaryByEntity[`task:${r.id}`])==null?void 0:n.count)??0}):null]}),e.jsx("div",{className:"mt-3 text-base font-semibold text-white",children:(r==null?void 0:r.title)??"Pick a task from the runway"}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/58",children:(r==null?void 0:r.description)??"Once a task is active, the timer rail and this panel stay aligned."}),r?e.jsx("button",{type:"button",className:"mt-4 inline-flex min-h-10 items-center justify-center rounded-2xl bg-[rgba(192,193,255,0.16)] px-3.5 py-2 text-sm font-medium text-[var(--primary)] transition hover:bg-[rgba(192,193,255,0.24)]",onClick:async()=>{await t.startTaskNow(r.id)},children:"Start work"}):null]}),e.jsxs("div",{className:"grid gap-3",children:[e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Recovery task"}),e.jsx("div",{className:"mt-3 text-sm font-semibold text-white",children:(u==null?void 0:u.title)??"No blocked or overdue task is dominating today"}),i?null:e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/56",children:(u==null?void 0:u.description)??"If something slips, it will surface here as the clean comeback move."})]}),e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/38",children:"Due habits"}),e.jsx("div",{className:"mt-3 grid gap-2",children:t.snapshot.today.dueHabits.slice(0,i?2:3).map(h=>e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-[16px] bg-white/[0.04] px-3 py-2.5",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium text-white",children:h.title}),i?null:e.jsx("div",{className:"text-sm text-white/52",children:h.frequency})]}),e.jsxs(x,{className:"bg-[rgba(78,222,163,0.14)] text-[var(--secondary)]",children:[h.rewardXp," xp"]})]},h.id))})]})]})]})})}},{id:"time",title:"Clock",description:"Optional utility widget.",defaultWidth:3,defaultHeight:2,defaultHidden:!0,render:({compact:i})=>e.jsx(G,{compact:i})},{id:"weather",title:"Weather",description:"Optional utility widget.",defaultWidth:3,defaultHeight:2,defaultHidden:!0,render:({compact:i})=>e.jsx(J,{compact:i})},{id:"mini-calendar",title:"Mini calendar",description:"Optional utility widget.",defaultWidth:4,defaultHeight:3,defaultHidden:!0,render:({compact:i})=>e.jsx(Y,{compact:i})},{id:"spotify",title:"Spotify",description:"Optional utility widget.",defaultWidth:4,defaultHeight:2,defaultHidden:!0,render:()=>e.jsx(Z,{surfaceId:"today"})},{id:"quick-capture",title:"Quick capture",description:"Save a note or wiki draft without leaving Today.",defaultWidth:5,defaultHeight:3,defaultHidden:!0,render:({compact:i})=>{var n;return e.jsx(ee,{compact:i,defaultUserId:t.selectedUserIds[0]??((n=t.snapshot.users[0])==null?void 0:n.id)??null})}}];return e.jsx(_,{surfaceId:"today",baseWidgets:g})}export{Te as TodayPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as x,j as e,du as B,aL as D,bU as W,aH as Z,cg as P,bJ as $,dv as F,bK as V}from"./vendor-DHkYh85p.js";import{i as U}from"./state-B-4sS1xO.js";import{C as m,aq as b,c as T,u as q,S as G,E as Q,eL as Y}from"./index-BHTUu_4M.js";import{f as K,C as L,X as R,Y as j,T as z,B as v,e as A,a as X,b as E,j as J,P as ee,k as te,l as ae,g as ie}from"./charts-P7EVhIog.js";import{P as se}from"./page-hero-CQWo1Mm_.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";function _({height:a,children:t}){const o=x.useRef(null),[r,l]=x.useState(0);return x.useEffect(()=>{const i=o.current;if(!i)return;const c=()=>{l(Math.max(0,Math.floor(i.getBoundingClientRect().width)))};if(c(),typeof ResizeObserver>"u")return window.addEventListener("resize",c),()=>window.removeEventListener("resize",c);const f=new ResizeObserver(c);return f.observe(i),()=>f.disconnect()},[]),e.jsx("div",{ref:o,style:{height:a},className:"min-w-0",children:r>24?t({width:r,height:a}):null})}const I=["below_z1","zone_1","zone_2","zone_3","zone_4","zone_5"],H={below_z1:"Below Z1",zone_1:"Z1",zone_2:"Z2",zone_3:"Z3",zone_4:"Z4",zone_5:"Z5"},re={below_z1:"#94a3b8",zone_1:"#38bdf8",zone_2:"#22c55e",zone_3:"#eab308",zone_4:"#f97316",zone_5:"#ef4444"},y={timeInZone:"Each block totals the minutes Forge can place into adaptive HRR zones from stored heart-rate samples. Weekly is the default planning view because it matches common training microcycles; monthly and daily views help detect longer trends or recent spikes.",smartMode:"Smart modes do not change the underlying data. They change the coaching lens: combat readiness prioritizes hard-day spacing and controlled high intensity, aerobic base prioritizes low-zone development, and endurance pro compares the distribution with pyramidal or polarized endurance planning patterns.",interpretation:"This paragraph explains what the selected mode concludes from the latest load balance, zone distribution, hard-day count, and data confidence. It is a planning summary, not a medical clearance.",drivers:"Drivers are the signals helping the selected mode: examples include enough easy/base work, controlled high-zone share, stable acute/chronic load, or improving data quality.",limiters:"Limiters are the signals that should constrain the next block. If Forge lists a limiter, the next target should usually solve that before adding more hard work.",targets:"Next targets translate the selected mode into a practical week and next workout. The range is intentionally bounded so training can progress without turning every good week into a maximal week."};function ne(a){return a.key==="combat_readiness"?"Combat":a.key==="aerobic_base"?"Base":"Endurance"}function oe(a){return a>=82?"signal":a>=65?"default":"meta"}function le(a){switch(a){case"vo2max_4x4":return"4x4 VO2max";case"zone_2_base":return"Zone 2 / base";case"technical_kickboxing":return"Technical kickboxing";case"easy_aerobic":return"Easy aerobic";case"recovery":return"Recovery";default:return a.replaceAll("_"," ")}}function de(a,t){return t==="daily"?a.bucketKey.slice(5):t==="monthly"?a.bucketKey.slice(2):a.bucketKey.replace(/^20/,"'")}function ce(a,t){const o=t==="daily"?30:12;return a.slice(-o).map(r=>({bucket:de(r,t),total:Math.round(r.durationMinutes),load:r.trainingLoad,confidence:r.confidence,...Object.fromEntries(I.map(l=>[l,r.zoneMinutes[l]??0]))}))}function he(a,t){return a.zoneTimeSeries[t]}function xe({mode:a}){return e.jsxs("div",{className:"grid gap-3 lg:grid-cols-2",children:[e.jsxs("div",{className:"rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(W,{className:"size-3.5"}),"Drivers",e.jsx(b,{label:"Explain training drivers",title:"Drivers",content:y.drivers})]}),e.jsx("div",{className:"mt-3 grid gap-2 text-[12px] leading-5 text-white/62",children:(a.drivers.length>0?a.drivers:["No positive driver is strong enough yet."]).map(t=>e.jsx("div",{children:t},t))})]}),e.jsxs("div",{className:"rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(Z,{className:"size-3.5"}),"Limiters",e.jsx(b,{label:"Explain training limiters",title:"Limiters",content:y.limiters})]}),e.jsx("div",{className:"mt-3 grid gap-2 text-[12px] leading-5 text-white/62",children:(a.limitingFactors.length>0?a.limitingFactors:["No major limiter in this mode right now."]).map(t=>e.jsx("div",{children:t},t))})]})]})}function me({trainingLoad:a}){const[t,o]=x.useState(a.trainingIntelligence.defaultMode),[r,l]=x.useState("weekly"),i=a.trainingIntelligence.modes.find(n=>n.key===t)??a.trainingIntelligence.modes[0],c=he(a,r),f=x.useMemo(()=>ce(c,r),[c,r]),C=c.slice(-8).reverse();return i?e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1.25fr)_minmax(340px,0.75fr)]",children:[e.jsxs(m,{className:"overflow-hidden",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:"Zone intelligence"}),e.jsx(b,{label:"Explain zone intelligence",title:"Time in zone",content:y.timeInZone})]}),e.jsx("div",{className:"mt-2 text-lg text-white",children:"Time in zone by training block"}),e.jsx("div",{className:"mt-1 max-w-2xl text-[12px] leading-5 text-white/50",children:"Weekly by default because most training plans are adjusted week by week. The stacked bars preserve the full zone split, while the table adds load rate, hard days, and data confidence."})]}),e.jsx("div",{className:"grid grid-cols-3 gap-1 rounded-[8px] border border-white/8 bg-white/[0.035] p-1",children:[["weekly","Week"],["monthly","Month"],["daily","90d"]].map(([n,u])=>e.jsx("button",{type:"button",className:`rounded-[6px] px-3 py-1.5 text-[12px] ${r===n?"bg-white/[0.12] text-white":"text-white/54"}`,onClick:()=>l(n),children:u},n))})]}),e.jsx("div",{className:"mt-5",children:e.jsx(_,{height:320,children:({width:n,height:u})=>e.jsxs(K,{data:f,width:n,height:u,children:[e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"bucket",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10}}),e.jsx(j,{tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:42}),e.jsx(z,{formatter:(p,d)=>[`${Number(p).toFixed(0)} min`,H[d]??String(d)],contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),I.map(p=>e.jsx(v,{dataKey:p,stackId:"zones",fill:re[p],name:p},p))]})})}),e.jsxs("div",{className:"mt-4 overflow-x-auto rounded-[8px] border border-white/8",children:[e.jsxs("div",{className:"grid min-w-[760px] grid-cols-[96px_72px_72px_repeat(6,64px)_72px_80px] bg-white/[0.045] px-3 py-2 text-[10px] uppercase tracking-[0.14em] text-white/42",children:[e.jsx("div",{children:"Block"}),e.jsx("div",{children:"Load"}),e.jsx("div",{children:"TRIMP/min"}),I.map(n=>e.jsx("div",{children:H[n]},n)),e.jsx("div",{children:"Hard"}),e.jsx("div",{children:"Quality"})]}),C.map(n=>e.jsxs("div",{className:"grid min-w-[760px] grid-cols-[96px_72px_72px_repeat(6,64px)_72px_80px] border-t border-white/8 px-3 py-2 text-[12px] text-white/62",children:[e.jsx("div",{className:"text-white",children:n.bucketKey}),e.jsx("div",{children:n.trainingLoad}),e.jsx("div",{children:n.loadPerMinute}),I.map(u=>e.jsx("div",{children:n.zoneMinutes[u]},u)),e.jsx("div",{children:n.hardDayCount}),e.jsx("div",{children:n.confidence})]},n.bucketKey))]})]}),e.jsxs(m,{className:"overflow-hidden",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:"Smart training mode"}),e.jsx(b,{label:"Explain smart training modes",title:"Training mode",content:y.smartMode})]}),e.jsx("div",{className:"mt-2 text-lg text-white",children:i.label})]}),e.jsxs(T,{tone:oe(i.score),children:[i.score,"/100"]})]}),e.jsx("div",{className:"mt-4 grid grid-cols-3 gap-1 rounded-[8px] border border-white/8 bg-white/[0.035] p-1",children:a.trainingIntelligence.modes.map(n=>e.jsx("button",{type:"button",className:`rounded-[6px] px-2 py-2 text-[12px] ${n.key===i.key?"bg-white/[0.12] text-white":"text-white/54"}`,onClick:()=>o(n.key),children:ne(n)},n.key))}),e.jsxs("div",{className:"mt-4 rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(B,{className:"size-3.5"}),"Interpretation",e.jsx(b,{label:"Explain this interpretation",title:"Interpretation",content:y.interpretation})]}),e.jsx("div",{className:"mt-3 text-[13px] leading-5 text-white/72",children:i.summary}),e.jsxs("div",{className:"mt-3 grid grid-cols-2 gap-2 text-[11px] text-white/50",children:[e.jsxs("div",{children:["Balance: ",i.loadBalance.status]}),e.jsxs("div",{children:["Confidence: ",i.confidence]}),e.jsxs("div",{children:["ACWR: ",i.loadBalance.acuteChronicRatio??"n/a"]}),e.jsxs("div",{children:["Baseline:"," ",i.loadBalance.latestWeekBaselineLoadRatio??"n/a","x"]})]})]}),e.jsx("div",{className:"mt-4",children:e.jsx(xe,{mode:i})}),e.jsxs("div",{className:"mt-4 grid gap-3 rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(D,{className:"size-3.5"}),"Next targets",e.jsx(b,{label:"Explain next training targets",title:"Next targets",content:y.targets})]}),e.jsxs("div",{className:"grid gap-2 text-[12px] leading-5 text-white/62",children:[e.jsxs("div",{children:["Next week: ",i.nextWeekTargets.totalMinutesRange[0],"-",i.nextWeekTargets.totalMinutesRange[1]," min · max"," ",i.nextWeekTargets.maxHardSessions," hard sessions · at least ",i.nextWeekTargets.minimumEasyMinutes," easy/base min."]}),e.jsxs("div",{children:["Next workout:"," ",e.jsx("span",{className:"text-white",children:le(i.nextWorkout.recommendedType)})," ","for ",i.nextWorkout.durationMinutesRange[0],"-",i.nextWorkout.durationMinutesRange[1]," min, ceiling"," ",i.nextWorkout.intensityCeiling,"."]}),e.jsx("div",{className:"text-white/50",children:i.nextWorkout.reason}),i.nextWeekTargets.warning?e.jsx("div",{className:"rounded-[6px] bg-amber-300/10 px-2 py-1 text-amber-100/82",children:i.nextWeekTargets.warning}):null]})]})]})]}):null}const ue={low:"#22c55e",moderate:"#f59e0b",high:"#ef4444"},ge={below_z1:"#94a3b8",zone_1:"#38bdf8",zone_2:"#22c55e",zone_3:"#eab308",zone_4:"#f97316",zone_5:"#ef4444"},h={hero:"Forge estimates cardiovascular training stress from stored workouts, heart-rate samples, adaptive heart-rate-reserve zones, and recent vitals. Use this page to decide whether the next training block should build aerobic base, hold load steady, sharpen intensity, or recover. The numbers support coaching decisions; they are not medical diagnosis.",acuteLoad:"Acute load is the last seven days of Forge's TRIMP-like internal load. It rises when workouts are longer, harder, or spend more time in high heart-rate zones. Compare it with chronic load before adding hard sessions.",chronicBase:"Chronic base is the average weekly load over the last 28 days. It is Forge's estimate of the current load you have recently proven you can absorb.",acwr:"ACWR is acute load divided by chronic weekly load. Values near 1.0 usually mean the current week resembles the recent base. High values ask for recovery checks; low values suggest underloading. Treat it as a flag, not a verdict.",vo2max:"VO2max is the latest available wearable estimate in ml/kg/min. Forge shows the recent change when enough points exist, but wearable VO2max can move with device model, terrain, heat, and workout type.",weeklyMap:"This chart combines weekly internal load, training hours, and the share of time in zones 4 and 5. It helps reveal whether fatigue comes from total volume, hard intensity, or both.",adaptationRadar:"The radar compresses six signals into one coach view: current load, base capacity, acute/chronic balance, heart-rate data quality, high-intensity pressure, and VO2max movement.",intensityTarget:"This compares your recent or all-time low, moderate, and high intensity distribution with broad target bands used in endurance and combat-sport conditioning. The target is a planning reference, not a rule.",hrZones:"These bars show minutes in each adaptive HRR zone. Zone 2 is commonly used for aerobic base, zones 4 and 5 for threshold and VO2max work, and below-zone time often reflects warm-up, recovery, or missing cardiovascular load.",dailyTexture:"Daily texture shows whether load spikes are coming from easy volume, threshold work, or high-intensity minutes. It is useful for spacing hard days and avoiding accidental clusters.",sessionSignals:"Recent workout rows expose the session evidence behind the summary: date, activity, training load, high-zone share, heart-rate response, and data confidence.",sportContribution:"Sport contribution groups load by workout type. In kickboxing and other combat sports, wrist heart rate can undercount short striking spikes, so compare this with how the session actually felt."};function O(a,t=0){return a==null||Number.isNaN(a)?"n/a":`${(a*100).toFixed(t)}%`}function k(a,t=0){return a==null||Number.isNaN(a)?"n/a":a.toFixed(t)}function pe(a){switch(a){case"productive":return{label:"Productive",tone:"signal",text:"Acute load is close to the current chronic base."};case"underloaded":return{label:"Underloaded",tone:"meta",text:"The recent week is below the four-week baseline."};case"overload_watch":return{label:"Watch load",tone:"default",text:"Acute load or strain is elevated enough to deserve recovery checks."};default:return{label:"Building signal",tone:"meta",text:"Forge needs more recent training evidence for a cleaner read."}}}function M({label:a,value:t,detail:o,help:r,icon:l}){return e.jsxs(m,{className:"relative min-h-[136px] overflow-hidden",children:[e.jsx("div",{className:"absolute right-3 top-3 rounded-[8px] border border-white/8 bg-white/[0.045] p-2 text-white/58",children:e.jsx(l,{className:"size-4"})}),e.jsxs("div",{className:"flex max-w-[80%] items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:a}),e.jsx(b,{label:`Explain ${a}`,title:a,content:r})]}),e.jsx("div",{className:"mt-4 font-display text-4xl leading-none text-white",children:t}),e.jsx("div",{className:"mt-3 max-w-[24rem] text-[12px] leading-5 text-white/56",children:o})]})}function w({eyebrow:a,title:t,description:o,help:r,action:l}){return e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:a}),e.jsx(b,{label:`Explain ${a}`,title:t,content:r})]}),e.jsx("div",{className:"mt-2 text-lg text-white",children:t}),o?e.jsx("div",{className:"mt-1 max-w-2xl text-[12px] leading-5 text-white/50",children:o}):null]}),l?e.jsx("div",{className:"shrink-0",children:l}):null]})}function be(a){return a.weeklyLoad.map(t=>({week:t.weekKey.replace(/^20/,"'"),load:t.trainingLoad,hours:t.durationHours,loadPerHour:t.loadPerHour,high:Math.round(t.highPercentage*100),moderate:Math.round(t.moderatePercentage*100),low:Math.round(t.lowPercentage*100)}))}function we(a){return a.dailyLoad.map(t=>({date:t.dateKey.slice(5),load:t.trainingLoad,high:t.highIntensityMinutes,moderate:t.moderateIntensityMinutes,low:t.lowIntensityMinutes}))}function fe(a,t){return(t==="recent"?a.recentIntensityDistribution:a.intensityDistribution).map(r=>({...r,percent:Math.round(r.percentage*100),targetLow:Math.round(r.targetRange[0]*100),targetHigh:Math.round(r.targetRange[1]*100),fill:ue[r.key]??"#f8fafc"}))}function je(a,t){return(t==="recent"?a.recentZoneTotals:a.zoneTotals).map(r=>({...r,minutes:Math.round(r.seconds/60),percent:Math.round(r.percentage*100),fill:ge[r.key]??"#f8fafc"}))}function ve(a){const t=a.summary,o=t.acuteChronicRatio==null?45:Math.max(0,Math.min(100,100-Math.abs(t.acuteChronicRatio-1)*80));return[{axis:"Load",value:Math.min(100,t.acuteLoad7d/3)},{axis:"Base",value:Math.min(100,t.chronicWeeklyLoad28d/3)},{axis:"Balance",value:o},{axis:"Quality",value:Math.min(100,t.averageHeartRateCoverage*100)},{axis:"High",value:Math.min(100,t.highIntensityMinutes7d*1.8)},{axis:"VO2",value:t.vo2MaxDelta==null?50:Math.max(0,Math.min(100,50+t.vo2MaxDelta*10))}]}function ye({sessions:a}){return e.jsxs("div",{className:"overflow-hidden rounded-[8px] border border-white/8",children:[e.jsxs("div",{className:"grid grid-cols-[88px_minmax(118px,1fr)_64px_72px_72px] bg-white/[0.045] px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-white/42",children:[e.jsx("div",{children:"Date"}),e.jsx("div",{children:"Session"}),e.jsx("div",{children:"Load"}),e.jsx("div",{children:"Z4+Z5"}),e.jsx("div",{children:"HR"})]}),e.jsx("div",{className:"max-h-[370px] overflow-auto",children:a.slice(0,20).map(t=>e.jsxs("div",{className:"grid grid-cols-[88px_minmax(118px,1fr)_64px_72px_72px] border-t border-white/6 px-3 py-2 text-[12px] text-white/66",children:[e.jsx("div",{className:"text-white/52",children:t.dateKey.slice(5)}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-white/86",children:t.workoutTypeLabel}),e.jsxs("div",{className:"mt-0.5 text-[10px] text-white/42",children:[k(t.durationMinutes,0),"m ·"," ",t.confidence]})]}),e.jsx("div",{className:"text-white",children:k(t.trainingLoad,0)}),e.jsx("div",{children:O(t.highIntensityPercentage)}),e.jsxs("div",{children:[t.averageHr?Math.round(t.averageHr):"n/a",t.maxHr?`/${Math.round(t.maxHr)}`:""]})]},t.id))})]})}function Se(){const a=q(),t=Array.isArray(a.selectedUserIds)?a.selectedUserIds:[],[o,r]=x.useState("recent"),l=U({queryKey:["forge-training-load",...t],queryFn:async()=>(await Y(t)).trainingLoad}),i=l.data,c=pe((i==null?void 0:i.summary.readiness)??"insufficient_data"),f=x.useMemo(()=>i?be(i):[],[i]),C=x.useMemo(()=>i?we(i):[],[i]),n=x.useMemo(()=>i?fe(i,o):[],[o,i]),u=x.useMemo(()=>i?je(i,o):[],[o,i]),p=x.useMemo(()=>i?ve(i):[],[i]);if(l.isLoading)return e.jsx(G,{eyebrow:"Training Load",title:"Loading cardiovascular model",description:"Computing acute load, zone distribution, and target bands from workout evidence.",columns:3,blocks:8});if(l.isError||!i)return e.jsx(Q,{eyebrow:"Training Load",error:l.error??new Error("Training load data unavailable"),onRetry:()=>void l.refetch()});const{summary:d}=i;return e.jsxs("div",{className:"grid gap-5",children:[e.jsx(se,{eyebrow:"Health",entityKind:"habit",title:"Training Load",titleText:"Training Load",description:"Forge estimates cardiovascular training stress from workout duration, heart-rate response, adaptive HRR zones, and recent vitals so you can plan the next training block with clearer load and recovery context.",helpContent:h.hero,badge:`${d.sessionCount} sessions · ${d.reliableSessionCount} high-resolution`,actions:e.jsx(T,{tone:c.tone,children:c.label})}),e.jsxs("section",{className:"grid gap-4 lg:grid-cols-4",children:[M({label:"Acute load",value:k(d.acuteLoad7d,0),detail:`Last 7 days of internal load. ${c.text}`,help:h.acuteLoad,icon:$}),M({label:"Chronic base",value:k(d.chronicWeeklyLoad28d,0),detail:"Average weekly load across the last 28 days.",help:h.chronicBase,icon:F}),M({label:"ACWR",value:k(d.acuteChronicRatio,2),detail:"Acute load divided by chronic weekly load. Useful as a flag, not a verdict.",help:h.acwr,icon:W}),M({label:"VO2 max",value:d.vo2MaxLatest?k(d.vo2MaxLatest,1):"n/a",detail:d.vo2MaxDelta==null?"No delta available yet.":`${d.vo2MaxDelta>=0?"+":""}${d.vo2MaxDelta} since the first recent point.`,help:h.vo2max,icon:V})]}),e.jsx(me,{trainingLoad:i}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1.35fr)_minmax(320px,0.65fr)]",children:[e.jsxs(m,{className:"overflow-hidden",children:[e.jsx(w,{eyebrow:"Weekly load map",title:"Load, hours, and high-intensity share over the last 26 weeks.",description:"Load estimates internal stress; hours show volume; the red line shows how much of each week landed in zones 4 and 5.",help:h.weeklyMap,action:e.jsx(T,{tone:"meta",children:"TRIMP · HRR zones"})}),e.jsx("div",{className:"mt-5",children:e.jsx(_,{height:340,children:({width:s,height:g})=>e.jsxs(A,{data:f,width:s,height:g,children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:"trainingLoadFill",x1:"0",y1:"0",x2:"0",y2:"1",children:[e.jsx("stop",{offset:"0%",stopColor:"#38bdf8",stopOpacity:.38}),e.jsx("stop",{offset:"100%",stopColor:"#38bdf8",stopOpacity:.04})]})}),e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"week",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10}}),e.jsx(j,{yAxisId:"load",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:42}),e.jsx(j,{yAxisId:"pct",orientation:"right",domain:[0,100],tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:38}),e.jsx(z,{contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),e.jsx(X,{yAxisId:"load",type:"monotone",dataKey:"load",name:"Training load",stroke:"#38bdf8",fill:"url(#trainingLoadFill)",strokeWidth:2}),e.jsx(v,{yAxisId:"load",dataKey:"hours",name:"Hours",fill:"#a78bfa",radius:[3,3,0,0]}),e.jsx(E,{yAxisId:"pct",type:"monotone",dataKey:"high",name:"Z4+Z5 %",stroke:"#ef4444",strokeWidth:2.4,dot:{r:2}})]})})})]}),e.jsxs(m,{className:"overflow-hidden",children:[e.jsx(w,{eyebrow:"Adaptation radar",title:"Current signal balance",description:"A compact coach view of load, base, balance, data quality, high-intensity pressure, and VO2max movement.",help:h.adaptationRadar}),e.jsx("div",{className:"mt-4",children:e.jsx(_,{height:300,children:({width:s,height:g})=>e.jsxs(J,{data:p,width:s,height:g,children:[e.jsx(ee,{stroke:"rgba(255,255,255,0.12)"}),e.jsx(te,{dataKey:"axis",tick:{fill:"rgba(255,255,255,0.64)",fontSize:10}}),e.jsx(ae,{dataKey:"value",stroke:"#22c55e",fill:"#22c55e",fillOpacity:.24}),e.jsx(z,{contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}})]})})})]})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,0.8fr)_minmax(0,1.2fr)]",children:[e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Intensity target",title:"Distribution vs target bands",description:"Compare the selected time window with broad low, moderate, and high intensity bands.",help:h.intensityTarget,action:e.jsx("div",{className:"grid grid-cols-2 gap-1 rounded-[8px] border border-white/8 bg-white/[0.035] p-1",children:[["recent","28d"],["all","All"]].map(([s,g])=>e.jsx("button",{type:"button",className:`rounded-[6px] px-3 py-1.5 text-[12px] ${o===s?"bg-white/[0.12] text-white":"text-white/54"}`,onClick:()=>r(s),children:g},s))})}),e.jsx("div",{className:"mt-4 grid gap-3",children:n.map(s=>e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 text-[12px]",children:[e.jsx("span",{className:"text-white/74",children:s.label}),e.jsxs("span",{className:"text-white",children:[s.percent,"% · target ",s.targetLow,"-",s.targetHigh,"%"]})]}),e.jsxs("div",{className:"relative h-3 overflow-hidden rounded-full bg-white/[0.08]",children:[e.jsx("div",{className:"absolute inset-y-0 rounded-full bg-white/[0.12]",style:{left:`${s.targetLow}%`,width:`${Math.max(2,s.targetHigh-s.targetLow)}%`}}),e.jsx("div",{className:"relative h-full rounded-full",style:{width:`${Math.max(1,s.percent)}%`,background:s.fill}})]})]},s.key))}),e.jsx("div",{className:"mt-5 grid gap-2 rounded-[8px] border border-white/8 bg-white/[0.035] p-3 text-[12px] leading-5 text-white/54",children:i.targetModel.monitoringNotes.map(s=>e.jsxs("div",{className:"flex gap-2",children:[e.jsx(D,{className:"mt-0.5 size-3.5 shrink-0 text-[var(--primary)]"}),e.jsx("span",{children:s})]},s))})]}),e.jsxs(m,{children:[e.jsx(w,{eyebrow:"HR zones",title:`Detailed zone distribution for ${o==="recent"?"the last 28 days":"all available sessions"}.`,help:h.hrZones}),e.jsx("div",{className:"mt-4",children:e.jsx(_,{height:290,children:({width:s,height:g})=>e.jsxs(K,{data:u,width:s,height:g,children:[e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"label",interval:0,tick:{fill:"rgba(255,255,255,0.56)",fontSize:10}}),e.jsx(j,{tick:{fill:"rgba(255,255,255,0.56)",fontSize:10},width:38}),e.jsx(z,{formatter:(N,S)=>[S==="minutes"?`${N} min`:`${N}%`,S],contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),e.jsx(v,{dataKey:"minutes",name:"minutes",radius:[4,4,0,0],children:u.map(N=>e.jsx(ie,{fill:N.fill},N.key))})]})})})]})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]",children:[e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Daily load texture",title:"Easy, threshold, and high-intensity minutes against daily load.",help:h.dailyTexture}),e.jsx("div",{className:"mt-4",children:e.jsx(_,{height:310,children:({width:s,height:g})=>e.jsxs(A,{data:C,width:s,height:g,children:[e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"date",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10}}),e.jsx(j,{yAxisId:"minutes",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:38}),e.jsx(j,{yAxisId:"load",orientation:"right",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:38}),e.jsx(z,{contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),e.jsx(v,{yAxisId:"minutes",dataKey:"low",stackId:"zones",fill:"#22c55e",name:"low min"}),e.jsx(v,{yAxisId:"minutes",dataKey:"moderate",stackId:"zones",fill:"#f59e0b",name:"threshold min"}),e.jsx(v,{yAxisId:"minutes",dataKey:"high",stackId:"zones",fill:"#ef4444",name:"high min"}),e.jsx(E,{yAxisId:"load",type:"monotone",dataKey:"load",stroke:"#38bdf8",strokeWidth:2.2,dot:!1})]})})})]}),e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Session signals",title:"Recent workouts",help:h.sessionSignals,action:e.jsxs(T,{tone:"meta",children:[d.hardDayCount7d," hard days / 7d"]})}),e.jsx("div",{className:"mt-4",children:e.jsx(ye,{sessions:i.sessionSignals})})]})]}),e.jsxs("section",{className:"grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]",children:[e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Sport contribution",title:"Load by workout type",help:h.sportContribution}),e.jsx("div",{className:"mt-3 grid gap-3",children:i.activityBreakdown.slice(0,8).map(s=>e.jsxs("div",{className:"grid gap-2 rounded-[8px] border border-white/8 bg-white/[0.035] p-3 sm:grid-cols-[minmax(0,1fr)_76px_76px_76px]",children:[e.jsxs("div",{children:[e.jsx("div",{className:"truncate text-sm text-white",children:s.workoutTypeLabel}),e.jsxs("div",{className:"mt-1 text-[11px] text-white/46",children:[s.sessionCount," sessions ·"," ",s.activityFamilyLabel]})]}),e.jsxs("div",{className:"text-[12px] text-white/62",children:[e.jsxs("span",{className:"block text-white",children:[s.durationHours,"h"]}),"volume"]}),e.jsxs("div",{className:"text-[12px] text-white/62",children:[e.jsx("span",{className:"block text-white",children:s.trainingLoad}),"load"]}),e.jsxs("div",{className:"text-[12px] text-white/62",children:[e.jsx("span",{className:"block text-white",children:O(s.highPercentage)}),"high"]})]},s.workoutType))})]}),e.jsxs(m,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(P,{className:"size-4 text-amber-300"}),e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:"Interpretation guardrails"})]}),e.jsxs("div",{className:"mt-4 grid gap-3 text-[12px] leading-5 text-white/56",children:[e.jsx("p",{children:"Forge is estimating training stress from heart-rate reserve zones and a TRIMP-like load. This is good for trend decisions, but it is not a substitute for lactate testing, gas exchange thresholds, or coach-led periodization."}),e.jsx("p",{children:"Combat sports add sensor noise: wrist HR can miss short spikes during punching and clinch work. Treat high-intensity minutes as minimum evidence when the session had a lot of arm motion."}),e.jsx("p",{children:"The practical target is not maximum Z5. Keep hard combat sessions meaningful, then add easy aerobic base when the high-intensity share is already high."})]})]})]})]})}export{Se as TrainingLoadPage};
|
|
1
|
+
import{r as x,j as e,du as B,aL as D,bU as W,aH as Z,cg as P,bJ as $,dv as F,bK as V}from"./vendor-DHkYh85p.js";import{i as U}from"./state-B-4sS1xO.js";import{C as m,aq as b,c as T,u as q,S as G,E as Q,eL as Y}from"./index-CF4J4R9L.js";import{f as K,C as L,X as R,Y as j,T as z,B as v,e as A,a as X,b as E,j as J,P as ee,k as te,l as ae,g as ie}from"./charts-P7EVhIog.js";import{P as se}from"./page-hero-DRy5b2MU.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";function _({height:a,children:t}){const o=x.useRef(null),[r,l]=x.useState(0);return x.useEffect(()=>{const i=o.current;if(!i)return;const c=()=>{l(Math.max(0,Math.floor(i.getBoundingClientRect().width)))};if(c(),typeof ResizeObserver>"u")return window.addEventListener("resize",c),()=>window.removeEventListener("resize",c);const f=new ResizeObserver(c);return f.observe(i),()=>f.disconnect()},[]),e.jsx("div",{ref:o,style:{height:a},className:"min-w-0",children:r>24?t({width:r,height:a}):null})}const I=["below_z1","zone_1","zone_2","zone_3","zone_4","zone_5"],H={below_z1:"Below Z1",zone_1:"Z1",zone_2:"Z2",zone_3:"Z3",zone_4:"Z4",zone_5:"Z5"},re={below_z1:"#94a3b8",zone_1:"#38bdf8",zone_2:"#22c55e",zone_3:"#eab308",zone_4:"#f97316",zone_5:"#ef4444"},y={timeInZone:"Each block totals the minutes Forge can place into adaptive HRR zones from stored heart-rate samples. Weekly is the default planning view because it matches common training microcycles; monthly and daily views help detect longer trends or recent spikes.",smartMode:"Smart modes do not change the underlying data. They change the coaching lens: combat readiness prioritizes hard-day spacing and controlled high intensity, aerobic base prioritizes low-zone development, and endurance pro compares the distribution with pyramidal or polarized endurance planning patterns.",interpretation:"This paragraph explains what the selected mode concludes from the latest load balance, zone distribution, hard-day count, and data confidence. It is a planning summary, not a medical clearance.",drivers:"Drivers are the signals helping the selected mode: examples include enough easy/base work, controlled high-zone share, stable acute/chronic load, or improving data quality.",limiters:"Limiters are the signals that should constrain the next block. If Forge lists a limiter, the next target should usually solve that before adding more hard work.",targets:"Next targets translate the selected mode into a practical week and next workout. The range is intentionally bounded so training can progress without turning every good week into a maximal week."};function ne(a){return a.key==="combat_readiness"?"Combat":a.key==="aerobic_base"?"Base":"Endurance"}function oe(a){return a>=82?"signal":a>=65?"default":"meta"}function le(a){switch(a){case"vo2max_4x4":return"4x4 VO2max";case"zone_2_base":return"Zone 2 / base";case"technical_kickboxing":return"Technical kickboxing";case"easy_aerobic":return"Easy aerobic";case"recovery":return"Recovery";default:return a.replaceAll("_"," ")}}function de(a,t){return t==="daily"?a.bucketKey.slice(5):t==="monthly"?a.bucketKey.slice(2):a.bucketKey.replace(/^20/,"'")}function ce(a,t){const o=t==="daily"?30:12;return a.slice(-o).map(r=>({bucket:de(r,t),total:Math.round(r.durationMinutes),load:r.trainingLoad,confidence:r.confidence,...Object.fromEntries(I.map(l=>[l,r.zoneMinutes[l]??0]))}))}function he(a,t){return a.zoneTimeSeries[t]}function xe({mode:a}){return e.jsxs("div",{className:"grid gap-3 lg:grid-cols-2",children:[e.jsxs("div",{className:"rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(W,{className:"size-3.5"}),"Drivers",e.jsx(b,{label:"Explain training drivers",title:"Drivers",content:y.drivers})]}),e.jsx("div",{className:"mt-3 grid gap-2 text-[12px] leading-5 text-white/62",children:(a.drivers.length>0?a.drivers:["No positive driver is strong enough yet."]).map(t=>e.jsx("div",{children:t},t))})]}),e.jsxs("div",{className:"rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(Z,{className:"size-3.5"}),"Limiters",e.jsx(b,{label:"Explain training limiters",title:"Limiters",content:y.limiters})]}),e.jsx("div",{className:"mt-3 grid gap-2 text-[12px] leading-5 text-white/62",children:(a.limitingFactors.length>0?a.limitingFactors:["No major limiter in this mode right now."]).map(t=>e.jsx("div",{children:t},t))})]})]})}function me({trainingLoad:a}){const[t,o]=x.useState(a.trainingIntelligence.defaultMode),[r,l]=x.useState("weekly"),i=a.trainingIntelligence.modes.find(n=>n.key===t)??a.trainingIntelligence.modes[0],c=he(a,r),f=x.useMemo(()=>ce(c,r),[c,r]),C=c.slice(-8).reverse();return i?e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1.25fr)_minmax(340px,0.75fr)]",children:[e.jsxs(m,{className:"overflow-hidden",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:"Zone intelligence"}),e.jsx(b,{label:"Explain zone intelligence",title:"Time in zone",content:y.timeInZone})]}),e.jsx("div",{className:"mt-2 text-lg text-white",children:"Time in zone by training block"}),e.jsx("div",{className:"mt-1 max-w-2xl text-[12px] leading-5 text-white/50",children:"Weekly by default because most training plans are adjusted week by week. The stacked bars preserve the full zone split, while the table adds load rate, hard days, and data confidence."})]}),e.jsx("div",{className:"grid grid-cols-3 gap-1 rounded-[8px] border border-white/8 bg-white/[0.035] p-1",children:[["weekly","Week"],["monthly","Month"],["daily","90d"]].map(([n,u])=>e.jsx("button",{type:"button",className:`rounded-[6px] px-3 py-1.5 text-[12px] ${r===n?"bg-white/[0.12] text-white":"text-white/54"}`,onClick:()=>l(n),children:u},n))})]}),e.jsx("div",{className:"mt-5",children:e.jsx(_,{height:320,children:({width:n,height:u})=>e.jsxs(K,{data:f,width:n,height:u,children:[e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"bucket",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10}}),e.jsx(j,{tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:42}),e.jsx(z,{formatter:(p,d)=>[`${Number(p).toFixed(0)} min`,H[d]??String(d)],contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),I.map(p=>e.jsx(v,{dataKey:p,stackId:"zones",fill:re[p],name:p},p))]})})}),e.jsxs("div",{className:"mt-4 overflow-x-auto rounded-[8px] border border-white/8",children:[e.jsxs("div",{className:"grid min-w-[760px] grid-cols-[96px_72px_72px_repeat(6,64px)_72px_80px] bg-white/[0.045] px-3 py-2 text-[10px] uppercase tracking-[0.14em] text-white/42",children:[e.jsx("div",{children:"Block"}),e.jsx("div",{children:"Load"}),e.jsx("div",{children:"TRIMP/min"}),I.map(n=>e.jsx("div",{children:H[n]},n)),e.jsx("div",{children:"Hard"}),e.jsx("div",{children:"Quality"})]}),C.map(n=>e.jsxs("div",{className:"grid min-w-[760px] grid-cols-[96px_72px_72px_repeat(6,64px)_72px_80px] border-t border-white/8 px-3 py-2 text-[12px] text-white/62",children:[e.jsx("div",{className:"text-white",children:n.bucketKey}),e.jsx("div",{children:n.trainingLoad}),e.jsx("div",{children:n.loadPerMinute}),I.map(u=>e.jsx("div",{children:n.zoneMinutes[u]},u)),e.jsx("div",{children:n.hardDayCount}),e.jsx("div",{children:n.confidence})]},n.bucketKey))]})]}),e.jsxs(m,{className:"overflow-hidden",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:"Smart training mode"}),e.jsx(b,{label:"Explain smart training modes",title:"Training mode",content:y.smartMode})]}),e.jsx("div",{className:"mt-2 text-lg text-white",children:i.label})]}),e.jsxs(T,{tone:oe(i.score),children:[i.score,"/100"]})]}),e.jsx("div",{className:"mt-4 grid grid-cols-3 gap-1 rounded-[8px] border border-white/8 bg-white/[0.035] p-1",children:a.trainingIntelligence.modes.map(n=>e.jsx("button",{type:"button",className:`rounded-[6px] px-2 py-2 text-[12px] ${n.key===i.key?"bg-white/[0.12] text-white":"text-white/54"}`,onClick:()=>o(n.key),children:ne(n)},n.key))}),e.jsxs("div",{className:"mt-4 rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(B,{className:"size-3.5"}),"Interpretation",e.jsx(b,{label:"Explain this interpretation",title:"Interpretation",content:y.interpretation})]}),e.jsx("div",{className:"mt-3 text-[13px] leading-5 text-white/72",children:i.summary}),e.jsxs("div",{className:"mt-3 grid grid-cols-2 gap-2 text-[11px] text-white/50",children:[e.jsxs("div",{children:["Balance: ",i.loadBalance.status]}),e.jsxs("div",{children:["Confidence: ",i.confidence]}),e.jsxs("div",{children:["ACWR: ",i.loadBalance.acuteChronicRatio??"n/a"]}),e.jsxs("div",{children:["Baseline:"," ",i.loadBalance.latestWeekBaselineLoadRatio??"n/a","x"]})]})]}),e.jsx("div",{className:"mt-4",children:e.jsx(xe,{mode:i})}),e.jsxs("div",{className:"mt-4 grid gap-3 rounded-[8px] border border-white/8 bg-white/[0.035] p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-white/44",children:[e.jsx(D,{className:"size-3.5"}),"Next targets",e.jsx(b,{label:"Explain next training targets",title:"Next targets",content:y.targets})]}),e.jsxs("div",{className:"grid gap-2 text-[12px] leading-5 text-white/62",children:[e.jsxs("div",{children:["Next week: ",i.nextWeekTargets.totalMinutesRange[0],"-",i.nextWeekTargets.totalMinutesRange[1]," min · max"," ",i.nextWeekTargets.maxHardSessions," hard sessions · at least ",i.nextWeekTargets.minimumEasyMinutes," easy/base min."]}),e.jsxs("div",{children:["Next workout:"," ",e.jsx("span",{className:"text-white",children:le(i.nextWorkout.recommendedType)})," ","for ",i.nextWorkout.durationMinutesRange[0],"-",i.nextWorkout.durationMinutesRange[1]," min, ceiling"," ",i.nextWorkout.intensityCeiling,"."]}),e.jsx("div",{className:"text-white/50",children:i.nextWorkout.reason}),i.nextWeekTargets.warning?e.jsx("div",{className:"rounded-[6px] bg-amber-300/10 px-2 py-1 text-amber-100/82",children:i.nextWeekTargets.warning}):null]})]})]})]}):null}const ue={low:"#22c55e",moderate:"#f59e0b",high:"#ef4444"},ge={below_z1:"#94a3b8",zone_1:"#38bdf8",zone_2:"#22c55e",zone_3:"#eab308",zone_4:"#f97316",zone_5:"#ef4444"},h={hero:"Forge estimates cardiovascular training stress from stored workouts, heart-rate samples, adaptive heart-rate-reserve zones, and recent vitals. Use this page to decide whether the next training block should build aerobic base, hold load steady, sharpen intensity, or recover. The numbers support coaching decisions; they are not medical diagnosis.",acuteLoad:"Acute load is the last seven days of Forge's TRIMP-like internal load. It rises when workouts are longer, harder, or spend more time in high heart-rate zones. Compare it with chronic load before adding hard sessions.",chronicBase:"Chronic base is the average weekly load over the last 28 days. It is Forge's estimate of the current load you have recently proven you can absorb.",acwr:"ACWR is acute load divided by chronic weekly load. Values near 1.0 usually mean the current week resembles the recent base. High values ask for recovery checks; low values suggest underloading. Treat it as a flag, not a verdict.",vo2max:"VO2max is the latest available wearable estimate in ml/kg/min. Forge shows the recent change when enough points exist, but wearable VO2max can move with device model, terrain, heat, and workout type.",weeklyMap:"This chart combines weekly internal load, training hours, and the share of time in zones 4 and 5. It helps reveal whether fatigue comes from total volume, hard intensity, or both.",adaptationRadar:"The radar compresses six signals into one coach view: current load, base capacity, acute/chronic balance, heart-rate data quality, high-intensity pressure, and VO2max movement.",intensityTarget:"This compares your recent or all-time low, moderate, and high intensity distribution with broad target bands used in endurance and combat-sport conditioning. The target is a planning reference, not a rule.",hrZones:"These bars show minutes in each adaptive HRR zone. Zone 2 is commonly used for aerobic base, zones 4 and 5 for threshold and VO2max work, and below-zone time often reflects warm-up, recovery, or missing cardiovascular load.",dailyTexture:"Daily texture shows whether load spikes are coming from easy volume, threshold work, or high-intensity minutes. It is useful for spacing hard days and avoiding accidental clusters.",sessionSignals:"Recent workout rows expose the session evidence behind the summary: date, activity, training load, high-zone share, heart-rate response, and data confidence.",sportContribution:"Sport contribution groups load by workout type. In kickboxing and other combat sports, wrist heart rate can undercount short striking spikes, so compare this with how the session actually felt."};function O(a,t=0){return a==null||Number.isNaN(a)?"n/a":`${(a*100).toFixed(t)}%`}function k(a,t=0){return a==null||Number.isNaN(a)?"n/a":a.toFixed(t)}function pe(a){switch(a){case"productive":return{label:"Productive",tone:"signal",text:"Acute load is close to the current chronic base."};case"underloaded":return{label:"Underloaded",tone:"meta",text:"The recent week is below the four-week baseline."};case"overload_watch":return{label:"Watch load",tone:"default",text:"Acute load or strain is elevated enough to deserve recovery checks."};default:return{label:"Building signal",tone:"meta",text:"Forge needs more recent training evidence for a cleaner read."}}}function M({label:a,value:t,detail:o,help:r,icon:l}){return e.jsxs(m,{className:"relative min-h-[136px] overflow-hidden",children:[e.jsx("div",{className:"absolute right-3 top-3 rounded-[8px] border border-white/8 bg-white/[0.045] p-2 text-white/58",children:e.jsx(l,{className:"size-4"})}),e.jsxs("div",{className:"flex max-w-[80%] items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:a}),e.jsx(b,{label:`Explain ${a}`,title:a,content:r})]}),e.jsx("div",{className:"mt-4 font-display text-4xl leading-none text-white",children:t}),e.jsx("div",{className:"mt-3 max-w-[24rem] text-[12px] leading-5 text-white/56",children:o})]})}function w({eyebrow:a,title:t,description:o,help:r,action:l}){return e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:a}),e.jsx(b,{label:`Explain ${a}`,title:t,content:r})]}),e.jsx("div",{className:"mt-2 text-lg text-white",children:t}),o?e.jsx("div",{className:"mt-1 max-w-2xl text-[12px] leading-5 text-white/50",children:o}):null]}),l?e.jsx("div",{className:"shrink-0",children:l}):null]})}function be(a){return a.weeklyLoad.map(t=>({week:t.weekKey.replace(/^20/,"'"),load:t.trainingLoad,hours:t.durationHours,loadPerHour:t.loadPerHour,high:Math.round(t.highPercentage*100),moderate:Math.round(t.moderatePercentage*100),low:Math.round(t.lowPercentage*100)}))}function we(a){return a.dailyLoad.map(t=>({date:t.dateKey.slice(5),load:t.trainingLoad,high:t.highIntensityMinutes,moderate:t.moderateIntensityMinutes,low:t.lowIntensityMinutes}))}function fe(a,t){return(t==="recent"?a.recentIntensityDistribution:a.intensityDistribution).map(r=>({...r,percent:Math.round(r.percentage*100),targetLow:Math.round(r.targetRange[0]*100),targetHigh:Math.round(r.targetRange[1]*100),fill:ue[r.key]??"#f8fafc"}))}function je(a,t){return(t==="recent"?a.recentZoneTotals:a.zoneTotals).map(r=>({...r,minutes:Math.round(r.seconds/60),percent:Math.round(r.percentage*100),fill:ge[r.key]??"#f8fafc"}))}function ve(a){const t=a.summary,o=t.acuteChronicRatio==null?45:Math.max(0,Math.min(100,100-Math.abs(t.acuteChronicRatio-1)*80));return[{axis:"Load",value:Math.min(100,t.acuteLoad7d/3)},{axis:"Base",value:Math.min(100,t.chronicWeeklyLoad28d/3)},{axis:"Balance",value:o},{axis:"Quality",value:Math.min(100,t.averageHeartRateCoverage*100)},{axis:"High",value:Math.min(100,t.highIntensityMinutes7d*1.8)},{axis:"VO2",value:t.vo2MaxDelta==null?50:Math.max(0,Math.min(100,50+t.vo2MaxDelta*10))}]}function ye({sessions:a}){return e.jsxs("div",{className:"overflow-hidden rounded-[8px] border border-white/8",children:[e.jsxs("div",{className:"grid grid-cols-[88px_minmax(118px,1fr)_64px_72px_72px] bg-white/[0.045] px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-white/42",children:[e.jsx("div",{children:"Date"}),e.jsx("div",{children:"Session"}),e.jsx("div",{children:"Load"}),e.jsx("div",{children:"Z4+Z5"}),e.jsx("div",{children:"HR"})]}),e.jsx("div",{className:"max-h-[370px] overflow-auto",children:a.slice(0,20).map(t=>e.jsxs("div",{className:"grid grid-cols-[88px_minmax(118px,1fr)_64px_72px_72px] border-t border-white/6 px-3 py-2 text-[12px] text-white/66",children:[e.jsx("div",{className:"text-white/52",children:t.dateKey.slice(5)}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-white/86",children:t.workoutTypeLabel}),e.jsxs("div",{className:"mt-0.5 text-[10px] text-white/42",children:[k(t.durationMinutes,0),"m ·"," ",t.confidence]})]}),e.jsx("div",{className:"text-white",children:k(t.trainingLoad,0)}),e.jsx("div",{children:O(t.highIntensityPercentage)}),e.jsxs("div",{children:[t.averageHr?Math.round(t.averageHr):"n/a",t.maxHr?`/${Math.round(t.maxHr)}`:""]})]},t.id))})]})}function Se(){const a=q(),t=Array.isArray(a.selectedUserIds)?a.selectedUserIds:[],[o,r]=x.useState("recent"),l=U({queryKey:["forge-training-load",...t],queryFn:async()=>(await Y(t)).trainingLoad}),i=l.data,c=pe((i==null?void 0:i.summary.readiness)??"insufficient_data"),f=x.useMemo(()=>i?be(i):[],[i]),C=x.useMemo(()=>i?we(i):[],[i]),n=x.useMemo(()=>i?fe(i,o):[],[o,i]),u=x.useMemo(()=>i?je(i,o):[],[o,i]),p=x.useMemo(()=>i?ve(i):[],[i]);if(l.isLoading)return e.jsx(G,{eyebrow:"Training Load",title:"Loading cardiovascular model",description:"Computing acute load, zone distribution, and target bands from workout evidence.",columns:3,blocks:8});if(l.isError||!i)return e.jsx(Q,{eyebrow:"Training Load",error:l.error??new Error("Training load data unavailable"),onRetry:()=>void l.refetch()});const{summary:d}=i;return e.jsxs("div",{className:"grid gap-5",children:[e.jsx(se,{eyebrow:"Health",entityKind:"habit",title:"Training Load",titleText:"Training Load",description:"Forge estimates cardiovascular training stress from workout duration, heart-rate response, adaptive HRR zones, and recent vitals so you can plan the next training block with clearer load and recovery context.",helpContent:h.hero,badge:`${d.sessionCount} sessions · ${d.reliableSessionCount} high-resolution`,actions:e.jsx(T,{tone:c.tone,children:c.label})}),e.jsxs("section",{className:"grid gap-4 lg:grid-cols-4",children:[M({label:"Acute load",value:k(d.acuteLoad7d,0),detail:`Last 7 days of internal load. ${c.text}`,help:h.acuteLoad,icon:$}),M({label:"Chronic base",value:k(d.chronicWeeklyLoad28d,0),detail:"Average weekly load across the last 28 days.",help:h.chronicBase,icon:F}),M({label:"ACWR",value:k(d.acuteChronicRatio,2),detail:"Acute load divided by chronic weekly load. Useful as a flag, not a verdict.",help:h.acwr,icon:W}),M({label:"VO2 max",value:d.vo2MaxLatest?k(d.vo2MaxLatest,1):"n/a",detail:d.vo2MaxDelta==null?"No delta available yet.":`${d.vo2MaxDelta>=0?"+":""}${d.vo2MaxDelta} since the first recent point.`,help:h.vo2max,icon:V})]}),e.jsx(me,{trainingLoad:i}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1.35fr)_minmax(320px,0.65fr)]",children:[e.jsxs(m,{className:"overflow-hidden",children:[e.jsx(w,{eyebrow:"Weekly load map",title:"Load, hours, and high-intensity share over the last 26 weeks.",description:"Load estimates internal stress; hours show volume; the red line shows how much of each week landed in zones 4 and 5.",help:h.weeklyMap,action:e.jsx(T,{tone:"meta",children:"TRIMP · HRR zones"})}),e.jsx("div",{className:"mt-5",children:e.jsx(_,{height:340,children:({width:s,height:g})=>e.jsxs(A,{data:f,width:s,height:g,children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:"trainingLoadFill",x1:"0",y1:"0",x2:"0",y2:"1",children:[e.jsx("stop",{offset:"0%",stopColor:"#38bdf8",stopOpacity:.38}),e.jsx("stop",{offset:"100%",stopColor:"#38bdf8",stopOpacity:.04})]})}),e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"week",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10}}),e.jsx(j,{yAxisId:"load",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:42}),e.jsx(j,{yAxisId:"pct",orientation:"right",domain:[0,100],tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:38}),e.jsx(z,{contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),e.jsx(X,{yAxisId:"load",type:"monotone",dataKey:"load",name:"Training load",stroke:"#38bdf8",fill:"url(#trainingLoadFill)",strokeWidth:2}),e.jsx(v,{yAxisId:"load",dataKey:"hours",name:"Hours",fill:"#a78bfa",radius:[3,3,0,0]}),e.jsx(E,{yAxisId:"pct",type:"monotone",dataKey:"high",name:"Z4+Z5 %",stroke:"#ef4444",strokeWidth:2.4,dot:{r:2}})]})})})]}),e.jsxs(m,{className:"overflow-hidden",children:[e.jsx(w,{eyebrow:"Adaptation radar",title:"Current signal balance",description:"A compact coach view of load, base, balance, data quality, high-intensity pressure, and VO2max movement.",help:h.adaptationRadar}),e.jsx("div",{className:"mt-4",children:e.jsx(_,{height:300,children:({width:s,height:g})=>e.jsxs(J,{data:p,width:s,height:g,children:[e.jsx(ee,{stroke:"rgba(255,255,255,0.12)"}),e.jsx(te,{dataKey:"axis",tick:{fill:"rgba(255,255,255,0.64)",fontSize:10}}),e.jsx(ae,{dataKey:"value",stroke:"#22c55e",fill:"#22c55e",fillOpacity:.24}),e.jsx(z,{contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}})]})})})]})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,0.8fr)_minmax(0,1.2fr)]",children:[e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Intensity target",title:"Distribution vs target bands",description:"Compare the selected time window with broad low, moderate, and high intensity bands.",help:h.intensityTarget,action:e.jsx("div",{className:"grid grid-cols-2 gap-1 rounded-[8px] border border-white/8 bg-white/[0.035] p-1",children:[["recent","28d"],["all","All"]].map(([s,g])=>e.jsx("button",{type:"button",className:`rounded-[6px] px-3 py-1.5 text-[12px] ${o===s?"bg-white/[0.12] text-white":"text-white/54"}`,onClick:()=>r(s),children:g},s))})}),e.jsx("div",{className:"mt-4 grid gap-3",children:n.map(s=>e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 text-[12px]",children:[e.jsx("span",{className:"text-white/74",children:s.label}),e.jsxs("span",{className:"text-white",children:[s.percent,"% · target ",s.targetLow,"-",s.targetHigh,"%"]})]}),e.jsxs("div",{className:"relative h-3 overflow-hidden rounded-full bg-white/[0.08]",children:[e.jsx("div",{className:"absolute inset-y-0 rounded-full bg-white/[0.12]",style:{left:`${s.targetLow}%`,width:`${Math.max(2,s.targetHigh-s.targetLow)}%`}}),e.jsx("div",{className:"relative h-full rounded-full",style:{width:`${Math.max(1,s.percent)}%`,background:s.fill}})]})]},s.key))}),e.jsx("div",{className:"mt-5 grid gap-2 rounded-[8px] border border-white/8 bg-white/[0.035] p-3 text-[12px] leading-5 text-white/54",children:i.targetModel.monitoringNotes.map(s=>e.jsxs("div",{className:"flex gap-2",children:[e.jsx(D,{className:"mt-0.5 size-3.5 shrink-0 text-[var(--primary)]"}),e.jsx("span",{children:s})]},s))})]}),e.jsxs(m,{children:[e.jsx(w,{eyebrow:"HR zones",title:`Detailed zone distribution for ${o==="recent"?"the last 28 days":"all available sessions"}.`,help:h.hrZones}),e.jsx("div",{className:"mt-4",children:e.jsx(_,{height:290,children:({width:s,height:g})=>e.jsxs(K,{data:u,width:s,height:g,children:[e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"label",interval:0,tick:{fill:"rgba(255,255,255,0.56)",fontSize:10}}),e.jsx(j,{tick:{fill:"rgba(255,255,255,0.56)",fontSize:10},width:38}),e.jsx(z,{formatter:(N,S)=>[S==="minutes"?`${N} min`:`${N}%`,S],contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),e.jsx(v,{dataKey:"minutes",name:"minutes",radius:[4,4,0,0],children:u.map(N=>e.jsx(ie,{fill:N.fill},N.key))})]})})})]})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]",children:[e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Daily load texture",title:"Easy, threshold, and high-intensity minutes against daily load.",help:h.dailyTexture}),e.jsx("div",{className:"mt-4",children:e.jsx(_,{height:310,children:({width:s,height:g})=>e.jsxs(A,{data:C,width:s,height:g,children:[e.jsx(L,{stroke:"rgba(255,255,255,0.08)",vertical:!1}),e.jsx(R,{dataKey:"date",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10}}),e.jsx(j,{yAxisId:"minutes",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:38}),e.jsx(j,{yAxisId:"load",orientation:"right",tick:{fill:"rgba(255,255,255,0.54)",fontSize:10},width:38}),e.jsx(z,{contentStyle:{background:"rgba(6,10,18,0.96)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:8,color:"white"}}),e.jsx(v,{yAxisId:"minutes",dataKey:"low",stackId:"zones",fill:"#22c55e",name:"low min"}),e.jsx(v,{yAxisId:"minutes",dataKey:"moderate",stackId:"zones",fill:"#f59e0b",name:"threshold min"}),e.jsx(v,{yAxisId:"minutes",dataKey:"high",stackId:"zones",fill:"#ef4444",name:"high min"}),e.jsx(E,{yAxisId:"load",type:"monotone",dataKey:"load",stroke:"#38bdf8",strokeWidth:2.2,dot:!1})]})})})]}),e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Session signals",title:"Recent workouts",help:h.sessionSignals,action:e.jsxs(T,{tone:"meta",children:[d.hardDayCount7d," hard days / 7d"]})}),e.jsx("div",{className:"mt-4",children:e.jsx(ye,{sessions:i.sessionSignals})})]})]}),e.jsxs("section",{className:"grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]",children:[e.jsxs(m,{children:[e.jsx(w,{eyebrow:"Sport contribution",title:"Load by workout type",help:h.sportContribution}),e.jsx("div",{className:"mt-3 grid gap-3",children:i.activityBreakdown.slice(0,8).map(s=>e.jsxs("div",{className:"grid gap-2 rounded-[8px] border border-white/8 bg-white/[0.035] p-3 sm:grid-cols-[minmax(0,1fr)_76px_76px_76px]",children:[e.jsxs("div",{children:[e.jsx("div",{className:"truncate text-sm text-white",children:s.workoutTypeLabel}),e.jsxs("div",{className:"mt-1 text-[11px] text-white/46",children:[s.sessionCount," sessions ·"," ",s.activityFamilyLabel]})]}),e.jsxs("div",{className:"text-[12px] text-white/62",children:[e.jsxs("span",{className:"block text-white",children:[s.durationHours,"h"]}),"volume"]}),e.jsxs("div",{className:"text-[12px] text-white/62",children:[e.jsx("span",{className:"block text-white",children:s.trainingLoad}),"load"]}),e.jsxs("div",{className:"text-[12px] text-white/62",children:[e.jsx("span",{className:"block text-white",children:O(s.highPercentage)}),"high"]})]},s.workoutType))})]}),e.jsxs(m,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(P,{className:"size-4 text-amber-300"}),e.jsx("div",{className:"font-label text-[10px] uppercase tracking-[0.18em] text-white/45",children:"Interpretation guardrails"})]}),e.jsxs("div",{className:"mt-4 grid gap-3 text-[12px] leading-5 text-white/56",children:[e.jsx("p",{children:"Forge is estimating training stress from heart-rate reserve zones and a TRIMP-like load. This is good for trend decisions, but it is not a substitute for lactate testing, gas exchange thresholds, or coach-led periodization."}),e.jsx("p",{children:"Combat sports add sensor noise: wrist HR can miss short spikes during punching and clinch work. Treat high-intensity minutes as minimum evidence when the session had a lot of arm motion."}),e.jsx("p",{children:"The practical target is not maximum Z5. Keep hard combat sessions meaningful, then add easy aerobic base when the high-intensity share is already high."})]})]})]})]})}export{Se as TrainingLoadPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./vendor-DHkYh85p.js";import{i as x}from"./state-B-4sS1xO.js";import{P as v}from"./page-hero-
|
|
1
|
+
import{j as e}from"./vendor-DHkYh85p.js";import{i as x}from"./state-B-4sS1xO.js";import{P as v}from"./page-hero-DRy5b2MU.js";import{u as f,L as j,E as b,C as y,c as l,Z as N,bN as M,cy as k}from"./index-CF4J4R9L.js";import{S as o,f as C,m as D,M as u}from"./daily-metrics-dashboard-B3cqJgDt.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";import"./charts-P7EVhIog.js";const R=["restingHeartRate","heartRateVariabilitySDNN","vo2Max","oxygenSaturation","bodyMass","stepCount"];function p(t,a){return a.map(r=>({...r,metrics:t.filter(s=>s.category===r.category)}))}function S(t){return t}function V({metrics:t}){if(!t.summary.hasData||t.metrics.length===0)return null;const a=p(t.metrics,t.summary.categoryBreakdown),r=t.metrics.find(n=>n.metric==="devrageSwearCount")??null,s=t.metrics.find(n=>n.metric==="swearingMessagePercent")??null;return e.jsxs("section",{className:"grid gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/38",children:"Psyche metrics"}),e.jsx("div",{className:"mt-1 text-2xl font-semibold text-white",children:"Conversation tone alongside body signals"})]}),e.jsxs(l,{className:"bg-amber-200/10 text-amber-50",children:[t.summary.trackedDays," tracked days"]})]}),e.jsxs("div",{className:"grid gap-4 xl:grid-cols-2",children:[e.jsx(o,{title:"Devrage count",description:"Daily user-message swear count from stored conversation history.",metric:r}),e.jsx(o,{title:"Swearing rate",description:"Share of scanned user messages that contained at least one tracked swear.",metric:s})]}),e.jsx(u,{groups:a})]})}function I(){var h;const t=f(),a=x({queryKey:["forge-vitals-view",...t.selectedUserIds],queryFn:async()=>(await M(t.selectedUserIds)).vitals}),r=x({queryKey:["forge-psyche-metrics-vitals-view"],queryFn:async()=>(await k()).metrics});if(a.isLoading)return e.jsx(j,{title:"Loading body signals",description:"Reading recent HealthKit body metrics, recovery signals, and daily aggregates."});if(a.isError||!a.data)return e.jsx(b,{error:a.error??new Error("Vitals data unavailable"),onRetry:()=>void a.refetch()});const s=a.data,n=s.metrics.map(S),c=R.map(i=>n.find(d=>d.metric===i)??null),m=s.summary.categoryBreakdown,w=p(n,m),g=!r.isError&&((h=r.data)!=null&&h.summary.hasData)?r.data:null;return e.jsxs("div",{className:"mx-auto grid w-full max-w-[1380px] gap-5",children:[e.jsx(v,{title:"Vitals",description:"Forge now keeps a daily body-signals layer across recovery, cardio fitness, breathing, composition, temperature, and activity. Use this surface to spot drift early, not just admire numbers late.",badge:`${s.summary.metricCount} live metrics`}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-4",children:[e.jsx(o,{title:"Recovery pulse",description:"Resting heart rate and HRV are the fastest read on load, stress, and whether today needs a gentler edge.",metric:c[0]??c[1]}),e.jsx(o,{title:"Cardio engine",description:"VO2 max and walking heart rate show whether baseline fitness is improving or whether your effort is costing more than usual.",metric:c[2]}),e.jsx(o,{title:"Breath and oxygen",description:"Respiratory rate and oxygen saturation help catch nights or stretches where recovery quality starts to slip.",metric:c[3]}),e.jsx(o,{title:"Body composition",description:"Mass and composition stay close to the daily story so progress is visible without flattening everything into weight alone.",metric:c[4]})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1.1fr)_minmax(340px,0.9fr)]",children:[e.jsxs(y,{className:"overflow-hidden rounded-[30px] border-white/8 bg-[radial-gradient(circle_at_top_left,rgba(108,99,255,0.16),transparent_36%),linear-gradient(180deg,rgba(15,19,38,0.98),rgba(9,13,28,0.98))] p-6",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Coverage"}),e.jsxs("div",{className:"text-2xl font-semibold text-white",children:[s.summary.trackedDays," tracked days across ",s.summary.metricCount," metrics"]}),e.jsx("div",{className:"max-w-3xl text-sm leading-6 text-white/58",children:"The companion is compressing HealthKit into daily signal bands, so what you see here is designed for decisions: how your recovery is trending, where your physiology is changing, and which body systems are actually being observed consistently."})]}),e.jsxs(l,{className:"bg-white/[0.08] text-white/72",children:["Latest snapshot ",C(s.summary.latestDateKey)]})]}),e.jsx("div",{className:"mt-5 grid gap-3 md:grid-cols-2 xl:grid-cols-3",children:m.map(i=>{const d=D(i.category);return e.jsxs("div",{className:N("rounded-[22px] border bg-white/[0.03] p-4",d.ring),children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx(l,{className:d.badge,children:i.category}),e.jsxs("div",{className:"text-xs text-white/44",children:[i.coverageDays," days"]})]}),e.jsx("div",{className:"mt-3 text-2xl font-semibold text-white",children:i.metricCount}),e.jsxs("div",{className:"mt-1 text-sm text-white/58",children:["active metric",i.metricCount===1?"":"s"]})]},i.category)})})]}),e.jsx(y,{className:"rounded-[30px] border-white/8 bg-[linear-gradient(180deg,rgba(13,19,37,0.96),rgba(10,14,30,0.96))] p-6",children:e.jsxs("div",{className:"grid gap-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Daily interpretation"}),e.jsx("div",{className:"text-lg font-semibold text-white",children:"Body signals should feel operational, not medical-chart dead."}),e.jsxs("div",{className:"grid gap-3 text-sm leading-6 text-white/58",children:[e.jsx("div",{children:"Lower resting heart rate paired with stable or rising HRV usually means recovery is holding."}),e.jsx("div",{children:"Rising walking heart rate, falling HRV, or a jump in respiratory rate usually means you are carrying more load than the calendar admits."}),e.jsx("div",{children:"Composition and temperature metrics move slower, but they make the fast signals easier to trust because you can see the surrounding body context."})]}),e.jsxs("div",{className:"mt-2 rounded-[22px] border border-white/8 bg-white/[0.035] p-4 text-sm text-white/70",children:[s.summary.latestMetricCount," metrics updated on the latest tracked day."]})]})})]}),e.jsx(u,{groups:w}),g?e.jsx(V,{metrics:g}):null]})}export{I as VitalsPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./vendor-DHkYh85p.js";import{j as h,i as u,k as y}from"./state-B-4sS1xO.js";import{F as v}from"./flagship-signal-deck-
|
|
1
|
+
import{j as e}from"./vendor-DHkYh85p.js";import{j as h,i as u,k as y}from"./state-B-4sS1xO.js";import{F as v}from"./flagship-signal-deck-cmy82b8_.js";import{P as f,fm as g,i as j,S as k,E as x,C as o,c as w,B as N,fn as b}from"./index-CF4J4R9L.js";import{P as R}from"./page-hero-DRy5b2MU.js";import{R as S,f as z,X as $,Y as P,B as X}from"./charts-P7EVhIog.js";import"./motion-BeD44FeG.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";function M(){var c;const{t}=f(),n=h(),l=u({queryKey:["forge-weekly-review"],queryFn:b}),d=y({mutationFn:g,onSuccess:async()=>{await Promise.all([n.invalidateQueries({queryKey:["forge-weekly-review"]}),n.invalidateQueries({queryKey:["forge-xp-metrics"]}),n.invalidateQueries({queryKey:["forge-reward-ledger"]}),j(n),n.invalidateQueries({queryKey:["activity-archive"]})])}}),i=(c=l.data)==null?void 0:c.review;if(l.isLoading)return e.jsx(k,{});if(l.isError)return e.jsx(x,{eyebrow:t("common.weeklyReview.heroEyebrow"),error:l.error,onRetry:()=>void l.refetch()});if(!i)return e.jsx(x,{eyebrow:t("common.weeklyReview.heroEyebrow"),error:new Error("Forge returned an empty weekly review payload."),onRetry:()=>void l.refetch()});const r=i.wins[0]??null,a=i.calibration.find(s=>s.mode==="recover")??i.calibration[0]??null,m=i.calibration.find(s=>s.mode==="accelerate")??i.calibration[0]??null,p=[{id:"week",label:"This week",title:`${i.momentumSummary.totalXp} XP with ${i.momentumSummary.focusHours} focus hours`,detail:`Peak window: ${i.momentumSummary.peakWindow}. Efficiency score is holding at ${i.momentumSummary.efficiencyScore}.`,badge:i.windowLabel},{id:"wins",label:"Wins",title:(r==null?void 0:r.title)??t("common.weeklyReview.noWin"),detail:(r==null?void 0:r.summary)??t("common.weeklyReview.noWinDetail"),badge:r?`+${r.rewardXp} xp`:`${i.wins.length} wins`},{id:"recovery",label:"Recovery",title:(a==null?void 0:a.title)??t("common.weeklyReview.noRecovery"),detail:(a==null?void 0:a.note)??t("common.weeklyReview.noRecoveryDetail"),badge:(a==null?void 0:a.mode)??"maintain"},{id:"next-intent",label:"Next intent",title:(m==null?void 0:m.title)??i.reward.title,detail:(m==null?void 0:m.note)??i.reward.summary,badge:`+${i.reward.rewardXp} xp`}];return e.jsxs("div",{className:"grid gap-5",children:[e.jsx(R,{title:"Weekly Review",description:`${i.windowLabel}. ${t("common.weeklyReview.heroDescription")}`,badge:`${i.momentumSummary.totalXp} xp`}),e.jsxs("section",{className:"grid gap-5 xl:grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)]",children:[e.jsxs("div",{className:"grid gap-5",children:[e.jsxs(o,{children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:t("common.weeklyReview.sectionMomentum")}),e.jsx("div",{className:"mt-4 h-64",children:e.jsx(S,{width:"100%",height:"100%",children:e.jsxs(z,{data:i.chart,children:[e.jsx($,{dataKey:"label",tick:{fill:"rgba(255,255,255,0.42)",fontSize:11}}),e.jsx(P,{hide:!0}),e.jsx(X,{dataKey:"xp",fill:"#c0c1ff",radius:[8,8,0,0]})]})})}),e.jsxs("div",{className:"mt-4 grid gap-3 md:grid-cols-3",children:[e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/40",children:"XP"}),e.jsx("div",{className:"mt-2 text-2xl text-white",children:i.momentumSummary.totalXp})]}),e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Focus hours"}),e.jsx("div",{className:"mt-2 text-2xl text-white",children:i.momentumSummary.focusHours})]}),e.jsxs("div",{className:"rounded-[18px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Peak window"}),e.jsx("div",{className:"mt-2 text-2xl text-white",children:i.momentumSummary.peakWindow})]})]})]}),e.jsxs(o,{children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:t("common.weeklyReview.sectionGoals")}),e.jsx("div",{className:"mt-4 grid gap-3",children:i.calibration.map(s=>e.jsxs("div",{className:"overflow-hidden rounded-[20px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-3",children:[e.jsx("div",{className:"min-w-0 flex-1 font-medium text-white",children:s.title}),e.jsx(w,{className:"max-w-[9rem] shrink-0 self-start",children:s.mode})]}),e.jsx("div",{className:"mt-3 text-sm text-white/58",children:s.note})]},s.id))})]})]}),e.jsxs("div",{className:"grid gap-5",children:[e.jsxs(o,{children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/45",children:t("common.weeklyReview.sectionWins")}),e.jsx("div",{className:"mt-4 grid gap-3",children:i.wins.map(s=>e.jsxs("div",{className:"overflow-hidden rounded-[20px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-3",children:[e.jsx("div",{className:"min-w-0 flex-1 font-medium text-white",children:s.title}),e.jsxs(w,{className:"max-w-[8rem] shrink-0 self-start text-emerald-300",children:["+",s.rewardXp," xp"]})]}),e.jsx("div",{className:"mt-2 text-sm text-white/58",children:s.summary})]},s.id))})]}),e.jsxs(o,{children:[e.jsx("h2",{className:"font-display text-3xl text-white",children:i.reward.title}),e.jsx("p",{className:"mt-3 text-sm leading-7 text-white/60",children:i.reward.summary}),e.jsxs("div",{className:"mt-4 rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/40",children:t("common.weeklyReview.completionBonus")}),e.jsxs("div",{className:"mt-2 text-3xl text-[var(--primary)]",children:["+",i.reward.rewardXp," XP"]})]}),e.jsx(N,{className:"mt-4 w-full",disabled:i.completion.finalized,pending:d.isPending,pendingLabel:t("common.weeklyReview.finalizePending"),onClick:async()=>{await d.mutateAsync()},children:i.completion.finalized?t("common.weeklyReview.finalized"):t("common.weeklyReview.finalize")}),e.jsx("div",{className:"mt-3 text-sm leading-6 text-white/58",children:i.completion.finalized?`${t("common.weeklyReview.finalizedDetail")} ${i.completion.finalizedBy?`By ${i.completion.finalizedBy}. `:""}${i.completion.finalizedAt?new Date(i.completion.finalizedAt).toLocaleString():""}`.trim():i.reward.summary})]})]})]}),e.jsx(v,{eyebrow:t("common.weeklyReview.summaryEyebrow"),title:t("common.weeklyReview.summaryTitle"),description:t("common.weeklyReview.summaryDescription"),items:p})]})}export{M as WeeklyReviewPage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as d,j as e,bL as B,dx as ue,bJ as pe,bU as be,aG as je,du as ne,dy as ve,bI as fe,bs as we,dz as Ne,cL as ye}from"./vendor-DHkYh85p.js";import{j as ke,i as Ce,k as u}from"./state-B-4sS1xO.js";import{P as Ge}from"./page-hero-DRy5b2MU.js";import{u as Se,eW as D,eX as Fe,eY as Me,eZ as Le,e_ as Pe,e$ as $e,f0 as Be,f1 as Te,L as Ee,E as Ie,C as h,c as f,T as Ae,I as m,B as p,Z as de,f2 as Ke}from"./index-CF4J4R9L.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";function H(s){return typeof s=="number"&&Number.isFinite(s)?s:null}function v(s){return typeof s=="string"&&s.trim()?s:null}function l(s,r=0){const i=H(s);return i===null?"n/a":i.toFixed(r)}function le(s,r=0){const i=H(s);return i===null?"n/a":`${i>0?"+":""}${i.toFixed(r)}`}function g(s){const r=H(s);return r===null?"n/a":`${r.toFixed(1)}/10`}function Qe(s){return Array.isArray(s)?s.filter(r=>!!r&&typeof r=="object"&&!Array.isArray(r)):[]}function x({label:s,value:r,detail:i,icon:b,tone:o="default"}){const w=o==="green"?"bg-emerald-300/10 text-emerald-100":o==="amber"?"bg-amber-300/10 text-amber-100":o==="rose"?"bg-rose-300/10 text-rose-100":"bg-indigo-300/10 text-indigo-100";return e.jsxs(h,{className:"grid gap-4 border-white/8 bg-white/[0.045] p-5",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:de("rounded-2xl p-2.5",w),children:e.jsx(b,{className:"size-5"})}),e.jsx("div",{className:"text-right text-[11px] uppercase tracking-[0.16em] text-white/38",children:s})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-3xl font-semibold text-white",children:r}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/58",children:i})]})]})}function oe({meal:s,onLogAgain:r,pending:i=!1}){const b=s.items.slice(0,3).map(o=>o.name).join(", ");return e.jsxs("div",{className:"grid gap-2 rounded-[22px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium text-white",children:s.mealLabel??"Meal"}),e.jsx("div",{className:"truncate text-xs text-white/42",children:b||s.notes||"No items"})]}),e.jsxs(f,{className:"bg-white/[0.08] text-white/70",children:[s.totals.calories.toFixed(0)," kcal"]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-2 text-xs text-white/56",children:[e.jsxs("span",{children:[s.totals.proteinGrams.toFixed(0),"g protein"]}),e.jsxs("span",{children:[s.totals.fiberGrams.toFixed(0),"g fiber"]}),e.jsx("span",{children:s.confirmationState})]}),r?e.jsxs(p,{type:"button",size:"sm",variant:"ghost",pending:i,onClick:()=>r(s),children:[e.jsx(ye,{className:"size-4"}),"Log again"]}):null]})}function ce({food:s,onLog:r,pending:i}){return e.jsxs("div",{className:"grid gap-3 rounded-[22px] border border-white/8 bg-white/[0.04] p-4 md:grid-cols-[minmax(0,1fr)_auto] md:items-center",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium text-white",children:s.name}),e.jsx("div",{className:"mt-1 truncate text-xs text-white/44",children:[s.brand,s.servingLabel,s.source].filter(Boolean).join(" · ")}),e.jsxs("div",{className:"mt-3 flex flex-wrap gap-2 text-xs text-white/56",children:[e.jsxs("span",{children:[l(s.calories)," kcal"]}),e.jsxs("span",{children:[l(s.proteinGrams),"g protein"]}),e.jsxs("span",{children:[l(s.fiberGrams),"g fiber"]}),s.novaGroup?e.jsxs("span",{children:["NOVA ",s.novaGroup]}):null]})]}),e.jsxs(p,{type:"button",size:"sm",variant:"secondary",pending:i,onClick:()=>r(s),children:[e.jsx(B,{className:"size-4"}),"Log"]})]})}function Oe(){var re;const s=Se(),r=ke(),i=s.selectedUserIds,b=d.useMemo(()=>["forge-weight-loss-view",...i],[i]),[o,w]=d.useState(""),[T,E]=d.useState(""),[U,I]=d.useState(""),[A,me]=d.useState(""),[K,ge]=d.useState(""),[k,V]=d.useState(""),[C,O]=d.useState(""),[G,Z]=d.useState(""),[S,J]=d.useState(""),j=Ce({queryKey:b,queryFn:async()=>(await Ke(i)).weightLoss}),N=()=>r.invalidateQueries({queryKey:b}),X=u({mutationFn:async()=>D({mealLabel:"Quick log",source:"manual",confirmationState:"confirmed",notes:o.trim()||null,items:[{name:o.trim()||"Manual food entry",quantity:1,unit:"entry",calories:Number(T)||null,proteinGrams:Number(U)||null,confidence:.55,tags:["quick-log"]}]},i),onSuccess:()=>{w(""),E(""),I(""),N()}}),Y=u({mutationFn:async()=>Fe({text:o,mealLabel:"ChatGPT parsed meal",userIds:i}),onSuccess:()=>{w(""),E(""),I(""),N()}}),Q=u({mutationFn:async()=>(await Me({query:A,userIds:i})).foods}),q=u({mutationFn:async()=>(await Le({barcode:K,userIds:i})).food}),F=u({mutationFn:async t=>D({mealLabel:"Catalog food",source:t.barcode?"barcode":"manual",confirmationState:"confirmed",items:[{name:t.name,brand:t.brand,quantity:1,unit:t.servingLabel??"serving",calories:t.calories,proteinGrams:t.proteinGrams,carbohydrateGrams:t.carbohydrateGrams,fatGrams:t.fatGrams,fiberGrams:t.fiberGrams,sugarGrams:t.sugarGrams,sodiumMg:t.sodiumMg,potassiumMg:t.potassiumMg,caffeineMg:t.caffeineMg,alcoholGrams:t.alcoholGrams,glycemicIndex:t.glycemicIndex,novaGroup:t.novaGroup,tags:t.tags,confidence:.82}]},i),onSuccess:()=>{N()}}),M=u({mutationFn:async t=>D({mealLabel:t.mealLabel??"Saved meal",source:"saved_meal",confirmationState:"confirmed",notes:t.notes,items:t.items.map(a=>({name:a.name,brand:a.brand,quantity:a.quantity,unit:a.unit,calories:a.calories,proteinGrams:a.proteinGrams,carbohydrateGrams:a.carbohydrateGrams,fatGrams:a.fatGrams,fiberGrams:a.fiberGrams,sugarGrams:a.sugarGrams,sodiumMg:a.sodiumMg,potassiumMg:a.potassiumMg,caffeineMg:a.caffeineMg,alcoholGrams:a.alcoholGrams,glycemicIndex:a.glycemicIndex,novaGroup:a.novaGroup,fermented:a.fermented,probiotic:a.probiotic,fodmapLevel:a.fodmapLevel,tags:a.tags,confidence:a.confidence??.85}))},i),onSuccess:()=>{N()}}),ee=u({mutationFn:async()=>{await Promise.all([k.trim()?Pe({weightKg:Number(k)},i):Promise.resolve(),C.trim()?$e({energy:Number(C),timeRelation:"current"},i):Promise.resolve(),G.trim()?Be({bloating:Number(G)},i):Promise.resolve(),S.trim()?Te({aestheticScore:Number(S)},i):Promise.resolve()])},onSuccess:()=>{V(""),O(""),Z(""),J(""),N()}});if(j.isLoading)return e.jsx(Ee,{title:"Loading weight-loss signals",description:"Combining food logs, HealthKit, movement, workouts, body check-ins, subjective state, and gut signals."});if(j.isError||!j.data)return e.jsx(Ie,{error:j.error??new Error("Weight-loss view unavailable"),onRetry:()=>void j.refetch()});const n=j.data,c=n.todayLedger,y=c.totals,_=y.calories,z=c.targetCalories-_,xe=c.targetCalories>0?Math.min(140,Math.max(0,_/c.targetCalories*100)):0,L=n.energyModel,te=n.weightTrend,P=n.foodQuality,W=n.trainingFuel,R=n.subjective,se=n.gut,$=n.dataQuality,ae=Qe(n.hypotheses),he=Q.data??[],ie=q.data??null;return e.jsxs("div",{className:"mx-auto grid w-full max-w-[1500px] gap-5",children:[e.jsx(Ge,{title:"Weight Loss",description:"A Forge-native body composition lab: calories and protein, but also sport fuel, visual look, energy, gut comfort, cravings, and testable food hypotheses.",badge:`${n.summary.loggedMealCount} food logs`}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-4",children:[e.jsx(x,{label:"Today",value:`${_.toFixed(0)} kcal`,detail:`${z.toFixed(0)} kcal remaining against a ${c.targetCalories.toFixed(0)} kcal target.`,icon:B,tone:z>=0?"green":"rose"}),e.jsx(x,{label:"Protein",value:`${y.proteinGrams.toFixed(0)}g`,detail:`${n.target.proteinGramsTarget.toFixed(0)}g target. Forge treats protein as the anchor for dieting without looking flat or under-recovered.`,icon:ue}),e.jsx(x,{label:"Energy gap",value:le(L.estimatedDailyEnergyBalanceKcal),detail:`TDEE estimate ${l(L.estimatedTdeeKcal)} kcal, movement ${l(L.movementCaloriesKcal)} kcal, active burn ${l(L.activeBurnKcal)} kcal.`,icon:pe,tone:"amber"}),e.jsx(x,{label:"Weight trend",value:le(te.sevenDayRateKg,2),detail:`Latest ${l(te.latestWeightKg,1)} kg. Trend uses check-ins, not noisy single weigh-ins.`,icon:be,tone:"green"})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1.08fr)_minmax(360px,0.92fr)]",children:[e.jsxs(h,{className:"grid gap-5 border-white/8 bg-[radial-gradient(circle_at_top_left,rgba(52,211,153,0.14),transparent_34%),linear-gradient(180deg,rgba(14,21,34,0.98),rgba(8,12,24,0.98))] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Quick capture"}),e.jsx("h2",{className:"mt-1 text-2xl font-semibold text-white",children:"Food, photo description, or rough meal"}),e.jsx("p",{className:"mt-2 max-w-3xl text-sm leading-6 text-white/58",children:"Use natural language for ChatGPT parsing through the `openai-codex` subscription connection, or log manually when you only know rough calories."})]}),e.jsx(f,{className:"bg-emerald-300/10 text-emerald-50",children:"subscription parser"})]}),e.jsx(Ae,{value:o,onChange:t=>w(t.target.value),placeholder:"Example: 3 eggs, two slices of sourdough, Greek yogurt with honey, espresso. Felt sharp for training but a bit bloated later."}),e.jsxs("div",{className:"grid gap-3 md:grid-cols-2",children:[e.jsx(m,{inputMode:"decimal",value:T,onChange:t=>E(t.target.value),placeholder:"Manual kcal"}),e.jsx(m,{inputMode:"decimal",value:U,onChange:t=>I(t.target.value),placeholder:"Manual protein g"})]}),e.jsxs("div",{className:"flex flex-wrap gap-3",children:[e.jsxs(p,{type:"button",pending:Y.isPending,disabled:!o.trim(),onClick:()=>Y.mutate(),children:[e.jsx(je,{className:"size-4"}),"Parse with ChatGPT"]}),e.jsxs(p,{type:"button",variant:"secondary",pending:X.isPending,disabled:!o.trim()&&!T.trim(),onClick:()=>X.mutate(),children:[e.jsx(B,{className:"size-4"}),"Manual log"]})]}),n.recentMeals.length>0?e.jsxs("div",{className:"grid gap-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Saved and recent meals"}),e.jsx("div",{className:"grid gap-3 md:grid-cols-2",children:n.recentMeals.slice(0,4).map(t=>e.jsx(oe,{meal:t,pending:M.isPending,onLogAgain:a=>M.mutate(a)},`saved-${t.id}`))})]}):null]}),e.jsxs(h,{className:"grid gap-4 border-white/8 bg-white/[0.045] p-5",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Body state"}),e.jsx("h2",{className:"mt-1 text-xl font-semibold text-white",children:"Check-in loop"})]}),e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(m,{value:k,inputMode:"decimal",onChange:t=>V(t.target.value),placeholder:"Weight kg"}),e.jsx(m,{value:C,inputMode:"decimal",onChange:t=>O(t.target.value),placeholder:"Energy 0-10"}),e.jsx(m,{value:G,inputMode:"decimal",onChange:t=>Z(t.target.value),placeholder:"Bloating 0-10"}),e.jsx(m,{value:S,inputMode:"decimal",onChange:t=>J(t.target.value),placeholder:"Look 0-10"})]}),e.jsxs(p,{type:"button",variant:"secondary",pending:ee.isPending,disabled:!k.trim()&&!C.trim()&&!G.trim()&&!S.trim(),onClick:()=>ee.mutate(),children:[e.jsx(ne,{className:"size-4"}),"Save check-in"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3 text-sm text-white/58",children:[e.jsxs("div",{className:"rounded-[18px] border border-white/8 bg-white/[0.04] p-3",children:["Energy avg ",e.jsx("span",{className:"text-white",children:g(R.averageEnergy)})]}),e.jsxs("div",{className:"rounded-[18px] border border-white/8 bg-white/[0.04] p-3",children:["Gut comfort ",e.jsx("span",{className:"text-white",children:g(se.gutComfortScore)})]}),e.jsxs("div",{className:"rounded-[18px] border border-white/8 bg-white/[0.04] p-3",children:["Look avg ",e.jsx("span",{className:"text-white",children:g((re=n.appearanceCheckins[0])==null?void 0:re.aestheticScore)})]}),e.jsxs("div",{className:"rounded-[18px] border border-white/8 bg-white/[0.04] p-3",children:["Cravings ",e.jsx("span",{className:"text-white",children:g(R.averageCravings)})]})]})]})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(360px,0.9fr)_minmax(0,1.1fr)]",children:[e.jsxs(h,{className:"grid gap-4 border-white/8 bg-white/[0.045] p-5",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Catalog"}),e.jsx("h2",{className:"mt-1 text-xl font-semibold text-white",children:"Food search and barcode"})]}),e.jsx(ve,{className:"size-5 text-white/42"})]}),e.jsxs("div",{className:"grid gap-3 md:grid-cols-[minmax(0,1fr)_auto]",children:[e.jsx(m,{value:A,onChange:t=>me(t.target.value),placeholder:"Search food database"}),e.jsx(p,{type:"button",variant:"secondary",pending:Q.isPending,disabled:!A.trim(),onClick:()=>Q.mutate(),children:"Search"})]}),e.jsxs("div",{className:"grid gap-3 md:grid-cols-[minmax(0,1fr)_auto]",children:[e.jsx(m,{value:K,onChange:t=>ge(t.target.value),placeholder:"Barcode"}),e.jsx(p,{type:"button",variant:"secondary",pending:q.isPending,disabled:!K.trim(),onClick:()=>q.mutate(),children:"Lookup"})]}),ie?e.jsx(ce,{food:ie,pending:F.isPending,onLog:t=>F.mutate(t)}):null,e.jsx("div",{className:"grid gap-3",children:he.slice(0,6).map(t=>e.jsx(ce,{food:t,pending:F.isPending,onLog:a=>F.mutate(a)},t.id))})]}),e.jsxs(h,{className:"grid gap-5 border-white/8 bg-white/[0.045] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Today ledger"}),e.jsx("h2",{className:"mt-1 text-xl font-semibold text-white",children:"Calories, macros, and meal evidence"})]}),e.jsxs(f,{className:"bg-white/[0.08] text-white/70",children:[c.meals.length," meals"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"h-3 overflow-hidden rounded-full bg-white/[0.08]",children:e.jsx("div",{className:de("h-full rounded-full",z>=0?"bg-emerald-300":"bg-rose-300"),style:{width:`${Math.min(100,xe)}%`}})}),e.jsxs("div",{className:"mt-3 grid gap-2 text-sm text-white/58 sm:grid-cols-4",children:[e.jsxs("span",{children:[y.carbohydrateGrams.toFixed(0),"g carbs"]}),e.jsxs("span",{children:[y.fatGrams.toFixed(0),"g fat"]}),e.jsxs("span",{children:[y.fiberGrams.toFixed(0),"g fiber"]}),e.jsxs("span",{children:[c.unconfirmedCount," unconfirmed"]})]})]}),e.jsx("div",{className:"grid gap-3",children:c.meals.length>0?c.meals.map(t=>e.jsx(oe,{meal:t,pending:M.isPending,onLogAgain:a=>M.mutate(a)},t.id)):e.jsx("div",{className:"rounded-[22px] border border-dashed border-white/12 p-5 text-sm text-white/50",children:"No meals logged today yet."})})]})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-4",children:[e.jsx(x,{label:"Food quality",value:g(P.qualityScore),detail:`Fiber density ${l(P.fiberPer1000Kcal,1)}g/1000 kcal, protein density ${l(P.proteinPer1000Kcal,1)}g/1000 kcal, ultra-processed share ${l(P.ultraProcessedShare,0)}%.`,icon:B,tone:"green"}),e.jsx(x,{label:"Training fuel",value:g(W.fuelingScore),detail:`Recent workout load ${l(W.recentTrainingLoad)} with ${l(W.carbsPerTrainingLoad,1)}g carbs per load unit.`,icon:fe,tone:"amber"}),e.jsx(x,{label:"Subjective",value:g(R.averageFocus),detail:"Focus, energy, hunger, cravings, and performance are tracked as food-effect evidence, not diary fluff.",icon:ne}),e.jsx(x,{label:"Gut",value:g(se.averageBloating),detail:"Bloating, reflux, stool type, and suspected triggers help Forge connect food choices to comfort and look.",icon:we,tone:"rose"})]}),e.jsxs("section",{className:"grid gap-4 xl:grid-cols-[minmax(0,1fr)_minmax(360px,0.8fr)]",children:[e.jsxs(h,{className:"grid gap-4 border-white/8 bg-white/[0.045] p-5",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Hypotheses"}),e.jsx("h2",{className:"mt-1 text-xl font-semibold text-white",children:"Food and body pattern candidates"})]}),e.jsx("div",{className:"grid gap-3 md:grid-cols-2",children:ae.length>0?ae.slice(0,6).map((t,a)=>e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx(f,{className:"bg-indigo-300/10 text-indigo-50",children:v(t.metric)??"pattern"}),e.jsx("span",{className:"text-xs text-white/40",children:l(t.confidence,2)})]}),e.jsx("div",{className:"mt-3 text-sm font-medium text-white",children:v(t.label)??"Candidate pattern"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/56",children:v(t.description)??"Forge needs more paired meals and check-ins to harden this signal."})]},String(t.key??a))):e.jsx("div",{className:"rounded-[22px] border border-dashed border-white/12 p-5 text-sm text-white/50 md:col-span-2",children:"Log meals plus energy, gut, and look check-ins for a few days to generate pattern candidates."})})]}),e.jsxs(h,{className:"grid content-start gap-4 border-white/8 bg-white/[0.045] p-5",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"rounded-2xl bg-cyan-300/10 p-2.5 text-cyan-100",children:e.jsx(Ne,{className:"size-5"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Experiments"}),e.jsx("h2",{className:"text-xl font-semibold text-white",children:"N-of-1 lab"})]})]}),e.jsxs("div",{className:"grid gap-3",children:[n.experiments.slice(0,4).map((t,a)=>e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-sm font-medium text-white",children:v(t.title)??"Nutrition experiment"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/56",children:v(t.hypothesis)??v(t.intervention)??"No hypothesis recorded."})]},String(t.id??a))),n.experiments.length===0?e.jsx("div",{className:"rounded-[22px] border border-dashed border-white/12 p-5 text-sm text-white/50",children:"Start experiments from OpenClaw or the API: caffeine timing, fiber ramp, low-FODMAP trial, carb timing, sodium/puffiness, or pre-training fueling."}):null]})]})]}),e.jsxs(h,{className:"grid gap-4 border-white/8 bg-white/[0.045] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/40",children:"Data quality"}),e.jsx("h2",{className:"mt-1 text-xl font-semibold text-white",children:"Confidence, coverage, and next evidence"})]}),e.jsxs(f,{className:"bg-white/[0.08] text-white/70",children:[n.summary.dataQualityScore.toFixed(0),"% coverage"]})]}),e.jsxs("div",{className:"grid gap-3 md:grid-cols-3",children:[e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/36",children:"Source confidence"}),e.jsx("div",{className:"mt-2 text-lg font-semibold text-white",children:$.sourceConfidence}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/54",children:"Food parsing stays candidate-based until accepted; wearable burn is treated as a trend input."})]}),e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/36",children:"Missing check-ins"}),e.jsx("div",{className:"mt-3 flex flex-wrap gap-2",children:$.missingHighValueCheckins.length>0?$.missingHighValueCheckins.map(t=>e.jsx(f,{className:"bg-amber-300/10 text-amber-50",children:t},t)):e.jsx("span",{className:"text-sm text-white/58",children:"Core evidence loop is covered."})})]}),e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/36",children:"Next best cue"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/58",children:$.notes}),e.jsxs("div",{className:"mt-3 text-xs text-white/42",children:[c.unconfirmedCount," unconfirmed candidate",c.unconfirmedCount===1?"":"s"]})]})]})]})]})}export{Oe as WeightLossPage};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as a,aC as w,r as y}from"./vendor-DHkYh85p.js";import{Z as m,bq as b,cO as j}from"./index-
|
|
1
|
+
import{j as a,aC as w,r as y}from"./vendor-DHkYh85p.js";import{Z as m,bq as b,cO as j}from"./index-CF4J4R9L.js";function v(s){const e=[];let r,i;for(const n of s){const t=n.trim();if(!t)continue;const o=t.indexOf(":");if(o<=0){e.push({label:"Note",value:t});continue}const c=t.slice(0,o).trim(),h=t.slice(o+1).trim();if(!h)continue;const p=c.toLowerCase();if(p==="title"){r=h;continue}if(p==="summary"){i=h;continue}e.push({label:c,value:h})}return{title:r,summary:i,rows:e}}function N(s){const e=[],r=/(!?\[\[([^\]]+)\]\]|\[([^\]]+)\]\(([^)]+)\)|`([^`]+)`|\*\*([^*]+)\*\*|\*([^*]+)\*)/g;let i=0,n=null;for(;(n=r.exec(s))!==null;){if(n.index>i&&e.push({type:"text",value:s.slice(i,n.index)}),n[1]&&n[2]){const t=n[2].trim(),o=n[1].startsWith("!"),c=t.indexOf("|"),h=c>=0?t.slice(0,c).trim():t,p=c>=0?t.slice(c+1).trim():h;if(h.toLowerCase().startsWith("forge:")){const[,x,...l]=h.split(":");e.push({type:"forge-link",entityType:x??"",entityId:l.join(":").trim(),label:p})}else e.push({type:"wiki-link",target:h,label:p,embed:o})}else n[3]&&n[4]?e.push({type:"link",label:n[3],href:n[4].trim()}):n[5]?e.push({type:"code",value:n[5]}):n[6]?e.push({type:"strong",value:n[6]}):n[7]&&e.push({type:"em",value:n[7]});i=r.lastIndex}return i<s.length&&e.push({type:"text",value:s.slice(i)}),e}function $(s){const e=s.replace(/\r/g,"").split(`
|
|
2
2
|
`),r=[],i=[];let n=null,t=0;for(;t<e.length;){const o=e[t]??"",c=o.trim();if(!c){t+=1;continue}if(c.startsWith("```")){const l=[];for(t+=1;t<e.length&&!(e[t]??"").trim().startsWith("```");)l.push(e[t]??""),t+=1;t+=1,r.push({type:"code",code:l.join(`
|
|
3
3
|
`)});continue}const h=c.match(/^:::([a-z0-9-]+)\s*$/i);if(h){const l=h[1].toLowerCase(),d=[];for(t+=1;t<e.length&&(e[t]??"").trim()!==":::";)d.push(e[t]??""),t+=1;t<e.length&&(t+=1);const f=[`:::${l}`,...d,":::"].join(`
|
|
4
4
|
`);i.push({kind:l,lines:d,raw:f}),l==="forge-infobox"?n=v(d):l==="note"||l==="tip"||l==="warning"||l==="danger"?r.push({type:"admonition",kind:l,lines:d}):(l==="forge-links"||l==="forge-media"||l==="forge-related")&&r.push({type:l,lines:d});continue}const p=o.match(/^(#{1,6})\s+(.*)$/);if(p){r.push({type:"heading",level:p[1].length,text:p[2].trim()}),t+=1;continue}if(/^>\s?/.test(o)){const l=[];for(;t<e.length&&/^>\s?/.test(e[t]??"");)l.push((e[t]??"").replace(/^>\s?/,"")),t+=1;r.push({type:"quote",text:l.join(" ").trim()});continue}if(/^[-*+]\s+/.test(o)||/^\d+\.\s+/.test(o)){const l=/^\d+\.\s+/.test(o),d=[];for(;t<e.length&&(/^[-*+]\s+/.test(e[t]??"")||/^\d+\.\s+/.test(e[t]??""));)d.push((e[t]??"").replace(/^[-*+]\s+/,"").replace(/^\d+\.\s+/,"").trim()),t+=1;r.push({type:"list",ordered:l,items:d});continue}const x=[];for(;t<e.length;){const l=e[t]??"",d=l.trim();if(!d||d.startsWith("```")||d.startsWith(":::")||/^#{1,6}\s+/.test(l)||/^>\s?/.test(l)||/^[-*+]\s+/.test(l)||/^\d+\.\s+/.test(l))break;x.push(d),t+=1}if(x.length>0){r.push({type:"paragraph",text:x.join(" ")});continue}t+=1}return{blocks:r,infobox:n,directives:i}}function L(s,e,r){return s.map((i,n)=>{const t=`${e}-${n}`;switch(i.type){case"text":return a.jsx(y.Fragment,{children:i.value},t);case"code":return a.jsx("code",{className:"rounded bg-black/10 px-1.5 py-0.5 font-mono text-[0.92em] text-white",children:i.value},t);case"strong":return a.jsx("strong",{className:"font-semibold text-white",children:i.value},t);case"em":return a.jsx("em",{className:"italic text-white/82",children:i.value},t);case"link":{const o=/^https?:\/\//i.test(i.href);return a.jsx("a",{href:i.href,target:o?"_blank":void 0,rel:o?"noreferrer":void 0,className:"text-[var(--secondary)] underline decoration-current/30 underline-offset-2 transition hover:text-white",children:i.label},t)}case"forge-link":{const o=b(i.entityType,i.entityId),c=o?j(o):null;return c?a.jsx("a",{href:c,className:"rounded-sm bg-white/[0.08] px-1.5 py-0.5 text-white no-underline ring-1 ring-black/5 transition hover:bg-white/[0.12]",children:i.label},t):a.jsx("span",{className:"rounded-sm bg-white/[0.08] px-1.5 py-0.5 text-white/64",children:i.label},t)}case"wiki-link":return a.jsx(w,{to:{pathname:`/wiki/page/${encodeURIComponent(i.target)}`,search:r?`?spaceId=${encodeURIComponent(r)}`:""},className:m("underline decoration-current/30 underline-offset-2 transition hover:text-white",i.embed?"text-[var(--primary)]":"text-[var(--secondary)]"),children:i.label},t)}})}function u(s,e,r){return L(N(s),e,r)}function W(s,e){const r=s.map(i=>i.trim()).filter(Boolean);return r.length===0?null:a.jsx("ul",{className:"space-y-1.5 pl-4 text-[13px] leading-6 text-white/76",children:r.map((i,n)=>a.jsx("li",{children:u(i,`directive-${n}`,e)},`${i}-${n}`))})}function g(s,e,r){switch(s.type){case"heading":{const i=s.level===1?"text-[1.9rem] leading-[1.08]":s.level===2?"text-[1.25rem] leading-[1.2]":s.level===3?"text-[1.05rem] leading-[1.3]":"text-[0.92rem] leading-[1.35]";return a.jsx("h2",{className:m("font-semibold tracking-[-0.02em] text-white",e>0&&"mt-6",i),children:u(s.text,`heading-${e}`,r)},`heading-${e}`)}case"paragraph":return a.jsx("p",{className:"text-[14px] leading-7 text-white/78",children:u(s.text,`paragraph-${e}`,r)},`paragraph-${e}`);case"quote":return a.jsx("blockquote",{className:"border-l-[3px] border-white/16 pl-4 text-[14px] leading-7 text-white/62",children:u(s.text,`quote-${e}`,r)},`quote-${e}`);case"list":{const i=s.ordered?"ol":"ul";return a.jsx(i,{className:m("space-y-1.5 pl-5 text-[14px] leading-7 text-white/78",s.ordered?"list-decimal":"list-disc"),children:s.items.map((n,t)=>a.jsx("li",{children:u(n,`list-${e}-${t}`,r)},`item-${e}-${t}`))},`list-${e}`)}case"code":return a.jsx("pre",{className:"overflow-x-auto rounded-xl bg-[rgba(10,16,30,0.9)] px-4 py-3 text-[12px] leading-6 text-white ring-1 ring-black/5",children:a.jsx("code",{children:s.code})},`code-${e}`);case"admonition":return a.jsxs("aside",{className:m("rounded-xl border px-4 py-3",s.kind==="warning"||s.kind==="danger"?"border-amber-500/25 bg-amber-500/8":"border-white/12 bg-white/[0.04]"),children:[a.jsx("div",{className:"mb-2 text-[11px] font-semibold uppercase tracking-[0.16em] text-white/48",children:s.kind}),a.jsx("div",{className:"grid gap-2 text-[13px] leading-6 text-white/76",children:s.lines.map((i,n)=>a.jsx("p",{children:u(i,`admonition-${e}-${n}`,r)},`admonition-line-${n}`))})]},`admonition-${e}`);case"forge-links":case"forge-media":case"forge-related":return a.jsxs("section",{className:"rounded-xl border border-white/10 bg-white/[0.03] px-4 py-3",children:[a.jsx("div",{className:"mb-2 text-[11px] font-semibold uppercase tracking-[0.16em] text-white/48",children:s.type.replace("forge-","")}),W(s.lines,r)]},`${s.type}-${e}`)}}function k(s,e,r){return a.jsx("div",{className:"text-[13px] leading-6 text-white/76",children:u(s,e,r)})}function q({infobox:s,spaceId:e,className:r}){return a.jsxs("aside",{className:m("wiki-infobox rounded-2xl border border-white/10 bg-white/[0.03] p-4",r),children:[s.title?a.jsx("div",{className:"text-[1rem] font-semibold leading-tight text-white",children:s.title}):null,s.summary?a.jsx("p",{className:"mt-2 text-[13px] leading-6 text-white/60",children:u(s.summary,"infobox-summary",e)}):null,a.jsx("dl",{className:"mt-3 grid gap-2",children:s.rows.map((i,n)=>a.jsxs("div",{className:"grid gap-1 border-t border-white/10 pt-2 first:border-t-0 first:pt-0",children:[a.jsx("dt",{className:"text-[10px] font-semibold uppercase tracking-[0.16em] text-white/48",children:i.label}),a.jsx("dd",{children:k(i.value,`infobox-row-${n}`,e)})]},`${i.label}-${n}`))})]})}function C(s){const e=[],r=[];let i=!1;for(const n of s)!i&&n.type==="heading"&&n.level<=2&&e.length>0&&(i=!0),i?r.push(n):e.push(n);return{intro:e.length>0?e:s.slice(0,1),rest:e.length>0?r:s.slice(1)}}function M({markdown:s,spaceId:e,className:r}){const i=$(s),{intro:n,rest:t}=C(i.blocks);return a.jsxs("div",{className:m("grid gap-4",r),children:[a.jsxs("div",{className:"grid gap-4 xl:grid-cols-[minmax(0,1fr)_19rem] xl:items-start",children:[a.jsx("div",{className:"grid gap-4",children:n.map((o,c)=>g(o,c,e))}),i.infobox?a.jsx(q,{infobox:i.infobox,spaceId:e,className:"order-2 xl:order-none"}):null]}),t.length>0?a.jsx("div",{className:"grid gap-4",children:t.map((o,c)=>g(o,c+n.length,e))}):null]})}export{M as W};
|