Hover state fed the nodes/edges useMemos, so every hover recreated both
arrays — React Flow re-measured the dimensionless nodes and the hovered
node's scale transform shifted it out from under the pointer, causing a
rapid dark↔light flicker. Drive hover focus through React context instead
so the nodes/edges props stay referentially stable (custom memoized node +
edge read the hovered id), and drop the scale transform. Theme the React
Flow controls via colorMode from next-themes so the zoom box matches the
active theme instead of rendering white.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The record graph was a cramped React Flow box wedged inside a sheet
section. Redesign it Obsidian-style — round nodes with the label
underneath, a soft glow, and a hover-focus that highlights a node plus
its neighbours while dimming the rest.
Move it out of the inline section: the sheet now shows an "Open graph"
button (closes the sheet, opens the graph in a large dialog) and a
clickable list of the patient's records (problems + visits); clicking a
record opens a detail dialog.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- deletePatient() lib fn (DELETE /api/patients/:fileNumber already existed)
- confirmed delete button in the patient sheet (full-clinician only)
- aggregate appointments/prescriptions/invoices into the sheet (by file #)
- new shared RecordGraph (@xyflow/react + d3-force) linking problems↔visits,
added as a "Record graph" section + reusable by AI Graph mode
- i18n keys for delete + new sheet sections
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>