pediatric-ai-scribe-v3/client/src/pages/hospital/LabsList.tsx
Daniel 8d5bf47f15 feat(notes): structured HospitalCourse + ChartReview match vanilla
Both pages were partial ports — HospitalCourse had a single "notes
textarea separated by blank lines" instead of the dynamic note cards
vanilla shipped, and ChartReview lacked per-visit type / specialist
/ specialty fields plus the Additional Labs block. These commits
close the gap.

HospitalCourse (ports public/components/hospital.html +
                 public/js/hospitalCourse.js @be14578):

  client/src/pages/hospital/DictatableCard.tsx — reusable card
    (title + date + meta children + content + per-card Recorder).
    Each note gets its own recorder so dictating into one card
    doesn't interrupt another in progress.
  client/src/pages/hospital/LabsList.tsx — dynamic (date, values)
    rows with add/remove.
  client/src/pages/hospital/ClarifyButton.tsx — "What's Missing?"
    → POST /api/hospital-course-clarify, renders the returned
    questions inline.
  client/src/pages/HospitalCourse.tsx — rewritten: ED Note card
    (date + ED labs + content + dictate), H&P card (date + content
    + dictate), Progress Notes as dynamic cards (date + type
    select matching vanilla's 6 options + content + per-card
    dictate + remove), separate Labs list, instructions,
    EditableResult output, ClarifyButton. Save/Load round-trips the
    entire structured note-set via JSON in the transcript column.

ChartReview (ports public/components/chart.html +
                   public/js/chartReview.js @be14578):

  client/src/pages/ChartReview.tsx — rewritten: each visit now has
    its own date + visit-type select (outpatient/subspecialty/ed),
    and when subspecialty is selected the specialist-name +
    specialty fields appear inline. Per-visit labs textarea.
    New Additional Labs block (reuses hospital/LabsList) for labs
    not tied to a visit. Submit splits visits by type into the
    server's visits / subspecialty / edVisits arrays, matching
    src/routes/chartReview.ts.
2026-04-24 05:38:27 +02:00

55 lines
2.2 KiB
TypeScript

// ============================================================
// LabsList — dynamic (date, values) rows. Port of hc-labs-container
// / cr-labs-container in the vanilla hospital.html / chart.html
// components. Pure controlled component — parent owns the array.
// ============================================================
export interface LabRow { date: string; values: string }
interface Props {
value: LabRow[];
onChange: (next: LabRow[]) => void;
placeholder?: string;
testIdPrefix?: string;
}
const input = 'rounded-md border border-input bg-background px-2 py-1 text-sm';
const btn = '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';
export function emptyLab(): LabRow { return { date: '', values: '' }; }
export default function LabsList({ value, onChange, placeholder, testIdPrefix = 'labs' }: Props) {
function patch(i: number, next: Partial<LabRow>) {
onChange(value.map((r, idx) => (idx === i ? { ...r, ...next } : r)));
}
function add() { onChange([...value, emptyLab()]); }
function remove(i: number) { onChange(value.filter((_, idx) => idx !== i)); }
return (
<div className="space-y-2" data-testid={testIdPrefix}>
{value.length === 0 && (
<div className="text-xs text-muted-foreground italic">No labs added.</div>
)}
{value.map((row, i) => (
<div key={i} className="flex flex-col sm:flex-row items-start gap-2" data-testid={testIdPrefix + '-row-' + i}>
<input
type="date"
value={row.date}
onChange={(e) => patch(i, { date: e.target.value })}
className={input + ' w-40 shrink-0'}
/>
<textarea
value={row.values}
onChange={(e) => patch(i, { values: e.target.value })}
placeholder={placeholder || 'e.g. WBC 12.5, H/H 10.2/31, BMP Na 138, K 3.5'}
className={input + ' flex-1 min-h-[60px] font-mono text-xs'}
/>
<button type="button" onClick={() => remove(i)} className="text-xs text-destructive hover:text-red-700" title="Remove">
🗑
</button>
</div>
))}
<button type="button" onClick={add} className={btn}>+ Add lab</button>
</div>
);
}