feat: polish UX +5% with Cmd+K Command Palette, Web Audio tactile feedback, Patient Clinical Vitals HUD, Fast Macros & Toasts

This commit is contained in:
2026-09-05 15:44:58 -07:00
parent dd5057d4e3
commit bfe527fb33
9 changed files with 1191 additions and 21 deletions
+18 -10
View File
@@ -12,6 +12,8 @@ import {
} from '@/types/clinical';
import { SpineVisualizer } from '@/components/ui/SpineVisualizer';
import { AmbientAudioRecorder } from '@/components/ui/AmbientAudioRecorder';
import { PatientClinicalHud } from '@/components/ui/PatientClinicalHud';
import { clinicalAudio } from '@/lib/clinical-audio';
import { STANDARD_CPT_CODES, STANDARD_ICD10_CODES, DISCIPLINE_PRESETS } from '@/lib/mock-data';
import {
CheckCircle,
@@ -22,6 +24,7 @@ import {
ShieldCheck,
Video,
Layers,
Lock,
} from 'lucide-react';
interface SoapChartEditorProps {
@@ -109,6 +112,7 @@ export const SoapChartEditor: React.FC<SoapChartEditorProps> = ({
};
const handleSwitchDiscipline = (newDiscipline: ClinicalDiscipline) => {
clinicalAudio.playClick();
setDiscipline(newDiscipline);
const preset = DISCIPLINE_PRESETS[newDiscipline];
if (preset) {
@@ -126,6 +130,7 @@ export const SoapChartEditor: React.FC<SoapChartEditorProps> = ({
};
const handleToggleAdjustment = (entry: SpinalAdjustmentEntry) => {
clinicalAudio.playClick();
setAdjustments((prev) => {
const exists = prev.some((a) => a.vertebra === entry.vertebra);
if (exists) {
@@ -137,6 +142,7 @@ export const SoapChartEditor: React.FC<SoapChartEditorProps> = ({
};
const handleCloneLastNote = () => {
clinicalAudio.playClick();
setSubjective('Patient reports continued symptom improvement following last spinal adjustment. Morning stiffness resolved within 10 minutes. Current pain rated 3/10.');
setObjective('Palpation reveals decreased tone in lumbar paraspinals. Persistent fixation noted at L4-L5 with right sacral torsion.');
setAssessment('Care plan compliance high. Significant restoration of active range of motion noted.');
@@ -144,6 +150,7 @@ export const SoapChartEditor: React.FC<SoapChartEditorProps> = ({
};
const handleSignChart = () => {
clinicalAudio.playSuccess();
const now = new Date().toISOString();
setIsSigned(true);
setSignedTimestamp(now);
@@ -174,6 +181,7 @@ export const SoapChartEditor: React.FC<SoapChartEditorProps> = ({
};
const handleCreateSuperbillClick = () => {
clinicalAudio.playSuccess();
const savedNote: SoapNote = {
id: initialSoapNote?.id || `soap-${Date.now()}`,
tenantId: patient.tenantId,
@@ -193,14 +201,18 @@ export const SoapChartEditor: React.FC<SoapChartEditorProps> = ({
icd10Codes: selectedIcd10,
cptCodes: selectedCpt,
signedAt: signedTimestamp,
signedBy: `${provider.name}, ${provider.credentials}`,
signedBy: isSigned ? `${provider.name}, ${provider.credentials}` : undefined,
};
onSaveSoapNote(savedNote);
onGenerateSuperbill(savedNote);
};
return (
<div className="space-y-6">
<div className="space-y-4">
{/* Patient Clinical HUD Ribbon */}
<PatientClinicalHud patient={patient} />
{/* Top Patient Header Bar */}
<div className="bg-white border border-slate-200 rounded-xl p-5 shadow-xs flex flex-col md:flex-row md:items-center justify-between gap-4">
<div className="flex items-center gap-3">
@@ -218,14 +230,10 @@ export const SoapChartEditor: React.FC<SoapChartEditorProps> = ({
<h3 className="text-lg font-bold text-slate-900">
{patient.firstName} {patient.lastName}
</h3>
<span className="text-xs px-2.5 py-0.5 rounded-full bg-sky-50 text-sky-800 border border-sky-200 font-semibold">
Care Plan: Visit {patient.carePlan.completedVisits + 1} of {patient.carePlan.totalVisits}
</span>
{patient.activeMembership && (
<span className="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-800 border border-emerald-200 font-bold">
{patient.activeMembership}
</span>
)}
<div className="flex items-center gap-1.5 px-2.5 py-0.5 rounded-full bg-emerald-50 border border-emerald-200 text-emerald-800 text-[10px] font-semibold">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse" />
<span>HIPAA Vault Sync</span>
</div>
{isSigned ? (
<span className="text-xs px-2.5 py-0.5 rounded-full bg-emerald-50 text-emerald-700 border border-emerald-200 font-semibold flex items-center gap-1">
<ShieldCheck className="w-3.5 h-3.5" /> Signed &amp; Locked