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
11 KiB
JavaScript
1 line
No EOL
11 KiB
JavaScript
import{i as e,n as t,t as n}from"./jsx-runtime-ByY1xr43.js";import{c as r,i}from"./index-C9wKWOAN.js";import{t as a}from"./OutputActions-6XZlmtIw.js";import{t as o}from"./Recorder-DdXTjnSC.js";var s=e(t(),1),c=n(),l=[{key:`strengths`,label:`Strengths`,icon:`⭐`,color:`#f59e0b`,intro:`Starting with what you do well helps us get to know you better.`,questions:[{id:`str1`,text:`Has something they are proud of or enjoy`,type:`yn`},{id:`str2`,text:`Describes self positively when asked`,type:`yn`},{id:`str3`,text:`Has at least one trusted adult they can talk to`,type:`yn`}]},{key:`school`,label:`School`,icon:`🎓`,color:`#3b82f6`,intro:`Ask about school performance, attendance, and future plans.`,questions:[{id:`sch1`,text:`Grades are satisfactory / doing their best`,type:`yn`},{id:`sch2`,text:`Likes school or finds something enjoyable about it`,type:`yn`},{id:`sch3`,text:`Regular attendance (no truancy concerns)`,type:`yn`},{id:`sch4`,text:`Has plans or goals for the future`,type:`yn`}]},{key:`home`,label:`Home`,icon:`🏠`,color:`#10b981`,intro:`Ask about living situation and family relationships.`,questions:[{id:`hom1`,text:`Stable living situation`,type:`yn`},{id:`hom2`,text:`Gets along with people at home`,type:`yn`},{id:`hom3`,text:`Would talk to family member if stressed`,type:`yn`},{id:`hom4`,text:`Has experienced household violence or instability (concern if YES)`,type:`yn`,concern_if:!0}]},{key:`activities`,label:`Activities`,icon:`👥`,color:`#8b5cf6`,intro:`Ask about friends, hobbies, and peer relationships.`,questions:[{id:`act1`,text:`Has friends and spends time with them`,type:`yn`},{id:`act2`,text:`Involved in sports, clubs, or hobbies`,type:`yn`},{id:`act3`,text:`Social media/screen use within healthy limits`,type:`yn`},{id:`act4`,text:`Has experienced bullying (concern if YES)`,type:`yn`,concern_if:!0}]},{key:`drugs`,label:`Drugs / Substances`,icon:`💊`,color:`#ef4444`,intro:`This is confidential. Ask in private.`,questions:[{id:`drg1`,text:`Has tried cigarettes / vaping / tobacco`,type:`yn`,concern_if:!0},{id:`drg2`,text:`Has tried alcohol`,type:`yn`,concern_if:!0},{id:`drg3`,text:`Has tried marijuana or other drugs`,type:`yn`,concern_if:!0},{id:`drg4`,text:`Friends use substances`,type:`yn`},{id:`drg5`,text:`CRAFFT screen result (if done)`,type:`text`,placeholder:`e.g., Score 0 — low risk`}]},{key:`emotions`,label:`Emotions / Eating`,icon:`❤️`,color:`#ec4899`,intro:`Screen for depression, anxiety, and disordered eating.`,questions:[{id:`emo1`,text:`Feeling down, sad, or hopeless recently`,type:`yn`,concern_if:!0},{id:`emo2`,text:`Feeling unusually stressed or anxious`,type:`yn`,concern_if:!0},{id:`emo3`,text:`Trouble sleeping`,type:`yn`},{id:`emo4`,text:`PHQ-A / depression screen result (if done)`,type:`text`,placeholder:`e.g., PHQ-A score 3 — minimal`},{id:`emo5`,text:`Happy with eating habits and body image`,type:`yn`},{id:`emo6`,text:`Restricting food / purging / using diet pills (concern if YES)`,type:`yn`,concern_if:!0}]},{key:`sexuality`,label:`Sexuality`,icon:`🛡️`,color:`#f97316`,intro:`Ask in private. Normalize the questions.`,questions:[{id:`sex1`,text:`Comfortable discussing attraction/identity`,type:`yn`},{id:`sex2`,text:`Sexually active`,type:`yn`},{id:`sex3`,text:`Uses protection consistently if sexually active`,type:`yn`},{id:`sex4`,text:`History of unwanted sexual contact (concern if YES)`,type:`yn`,concern_if:!0},{id:`sex5`,text:`STI screening indicated/done`,type:`yn`}]},{key:`safety`,label:`Safety`,icon:`🛡`,color:`#6366f1`,intro:`Ask about violence, weapons, and suicidal ideation.`,questions:[{id:`saf1`,text:`Feels safe at school and home`,type:`yn`},{id:`saf2`,text:`Carries a weapon (concern if YES)`,type:`yn`,concern_if:!0},{id:`saf3`,text:`Has been in physical fights recently`,type:`yn`,concern_if:!0},{id:`saf4`,text:`Wears seatbelt; safe driving practices`,type:`yn`},{id:`saf5`,text:`Thoughts of hurting self or suicide (concern if YES — STAT eval)`,type:`yn`,concern_if:!0},{id:`saf6`,text:`Columbia/ASQ suicide screen result (if done)`,type:`text`,placeholder:`e.g., ASQ: negative`}]}],u=`rounded-md border border-input bg-background px-3 py-2 text-sm`,d=`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`,f=`inline-flex items-center gap-1 rounded-md bg-primary text-primary-foreground px-3 py-2 text-sm font-semibold disabled:opacity-50`;function p(){let e={};return l.forEach(t=>{e[t.key]={questions:{},comment:``,concern:!1,skipped:!1}}),e}function m(){let[e,t]=(0,s.useState)(``),[n,m]=(0,s.useState)(``),[h,g]=(0,s.useState)(p),[_,v]=(0,s.useState)(``),[y,b]=(0,s.useState)(null),[x,S]=(0,s.useState)(null),[C,w]=(0,s.useState)(null),T=r({mutationFn:async()=>{let t={};if(l.forEach(e=>{let n=h[e.key],r=e.questions.map(e=>({id:e.id,text:e.text,answer:n.questions[e.id]||``})).filter(e=>e.answer!==``);t[e.key]={skipped:n.skipped,comment:n.comment,concern:n.concern,questions:r}}),!Object.values(t).some(e=>!e.skipped&&(e.questions.length>0||e.comment))&&!_.trim())throw Error(`Fill in at least one domain or dictate something`);return i.post(`/api/well-visit/shadess`,{patientAge:e,patientGender:n,domains:t,dictationText:_.trim()||null})},onSuccess:e=>{S(e.assessment),w({kind:`ok`,text:`Generated`});try{sessionStorage.setItem(`wv-shadess-assessment`,e.assessment)}catch{}},onError:e=>w({kind:`err`,text:e.message||`Generation failed`})});function E(e,t,n,r){g(i=>{let a=i[e],o={...a.questions,[t]:n},s=a.concern;return r!==void 0&&n===`yes`===r&&(s=!0),{...i,[e]:{...a,questions:o,concern:s}}})}function D(e,t){g(n=>({...n,[e]:{...n[e],comment:t}}))}function O(e){g(t=>({...t,[e]:{...t[e],skipped:!t[e].skipped}}))}function k(e){g(t=>({...t,[e]:{...t[e],concern:!t[e].concern}}))}function A(){g(p()),v(``),S(null),w(null)}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:`flex flex-wrap items-end 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:u+` w-32`,value:e,onChange:e=>t(e.target.value),placeholder:`e.g. 14 years`})]}),(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:u+` w-40`,value:n,onChange:e=>m(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.jsx)(`option`,{children:`Non-binary/Other`})]})]}),(0,c.jsx)(`div`,{className:`ml-auto text-xs text-muted-foreground`,children:`Recommended age 12 and older. Ask in private.`})]}),(0,c.jsxs)(`div`,{children:[(0,c.jsx)(`span`,{className:`text-xs font-semibold uppercase text-muted-foreground`,children:`Listen in (optional dictation)`}),(0,c.jsx)(o,{module:`shadess`,onTranscript:(e,t)=>{v(n=>t.appended&&n?n+` `+e:e),b(null)},onError:e=>b(e)}),y&&(0,c.jsx)(`div`,{className:`text-sm text-destructive`,children:y}),(0,c.jsx)(`textarea`,{className:u+` w-full mt-1 min-h-[60px] font-mono text-xs`,placeholder:`Or type the dictation directly. Used as supplementary input alongside the structured answers below.`,value:_,onChange:e=>v(e.target.value)})]})]}),l.map(e=>{let t=h[e.key];return(0,c.jsxs)(`div`,{className:`rounded-lg border border-border bg-card overflow-hidden`,style:{borderLeftWidth:3,borderLeftColor:e.color},"data-testid":`shadess-domain-`+e.key,children:[(0,c.jsxs)(`div`,{className:`px-4 py-2 flex items-center gap-2 bg-muted/30`,children:[(0,c.jsx)(`span`,{style:{color:e.color},children:e.icon}),(0,c.jsx)(`strong`,{className:`text-sm`,children:e.label}),(0,c.jsx)(`span`,{className:`text-xs text-muted-foreground flex-1 ml-2`,children:e.intro}),t.concern&&(0,c.jsx)(`span`,{className:`text-xs text-amber-700 bg-amber-100 px-2 py-0.5 rounded`,children:`⚠ Concern`}),(0,c.jsx)(`button`,{type:`button`,onClick:()=>k(e.key),className:`text-xs text-muted-foreground hover:text-foreground`,title:`Toggle concern flag`,children:`🚩`}),(0,c.jsxs)(`label`,{className:`text-xs text-muted-foreground flex items-center gap-1`,children:[(0,c.jsx)(`input`,{type:`checkbox`,checked:t.skipped,onChange:()=>O(e.key)}),` Skip`]})]}),(0,c.jsxs)(`div`,{className:`px-4 py-2 space-y-2 `+(t.skipped?`opacity-30`:``),children:[e.questions.map(n=>n.type===`yn`?(0,c.jsxs)(`div`,{className:`flex items-center gap-2 text-sm`,children:[(0,c.jsxs)(`span`,{className:`flex-1`,children:[n.text,n.concern_if!==void 0&&(0,c.jsxs)(`span`,{className:`text-[10px] text-muted-foreground ml-1`,children:[`(flag if `,n.concern_if?`Yes`:`No`,`)`]})]}),(0,c.jsxs)(`select`,{className:u+` text-xs py-1 w-24`,value:t.questions[n.id]||``,onChange:t=>E(e.key,n.id,t.target.value,n.concern_if),disabled:t.skipped,"data-testid":`shadess-q-`+n.id,children:[(0,c.jsx)(`option`,{value:``,children:`—`}),(0,c.jsx)(`option`,{value:`yes`,children:`Yes`}),(0,c.jsx)(`option`,{value:`no`,children:`No`})]})]},n.id):(0,c.jsxs)(`div`,{className:`flex items-center gap-2 text-sm`,children:[(0,c.jsx)(`span`,{className:`flex-1`,children:n.text}),(0,c.jsx)(`input`,{type:`text`,className:u+` text-xs py-1 flex-1 max-w-[260px]`,placeholder:n.placeholder,value:t.questions[n.id]||``,onChange:t=>E(e.key,n.id,t.target.value),disabled:t.skipped,"data-testid":`shadess-q-`+n.id})]},n.id)),(0,c.jsxs)(`div`,{className:`flex items-start gap-2 text-sm`,children:[(0,c.jsx)(`span`,{className:`flex-1 pt-1`,children:`Additional notes:`}),(0,c.jsx)(`textarea`,{rows:2,className:u+` text-xs flex-1 min-w-[200px] resize-y`,placeholder:`Free text comments for this domain…`,value:t.comment,onChange:t=>D(e.key,t.target.value),disabled:t.skipped})]})]})]},e.key)}),(0,c.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,c.jsx)(`button`,{type:`button`,onClick:()=>T.mutate(),disabled:T.isPending,className:f,"data-testid":`shadess-generate`,children:T.isPending?`Generating…`:`✨ Generate SSHADESS Assessment`}),(0,c.jsx)(`button`,{type:`button`,onClick:A,className:d,children:`↺ New patient`})]}),C&&(0,c.jsx)(`div`,{className:`text-sm `+(C.kind===`ok`?`text-green-600`:`text-destructive`),children:C.text}),x&&(0,c.jsxs)(`section`,{className:`rounded-lg border border-border bg-card`,children:[(0,c.jsx)(`header`,{className:`px-4 py-2 border-b border-border bg-muted/40`,children:(0,c.jsx)(`h3`,{className:`text-sm font-semibold`,children:`SSHADESS Assessment`})}),(0,c.jsx)(`div`,{className:`p-4 whitespace-pre-wrap text-sm`,children:x}),(0,c.jsx)(`div`,{className:`px-4 pb-4`,children:(0,c.jsx)(a,{text:x,onUpdate:S,sourceContext:_,exportLabel:`sshadess`,exportType:`sshadess`})}),(0,c.jsx)(`div`,{className:`px-4 pb-3 text-xs text-muted-foreground`,children:`ℹ︎ Auto-saved to session for the Visit Note tab — switch tabs to incorporate.`})]})]})}export{m as default}; |