pediatric-ai-scribe-v3/public/app/assets/Learning-DHnt_HCY.js
Daniel dc002360b0 perf(client): code-split every heavy route via React.lazy()
Cuts the initial bundle roughly in half. Users who open Home,
Extensions, or FAQ download ~343 kB / 106 kB gz instead of 817 kB /
230 kB gz. Heavy clinical reference data (PE_DATA, Fenton LMS,
Rosner BP splines, 15 Bedside drug panels, 10 Calculator formulas,
13 Settings sub-sections, 10 Admin sub-tabs) only loads when the
user opens that route.

client/src/App.tsx
  Every route except Home / Extensions / FAQ wrapped in
  React.lazy(() => import(...)) + <Suspense fallback>. Extensions and
  FAQ stay in the main chunk because they're small (3 kB, 2 kB) and
  likely visited early. The RouteFallback component shows a single
  "Loading…" line — Vite prefetches chunks on hover so the delay is
  typically invisible.

Resulting chunks (gzipped):
  • index.js             106 kB   React + Router + Query + Layout +
                                   Home + Extensions + FAQ
  • Bedside.js            33 kB   15 clinical dosing panels
  • PeGuide.js            36 kB   PE_DATA hierarchy + scales + sounds
  • Calculators.js        42 kB   All 10 calculators + BP Rosner
                                   coefficients + Fenton + BMI LMS
  • Settings.js           10 kB   13 Settings sub-sections
  • Admin.js               7 kB   10 Admin sub-tabs
  • Learning.js            3 kB
  • Fenton chunk (shared)  3 kB   Reused between Bedside neonatal
                                   and the Growth Charts calculator
  • Note pages (each)  1-2 kB   Encounter / SOAP / Well / Sick /
                                   Hospital / Chart / Dictation / Vax /
                                   Catch-up individually chunked

Vite's 500 kB chunk-size warning is gone. No functional changes.
2026-04-24 02:28:52 +02:00

1 line
No EOL
9.8 KiB
JavaScript

import{i as e,n as t,t as n}from"./jsx-runtime-ByY1xr43.js";import{a as r,i,o as a,s as o}from"./index-B0uH73Hx.js";var s=e(t(),1),c=n(),l=`rounded-lg border border-border bg-card p-5 space-y-3`,u=`px-3 py-1 rounded-full text-xs font-medium border transition-colors cursor-pointer`,d=`w-full rounded-md border border-input bg-background px-3 py-2 text-sm`,f=`rounded-md bg-primary text-primary-foreground px-3 py-2 text-sm font-medium disabled:opacity-50`,p=`rounded-md border border-border px-3 py-2 text-sm disabled:opacity-50`;function m(e){switch(e){case`quiz`:return`Quiz`;case`pearl`:return`Pearl`;case`presentation`:return`Slides`;default:return`Article`}}function h({row:e,onOpen:t}){return(0,c.jsxs)(`button`,{type:`button`,onClick:t,className:`w-full text-left rounded-lg border border-border bg-card hover:bg-muted/60 p-4 transition-colors`,"data-testid":`lh-feed-item-`+e.slug,children:[(0,c.jsxs)(`div`,{className:`flex items-center gap-2 text-xs text-muted-foreground uppercase tracking-wide mb-1`,children:[(0,c.jsx)(`span`,{className:`font-semibold`,children:m(e.content_type)}),e.category_name&&(0,c.jsxs)(`span`,{children:[`· `,e.category_name]}),e.question_count?(0,c.jsxs)(`span`,{children:[`· `,e.question_count,` Q`]}):null]}),(0,c.jsx)(`div`,{className:`text-sm font-semibold`,children:e.title}),e.subject&&(0,c.jsx)(`div`,{className:`text-xs text-muted-foreground mt-0.5 truncate`,children:e.subject})]})}function g({filter:e,query:t,onOpen:n}){let{data:r,isLoading:o,error:s}=a({queryKey:t?[`learning-search`,t]:e?[`learning-category`,e]:[`learning-feed`],queryFn:()=>t?i.get(`/api/learning/search?q=`+encodeURIComponent(t)):e?i.get(`/api/learning/category/`+encodeURIComponent(e)):i.get(`/api/learning/feed?limit=30`)});if(o)return(0,c.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Loading…`});if(s)return(0,c.jsx)(`div`,{className:`text-sm text-destructive`,children:s.message});let l=r?.content||[];return l.length===0?(0,c.jsx)(`div`,{className:`text-sm text-muted-foreground italic py-4`,children:`No content found.`}):(0,c.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,"data-testid":`lh-feed`,children:l.map(e=>(0,c.jsx)(h,{row:e,onOpen:()=>n(e.slug)},e.id))})}function _(e){let t={};for(let n of e)t[n.id]={optionIds:new Set};return t}function v({content:e,onReset:t}){let n=o(),[a,u]=(0,s.useState)(()=>_(e.questions)),[d,m]=(0,s.useState)(null),[h,g]=(0,s.useState)(null),v=r({mutationFn:e=>i.post(`/api/learning/submit-quiz`,e),onSuccess:t=>{m(t),n.invalidateQueries({queryKey:[`learning-content`,e.slug]})},onError:e=>g(e.message||`Submit failed`)});function y(t){t.preventDefault(),g(null);let n=e.questions.map(e=>{let t=a[e.id];return e.question_type===`multi`?{questionId:e.id,optionIds:Array.from(t?.optionIds||[])}:{questionId:e.id,optionId:t?.optionId??null}});v.mutate({contentId:e.id,answers:n})}function b(e,t){u(n=>({...n,[e.id]:{optionId:t,optionIds:new Set}}))}function x(e,t){u(n=>{let r=new Set(n[e.id]?.optionIds||[]);return r.has(t)?r.delete(t):r.add(t),{...n,[e.id]:{optionIds:r}}})}if(d){let n=d.percentage>=80?`bg-green-600`:d.percentage>=50?`bg-amber-500`:`bg-destructive`;return(0,c.jsxs)(`section`,{className:l,"data-testid":`lh-quiz-results`,children:[(0,c.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,c.jsx)(`h3`,{className:`text-base font-semibold`,children:`Results`}),(0,c.jsxs)(`span`,{className:`px-2 py-0.5 rounded text-xs font-semibold text-white `+n,"data-testid":`lh-quiz-score`,children:[d.score,`/`,d.total,` (`,d.percentage,`%)`]})]}),(0,c.jsx)(`div`,{className:`space-y-3`,children:d.results.map((e,t)=>(0,c.jsxs)(`div`,{className:`rounded-md border border-border p-3 bg-muted/30`,children:[(0,c.jsxs)(`div`,{className:`text-sm font-medium`,children:[(0,c.jsx)(`span`,{className:e.isCorrect?`text-green-600`:`text-destructive`,children:e.isCorrect?``:``}),` `,`Q`,t+1,`: `,e.questionText]}),!e.isCorrect&&e.correctOptionText&&(0,c.jsxs)(`div`,{className:`text-xs text-green-700 mt-1`,children:[(0,c.jsx)(`strong`,{children:`Correct:`}),` `,e.correctOptionText]}),!e.isCorrect&&e.selectedExplanation&&(0,c.jsxs)(`div`,{className:`text-xs text-destructive mt-1`,children:[(0,c.jsx)(`strong`,{children:`Why incorrect:`}),` `,e.selectedExplanation]}),e.generalExplanation&&(0,c.jsx)(`div`,{className:`text-xs text-muted-foreground mt-1`,children:e.generalExplanation})]},e.questionId))}),(0,c.jsxs)(`div`,{className:`flex gap-2`,children:[(0,c.jsx)(`button`,{type:`button`,className:p,onClick:()=>{m(null),u(_(e.questions))},children:`Retake`}),(0,c.jsx)(`button`,{type:`button`,className:f,onClick:t,children:`Back to Feed`})]})]})}return(0,c.jsxs)(`section`,{className:l,"data-testid":`lh-quiz`,children:[(0,c.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,c.jsx)(`h3`,{className:`text-base font-semibold`,children:`Quiz`}),(0,c.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[e.questions.length,` question`,e.questions.length===1?``:`s`]})]}),(0,c.jsxs)(`form`,{onSubmit:y,className:`space-y-4`,children:[e.questions.map((e,t)=>{let n=e.question_type===`multi`,r=e.question_type===`true_false`?`True / False`:n?`Multiple Select`:`Single Choice`;return(0,c.jsxs)(`div`,{className:`rounded-md border border-border p-3 space-y-2 bg-muted/30`,children:[(0,c.jsxs)(`div`,{className:`flex items-center justify-between text-xs text-muted-foreground`,children:[(0,c.jsxs)(`span`,{className:`font-semibold`,children:[`Q`,t+1]}),(0,c.jsx)(`span`,{children:r})]}),(0,c.jsx)(`div`,{className:`text-sm font-medium`,children:e.question_text}),n&&(0,c.jsx)(`div`,{className:`text-xs text-muted-foreground italic`,children:`Select all that apply`}),(0,c.jsx)(`div`,{className:`space-y-1`,children:e.options.map(t=>{let r=a[e.id],i=n?r?.optionIds.has(t.id)===!0:r?.optionId===t.id;return(0,c.jsxs)(`label`,{className:`flex items-start gap-2 text-sm cursor-pointer hover:bg-muted/50 rounded px-2 py-1`,children:[(0,c.jsx)(`input`,{type:n?`checkbox`:`radio`,name:`q-`+e.id,checked:i,onChange:()=>n?x(e,t.id):b(e,t.id),className:`mt-0.5`}),(0,c.jsx)(`span`,{children:t.option_text})]},t.id)})})]},e.id)}),h&&(0,c.jsx)(`div`,{className:`text-sm text-destructive`,children:h}),(0,c.jsx)(`button`,{type:`submit`,className:f,disabled:v.isPending,"data-testid":`btn-lh-submit-quiz`,children:v.isPending?`Submitting…`:`Submit Answers`})]})]})}function y({slug:e,onBack:t}){let{data:n,isLoading:r,error:o}=a({queryKey:[`learning-content`,e],queryFn:()=>i.get(`/api/learning/content/`+encodeURIComponent(e))});if(r)return(0,c.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Loading…`});if(o)return(0,c.jsx)(`div`,{className:`text-sm text-destructive`,children:o.message});if(!n)return null;let s=n.content;return(0,c.jsxs)(`div`,{className:`space-y-4`,children:[(0,c.jsx)(`button`,{type:`button`,className:p,onClick:t,"data-testid":`btn-lh-back`,children:`← Back to Feed`}),(0,c.jsxs)(`section`,{className:l,"data-testid":`lh-viewer`,children:[(0,c.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,c.jsx)(`h2`,{className:`text-xl font-semibold`,"data-testid":`lh-viewer-title`,children:s.title}),(0,c.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[m(s.content_type),s.category_name?` · `+s.category_name:``,s.author_name?` · `+s.author_name:``]})]}),s.content_type===`presentation`?(0,c.jsxs)(`div`,{className:`text-center py-8 space-y-3 bg-muted/30 rounded-md`,children:[(0,c.jsx)(`div`,{className:`text-4xl`,children:`📊`}),(0,c.jsx)(`div`,{className:`text-sm font-medium`,children:s.title}),(0,c.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Slide rendering lives in the legacy viewer.`}),(0,c.jsx)(`a`,{href:`/#learning/`+encodeURIComponent(s.slug),className:f+` inline-block`,rel:`noreferrer`,children:`Open in legacy viewer`})]}):(0,c.jsx)(`div`,{className:`whitespace-pre-wrap text-sm leading-relaxed`,"data-testid":`lh-viewer-body`,children:s.body||``})]}),s.progress&&s.progress.length>0&&(0,c.jsxs)(`section`,{className:l,children:[(0,c.jsx)(`h3`,{className:`text-base font-semibold`,children:`Your past attempts`}),(0,c.jsx)(`div`,{className:`space-y-1 text-sm`,children:s.progress.map((e,t)=>{let n=e.total>0?Math.round(e.score/e.total*100):0,r=n>=70?`text-green-600`:`text-amber-600`;return(0,c.jsxs)(`div`,{className:`flex justify-between border-b border-border py-1`,children:[(0,c.jsx)(`span`,{children:new Date(e.completed_at).toLocaleDateString()}),(0,c.jsxs)(`span`,{className:`font-semibold `+r,children:[e.score,`/`,e.total,` (`,n,`%)`]})]},t)})})]}),s.questions&&s.questions.length>0&&(0,c.jsx)(v,{content:s,onReset:t})]})}function b(){let[e,t]=(0,s.useState)(``),[n,r]=(0,s.useState)(``),[o,f]=(0,s.useState)(null),{data:p}=a({queryKey:[`learning-categories`],queryFn:()=>i.get(`/api/learning/categories`)});return o?(0,c.jsx)(`div`,{className:`max-w-4xl mx-auto p-6`,children:(0,c.jsx)(y,{slug:o,onBack:()=>f(null)})}):(0,c.jsxs)(`div`,{className:`max-w-4xl mx-auto p-6 space-y-4`,children:[(0,c.jsxs)(`header`,{children:[(0,c.jsx)(`h1`,{className:`text-2xl font-semibold`,children:`Learning Hub`}),(0,c.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Pediatric education, clinical pearls, and self-assessment quizzes.`})]}),(0,c.jsx)(`div`,{className:l,children:(0,c.jsx)(`input`,{type:`search`,className:d,placeholder:`Search topics, subjects…`,value:e,onChange:e=>t(e.target.value),"data-testid":`lh-search`})}),(0,c.jsxs)(`div`,{className:`flex flex-wrap gap-2`,"data-testid":`lh-categories`,children:[(0,c.jsx)(`button`,{type:`button`,onClick:()=>r(``),className:u+(n===``?` bg-primary text-primary-foreground border-primary`:` bg-muted hover:bg-muted/80`),children:`All`}),p?.categories.map(e=>(0,c.jsx)(`button`,{type:`button`,onClick:()=>r(e.slug),className:u+(n===e.slug?` bg-primary text-primary-foreground border-primary`:` bg-muted hover:bg-muted/80`),"data-testid":`lh-cat-`+e.slug,children:e.name},e.id))]}),(0,c.jsx)(g,{filter:n,query:e.trim(),onOpen:e=>f(e)})]})}export{b as default};