diff --git a/client/src/App.tsx b/client/src/App.tsx index 6e43c49..cf4ed4c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -7,6 +7,9 @@ import Dictation from '@/pages/Dictation'; import Encounter from '@/pages/Encounter'; import Soap from '@/pages/Soap'; import SickVisit from '@/pages/SickVisit'; +import HospitalCourse from '@/pages/HospitalCourse'; +import ChartReview from '@/pages/ChartReview'; +import WellVisit from '@/pages/WellVisit'; const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 30_000, retry: 1 } }, @@ -44,6 +47,9 @@ export default function App() { } /> } /> } /> + } /> + } /> + } /> } /> } /> {/* catch-all falls back to home while more tabs port over */} diff --git a/client/src/components/Layout.tsx b/client/src/components/Layout.tsx index 57f53c5..392d3e8 100644 --- a/client/src/components/Layout.tsx +++ b/client/src/components/Layout.tsx @@ -29,10 +29,10 @@ const NAV: NavGroup[] = [ { label: 'Notes', items: [ - { to: '/hospital', label: 'Hospital Course', available: false }, - { to: '/chart', label: 'Chart Review', available: false }, + { to: '/hospital', label: 'Hospital Course', available: true }, + { to: '/chart', label: 'Chart Review', available: true }, { to: '/soap', label: 'SOAP Note', available: true }, - { to: '/wellvisit', label: 'Well Visit', available: false }, + { to: '/wellvisit', label: 'Well Visit', available: true }, { to: '/sickvisit', label: 'Sick Visit', available: true }, ], }, diff --git a/client/src/pages/ChartReview.tsx b/client/src/pages/ChartReview.tsx new file mode 100644 index 0000000..673c34e --- /dev/null +++ b/client/src/pages/ChartReview.tsx @@ -0,0 +1,163 @@ +// ============================================================ +// CHART REVIEW — /api/generate-chart-review +// ============================================================ + +import { useState } from 'react'; +import { useMutation } from '@tanstack/react-query'; +import { api, ApiError } from '@/lib/api'; +import type { ChartReviewOk } from '@/shared/types'; + +type ReviewType = 'outpatient' | 'subspecialty' | 'ed'; + +interface VisitInput { date: string; content: string; labs: string } + +function emptyVisit(): VisitInput { return { date: '', content: '', labs: '' }; } + +export default function ChartReview() { + const [type, setType] = useState('outpatient'); + const [patientAge, setPatientAge] = useState(''); + const [patientGender, setPatientGender] = useState(''); + const [pmh, setPmh] = useState(''); + const [visits, setVisits] = useState([emptyVisit()]); + const [additionalInstructions, setAdditionalInstructions] = useState(''); + const [result, setResult] = useState(null); + + const generate = useMutation({ + mutationFn: (body) => api.post('/api/generate-chart-review', body), + onSuccess: (data) => setResult(data.review), + }); + + function updateVisit(i: number, patch: Partial) { + setVisits((vs) => vs.map((v, idx) => (idx === i ? { ...v, ...patch } : v))); + } + + function submit(e: React.FormEvent) { + e.preventDefault(); + setResult(null); + const filled = visits.filter((v) => v.content.trim()); + generate.mutate({ + type, + patientAge, patientGender, pmh, + visits: type === 'outpatient' ? filled : undefined, + subspecialty: type === 'subspecialty' ? filled : undefined, + edVisits: type === 'ed' ? filled : undefined, + additionalInstructions: additionalInstructions || undefined, + }); + } + + const input = 'w-full rounded-md border border-input bg-background px-3 py-2 text-sm'; + + return ( +
+
+

Chart Review

+

+ Past visits → summary for pre-charting. +

+
+ +
+
+ + + + +
+ +
+
+ Visits + +
+ {visits.map((v, i) => ( +
+
+ updateVisit(i, { date: e.target.value })} + /> + {visits.length > 1 && ( + + )} +
+