The verify pipeline carried two scripts whose targets no longer
exist after the vanilla deletion at commit 25a9c4c:
test/calc-math.test.js — required public/js/calc-math.js (gone);
every assertion is now covered by shared/clinical/
calculators.test.ts (vitest).
scripts/lint-references.js — scans public/js/*.js for DOM id
references and checks each target exists in public/components/
*.html. Those trees are gone; TypeScript + knip + vite build
cover the equivalent dead-reference class for the React tree.
package.json:
• `verify` drops `test:node` and `lint:refs`; now runs
typecheck + vitest + knip + client vite build.
• `test:node` script removed (test/ directory empty).
public/app/assets/ — fresh vite build so the bundle hashes match
the current source (new chunks for ByVisitAge, Cms, DxPicker,
EditableResult, LabsList, Milestones, OutputActions, Recorder,
Shadess, SlideEditor, VisitNote — all features landed in the
preceding commits).
Verified locally on node 20: tsc + 9 test files / 177 tests pass,
knip finds nothing, vite builds 35 chunks, client bundle is 343 kB
initial / 106 kB gzipped (Cms is the biggest lazy chunk at 402 kB
due to Tiptap/ProseMirror).
1 line
No EOL
9.4 KiB
JavaScript
1 line
No EOL
9.4 KiB
JavaScript
import{i as e,n as t,t as n}from"./jsx-runtime-ByY1xr43.js";import{c as r,i,l as a}from"./index-C9wKWOAN.js";import{t as o}from"./OutputActions-6XZlmtIw.js";var s=e(t(),1),c=n(),l={"Gross Motor":{icon:`🏃`,className:`border-l-4 border-l-blue-500`},"Fine Motor":{icon:`✋`,className:`border-l-4 border-l-purple-500`},Language:{icon:`💬`,className:`border-l-4 border-l-emerald-500`},"Social/Emotional":{icon:`😊`,className:`border-l-4 border-l-amber-500`},Cognitive:{icon:`🧠`,className:`border-l-4 border-l-pink-500`},"Self-Help":{icon:`🧒`,className:`border-l-4 border-l-indigo-500`},Feeding:{icon:`🍼`,className:`border-l-4 border-l-cyan-500`},Sleep:{icon:`💤`,className:`border-l-4 border-l-slate-500`}},u={icon:`📋`,className:`border-l-4 border-l-border`},d=[`Newborn / 1 month`,`2 months`,`4 months`,`6 months`,`9 months`,`12 months`,`15 months`,`18 months`,`24 months`,`30 months`,`36 months`,`48 months`,`60 months`,`6 years`,`7 years`,`8 years`,`9 years`,`10 years`,`11 years`],f=`w-full rounded-md border border-input bg-background px-3 py-2 text-sm`,p=`inline-flex items-center gap-1 rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium hover:bg-muted disabled:opacity-50`,m=`inline-flex items-center gap-1 rounded-md bg-primary text-primary-foreground px-3 py-1.5 text-sm font-semibold disabled:opacity-50`;function h(){let[e,t]=(0,s.useState)(``),[n,h]=(0,s.useState)(``),[g,_]=(0,s.useState)(``),[v,y]=(0,s.useState)(`narrative`),[b,x]=(0,s.useState)({}),[S,C]=(0,s.useState)(null),[w,T]=(0,s.useState)(void 0),[E,D]=(0,s.useState)(null),[O,k]=(0,s.useState)(null),{data:A,isLoading:j}=a({queryKey:[`milestones-data`],queryFn:()=>i.get(`/api/milestones-data`)}),M=(0,s.useMemo)(()=>{let e=A?.milestones?Object.keys(A.milestones):[],t=d.filter(t=>e.includes(t)),n=e.filter(e=>!d.includes(e));return[...t,...n]},[A]);(0,s.useEffect)(()=>{if(!g||!A?.milestones?.[g]){x({});return}let e={},t=A.milestones[g];Object.keys(t).forEach(n=>{t[n].forEach((t,r)=>{e[n+`-`+r]={domain:n,milestone:t,status:null}})}),x(e),C(null),T(void 0),D(null)},[g,A]);let N=r({mutationFn:async()=>{let t={milestones:Object.values(b),ageGroup:g,patientAge:e,patientGender:n,format:v};return i.post(`/api/generate-milestone-narrative`,t)},onSuccess:e=>{C(e.narrative),T(e.summary),D(null),k({kind:`ok`,text:`Generated`})},onError:e=>k({kind:`err`,text:e.message||`Failed`})}),P=r({mutationFn:async()=>i.post(`/api/generate-milestone-summary`,{narrative:S,ageGroup:g,patientAge:e,patientGender:n}),onSuccess:e=>{D(e.summary),k({kind:`ok`,text:`Summary generated`})},onError:e=>k({kind:`err`,text:e.message||`Failed`})});function F(e,t){x(n=>{let r=n[e];if(!r)return n;let i=r.status===t?null:t;return{...n,[e]:{...r,status:i}}})}function I(){x(e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,{...t,status:`yes`}])))}function L(){x(e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,{...t,status:null}]))),C(null),T(void 0),D(null)}function R(){if(!g){k({kind:`err`,text:`Select age group`});return}if(!Object.values(b).filter(e=>e.status!==null).length){k({kind:`err`,text:`Assess at least one milestone`});return}k(null),N.mutate()}function z(){if(S)try{sessionStorage.setItem(`wv-milestones-narrative`,S),k({kind:`ok`,text:`Copied to Visit Note — switch to that tab`})}catch{k({kind:`err`,text:`Session storage unavailable`})}}let B=(0,s.useMemo)(()=>{let e={};return Object.entries(b).forEach(([t,n])=>{e[n.domain]||(e[n.domain]=[]),e[n.domain].push({id:t,text:n.milestone,status:n.status})}),e},[b]),V=(0,s.useMemo)(()=>{let e={};return Object.values(b).forEach(t=>{let n=e[t.domain]||(e[t.domain]={total:0,yes:0,no:0});n.total++,t.status===`yes`&&n.yes++,t.status===`no`&&n.no++}),e},[b]);return(0,c.jsxs)(`div`,{className:`space-y-4`,children:[(0,c.jsxs)(`div`,{className:`rounded-lg border border-border bg-card p-4 space-y-3`,children:[(0,c.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-4 gap-3`,children:[(0,c.jsxs)(`label`,{className:`flex flex-col gap-1`,children:[(0,c.jsx)(`span`,{className:`text-xs font-semibold uppercase text-muted-foreground`,children:`Patient age`}),(0,c.jsx)(`input`,{className:f,value:e,onChange:e=>t(e.target.value),placeholder:`e.g. 9 months`})]}),(0,c.jsxs)(`label`,{className:`flex flex-col gap-1`,children:[(0,c.jsx)(`span`,{className:`text-xs font-semibold uppercase text-muted-foreground`,children:`Gender`}),(0,c.jsxs)(`select`,{className:f,value:n,onChange:e=>h(e.target.value),children:[(0,c.jsx)(`option`,{value:``,children:`Select`}),(0,c.jsx)(`option`,{children:`Male`}),(0,c.jsx)(`option`,{children:`Female`})]})]}),(0,c.jsxs)(`label`,{className:`flex flex-col gap-1`,children:[(0,c.jsx)(`span`,{className:`text-xs font-semibold uppercase text-muted-foreground`,children:`Age group`}),(0,c.jsxs)(`select`,{className:f,value:g,onChange:e=>_(e.target.value),"data-testid":`ms-age-group`,children:[(0,c.jsx)(`option`,{value:``,children:`-- Select --`}),M.map(e=>(0,c.jsx)(`option`,{value:e,children:e},e))]})]}),(0,c.jsxs)(`label`,{className:`flex flex-col gap-1`,children:[(0,c.jsx)(`span`,{className:`text-xs font-semibold uppercase text-muted-foreground`,children:`Output format`}),(0,c.jsxs)(`select`,{className:f,value:v,onChange:e=>y(e.target.value),children:[(0,c.jsx)(`option`,{value:`narrative`,children:`Narrative`}),(0,c.jsx)(`option`,{value:`list`,children:`Structured list`})]})]})]}),(0,c.jsxs)(`div`,{className:`flex flex-wrap gap-3 text-xs text-muted-foreground`,children:[(0,c.jsxs)(`span`,{children:[(0,c.jsx)(`span`,{className:`inline-block w-4 h-4 align-middle bg-green-100 text-green-700 text-center rounded mr-1`,children:`✓`}),` Achieved`]}),(0,c.jsxs)(`span`,{children:[(0,c.jsx)(`span`,{className:`inline-block w-4 h-4 align-middle bg-red-100 text-red-700 text-center rounded mr-1`,children:`✗`}),` Not achieved`]}),(0,c.jsxs)(`span`,{children:[(0,c.jsx)(`span`,{className:`inline-block w-4 h-4 align-middle bg-muted text-center rounded mr-1`,children:`—`}),` Not assessed (omitted)`]})]})]}),j&&(0,c.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Loading milestones…`}),g&&Object.keys(B).length===0&&!j&&(0,c.jsx)(`div`,{className:`text-sm text-muted-foreground italic`,children:`No data for this age group.`}),Object.entries(B).map(([e,t])=>{let n=l[e]||u,r=V[e];return(0,c.jsxs)(`div`,{className:`rounded-lg bg-card p-0 overflow-hidden `+n.className,children:[(0,c.jsxs)(`div`,{className:`px-4 py-2 flex items-center gap-2 bg-muted/40`,children:[(0,c.jsx)(`span`,{children:n.icon}),(0,c.jsx)(`span`,{className:`font-semibold`,children:e}),(0,c.jsx)(`span`,{className:`ml-auto text-xs text-muted-foreground`,"data-testid":`ms-badge-`+e.replace(/\W/g,`_`),children:r&&r.yes+r.no>0?r.yes+`✓ `+r.no+`✗ / `+r.total:r.total+` items`})]}),(0,c.jsx)(`div`,{className:`divide-y divide-border`,children:t.map(e=>(0,c.jsxs)(`div`,{className:`flex items-center gap-3 px-4 py-2 text-sm`,children:[(0,c.jsxs)(`div`,{className:`flex gap-1 shrink-0`,children:[(0,c.jsx)(`button`,{type:`button`,onClick:()=>F(e.id,`yes`),className:`w-8 h-8 rounded border text-xs font-bold `+(e.status===`yes`?`bg-green-100 text-green-700 border-green-400`:`bg-background border-border hover:bg-muted`),"aria-label":`Achieved: `+e.text,children:`✓`}),(0,c.jsx)(`button`,{type:`button`,onClick:()=>F(e.id,`no`),className:`w-8 h-8 rounded border text-xs font-bold `+(e.status===`no`?`bg-red-100 text-red-700 border-red-400`:`bg-background border-border hover:bg-muted`),"aria-label":`Not achieved: `+e.text,children:`✗`})]}),(0,c.jsx)(`span`,{className:e.status===`yes`?`text-green-700`:e.status===`no`?`text-red-700 line-through decoration-red-400`:``,children:e.text})]},e.id))})]},e)}),Object.keys(B).length>0&&(0,c.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,c.jsx)(`button`,{type:`button`,onClick:I,className:p,children:`✓ All yes`}),(0,c.jsx)(`button`,{type:`button`,onClick:L,className:p,children:`🧹 Clear all`}),(0,c.jsx)(`button`,{type:`button`,onClick:R,disabled:N.isPending,className:m,children:N.isPending?`Generating…`:`✨ Generate narrative`})]}),O&&(0,c.jsx)(`div`,{className:`text-sm `+(O.kind===`ok`?`text-green-600`:`text-destructive`),children:O.text}),S&&(0,c.jsxs)(`section`,{className:`rounded-lg border border-border bg-card`,children:[(0,c.jsxs)(`header`,{className:`px-4 py-2 border-b border-border bg-muted/40 flex items-center justify-between`,children:[(0,c.jsx)(`h3`,{className:`text-sm font-semibold`,children:`Developmental assessment`}),(0,c.jsx)(`button`,{type:`button`,onClick:z,className:p,children:`📋 Copy to Note`})]}),w&&(0,c.jsxs)(`div`,{className:`flex gap-4 text-xs px-4 py-2 border-b border-border bg-background text-muted-foreground`,children:[(0,c.jsxs)(`span`,{children:[`✓ Achieved: `,w.achieved]}),(0,c.jsxs)(`span`,{children:[`✗ Not yet: `,w.notAchieved]}),(0,c.jsxs)(`span`,{children:[`— Not assessed: `,w.notAssessed,` (omitted)`]})]}),(0,c.jsx)(`div`,{className:`p-4 whitespace-pre-wrap text-sm`,children:S}),(0,c.jsx)(`div`,{className:`px-4 pb-3`,children:(0,c.jsx)(o,{text:S,onUpdate:C,exportLabel:`milestones`,exportType:`milestones`})}),(0,c.jsxs)(`div`,{className:`px-4 pb-4 pt-2 border-t border-border space-y-2`,children:[(0,c.jsx)(`button`,{type:`button`,onClick:()=>P.mutate(),disabled:P.isPending,className:p,"data-testid":`ms-summary-btn`,children:P.isPending?`Summarizing…`:E?`↻ Regenerate summary`:`📏 3-sentence summary`}),E&&(0,c.jsx)(`div`,{className:`rounded-md bg-muted/40 p-3 whitespace-pre-wrap text-sm`,children:E})]})]})]})}export{h as default}; |