diff --git a/package-lock.json b/package-lock.json
index ad39d79..30a8234 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,8 @@
"name": "mediusa-clinic-os",
"version": "0.1.0",
"dependencies": {
+ "jspdf": "^4.2.1",
+ "lucide-react": "^1.41.0",
"next": "16.3.4",
"react": "19.2.8",
"react-dom": "19.2.8"
@@ -228,6 +230,15 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@babel/runtime": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
+ "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/template": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
@@ -1718,6 +1729,19 @@
"undici-types": "~6.21.0"
}
},
+ "node_modules/@types/pako": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
+ "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/raf": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
+ "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@types/react": {
"version": "19.2.18",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz",
@@ -1738,6 +1762,13 @@
"@types/react": "^19.2.0"
}
},
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.69.0.tgz",
@@ -2680,6 +2711,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/base64-arraybuffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+ "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/baseline-browser-mapping": {
"version": "2.11.21",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.21.tgz",
@@ -2830,6 +2871,26 @@
],
"license": "CC-BY-4.0"
},
+ "node_modules/canvg": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz",
+ "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@types/raf": "^3.4.0",
+ "core-js": "^3.8.3",
+ "raf": "^3.4.1",
+ "regenerator-runtime": "^0.13.7",
+ "rgbcolor": "^1.0.1",
+ "stackblur-canvas": "^2.0.0",
+ "svg-pathdata": "^6.0.3"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -2887,6 +2948,21 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/core-js": {
+ "version": "3.50.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.50.0.tgz",
+ "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2902,6 +2978,16 @@
"node": ">= 8"
}
},
+ "node_modules/css-line-break": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
+ "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "utrie": "^1.0.2"
+ }
+ },
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -3054,6 +3140,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/dompurify": {
+ "version": "3.4.14",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.14.tgz",
+ "integrity": "sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optional": true,
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -3777,6 +3873,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-png": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz",
+ "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/pako": "^2.0.3",
+ "iobuffer": "^5.3.2",
+ "pako": "^2.1.0"
+ }
+ },
"node_modules/fastq": {
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz",
@@ -3787,6 +3894,12 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/fflate": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
+ "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
+ "license": "MIT"
+ },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -4175,6 +4288,20 @@
"hermes-estree": "0.25.1"
}
},
+ "node_modules/html2canvas": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
+ "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "css-line-break": "^2.1.0",
+ "text-segmentation": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -4227,6 +4354,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/iobuffer": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
+ "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
+ "license": "MIT"
+ },
"node_modules/is-array-buffer": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@@ -4777,6 +4910,23 @@
"node": ">=6"
}
},
+ "node_modules/jspdf": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.1.tgz",
+ "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.6",
+ "fast-png": "^6.2.0",
+ "fflate": "^0.8.1"
+ },
+ "optionalDependencies": {
+ "canvg": "^3.0.11",
+ "core-js": "^3.6.0",
+ "dompurify": "^3.3.1",
+ "html2canvas": "^1.0.0-rc.5"
+ }
+ },
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@@ -5156,6 +5306,15 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lucide-react": {
+ "version": "1.41.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.41.0.tgz",
+ "integrity": "sha512-6lksP35l6KszDKUeRTi4LV7i6DEe0Yzl2ALJm9j4c5xEYN91GdW1xGsawGMOg2mgjF5GHBVX8pKX9kP+cWsP3Q==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -5573,6 +5732,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/pako": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-2.2.0.tgz",
+ "integrity": "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
+ "license": "(MIT AND Zlib)"
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -5613,6 +5788,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -5724,6 +5906,16 @@
],
"license": "MIT"
},
+ "node_modules/raf": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "performance-now": "^2.1.0"
+ }
+ },
"node_modules/react": {
"version": "19.2.8",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
@@ -5775,6 +5967,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/regexp.prototype.flags": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
@@ -5851,6 +6050,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/rgbcolor": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
+ "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
+ "license": "MIT OR SEE LICENSE IN FEEL-FREE.md",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.8.15"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -6173,6 +6382,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/stackblur-canvas": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
+ "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.14"
+ }
+ },
"node_modules/stop-iteration-iterator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
@@ -6373,6 +6592,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/svg-pathdata": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+ "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/tailwindcss": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
@@ -6394,6 +6623,16 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/text-segmentation": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
+ "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "utrie": "^1.0.2"
+ }
+ },
"node_modules/tinyglobby": {
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
@@ -6734,6 +6973,16 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/utrie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
+ "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "base64-arraybuffer": "^1.0.2"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index e1536e9..7bff733 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,8 @@
"lint": "eslint"
},
"dependencies": {
+ "jspdf": "^4.2.1",
+ "lucide-react": "^1.41.0",
"next": "16.3.4",
"react": "19.2.8",
"react-dom": "19.2.8"
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 9852c15..6ba36e0 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,29 +1,36 @@
-import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
-import "./globals.css";
+import type { Metadata } from 'next';
+import { Geist, Geist_Mono } from 'next/font/google';
+import './globals.css';
const geistSans = Geist({
- variable: "--font-geist-sans",
- subsets: ["latin"],
+ variable: '--font-geist-sans',
+ subsets: ['latin'],
});
const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
- subsets: ["latin"],
+ variable: '--font-geist-mono',
+ subsets: ['latin'],
});
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: 'Mediusa Clinic OS — Next-Gen Practice Management Platform',
+ description:
+ 'High-speed, proprietary white-label medical practice management platform for chiropractors and wellness clinics. Scheduling, paperless intake, ambient AI clinical notes, and billing.',
};
-export default function RootLayout({ children }: LayoutProps<"/">) {
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
return (
-
{children}
+
+ {children}
+
);
}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index c887311..678f250 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,69 +1,398 @@
-import Image from "next/image";
+'use client';
+
+import React, { useState } from 'react';
+import {
+ INITIAL_TENANTS,
+ INITIAL_PROVIDERS,
+ INITIAL_PATIENTS,
+ INITIAL_APPOINTMENTS,
+ INITIAL_SOAP_NOTES,
+ INITIAL_SUPERBILLS,
+} from '@/lib/mock-data';
+import {
+ ClinicTenant,
+ Provider,
+ Patient,
+ Appointment,
+ SoapNote,
+ Superbill,
+} from '@/types/clinical';
+import { CalendarView } from '@/components/calendar/CalendarView';
+import { SoapChartEditor } from '@/components/charting/SoapChartEditor';
+import { SuperbillView } from '@/components/billing/SuperbillView';
+import { RetentionView } from '@/components/retention/RetentionView';
+import { PatientPortalView } from '@/components/intake/PatientPortalView';
+import { SuperAdminView } from '@/components/admin/SuperAdminView';
+import {
+ Calendar,
+ FileText,
+ DollarSign,
+ Users,
+ ShieldCheck,
+ Building2,
+ Globe,
+ Sparkles,
+ ChevronDown,
+ Stethoscope,
+ Laptop,
+ CheckCircle2,
+} from 'lucide-react';
export default function Home() {
+ // Global Multi-Tenant State
+ const [tenants, setTenants] = useState(INITIAL_TENANTS);
+ const [activeTenantId, setActiveTenantId] = useState(INITIAL_TENANTS[0].id);
+
+ // Active Navigation Mode: 'clinic' (EHR Practice OS) | 'patient' (Booking/Intake) | 'superadmin' (Mediusa Command)
+ const [portalMode, setPortalMode] = useState<'clinic' | 'patient' | 'superadmin'>('clinic');
+
+ // Clinic Portal Sub-Tabs: 'calendar' | 'charting' | 'billing' | 'retention'
+ const [clinicTab, setClinicTab] = useState<'calendar' | 'charting' | 'billing' | 'retention'>('calendar');
+
+ // Active Entities
+ const [appointments, setAppointments] = useState(INITIAL_APPOINTMENTS);
+ const [patients, setPatients] = useState(INITIAL_PATIENTS);
+ const [soapNotes, setSoapNotes] = useState(INITIAL_SOAP_NOTES);
+ const [superbills, setSuperbills] = useState(INITIAL_SUPERBILLS);
+
+ const [activePatient, setActivePatient] = useState(INITIAL_PATIENTS[0]); // Marcus Chen
+ const [activeSoapNote, setActiveSoapNote] = useState(INITIAL_SOAP_NOTES[0]);
+ const [activeSuperbill, setActiveSuperbill] = useState(INITIAL_SUPERBILLS[0]);
+
+ const activeTenant = tenants.find((t) => t.id === activeTenantId) || tenants[0];
+ const activeProviders = INITIAL_PROVIDERS.filter((p) => p.tenantId === activeTenant.id);
+ const activeProvider = activeProviders[0] || INITIAL_PROVIDERS[0];
+
+ // Handlers
+ const handleSelectAppointment = (apt: Appointment) => {
+ const patientMatch = patients.find((p) => p.id === apt.patientId) || patients[0];
+ setActivePatient(patientMatch);
+
+ const existingSoap = soapNotes.find((s) => s.patientId === apt.patientId && s.appointmentId === apt.id);
+ setActiveSoapNote(existingSoap);
+ setClinicTab('charting');
+ };
+
+ const handleUpdateAppointmentStatus = (aptId: string, status: Appointment['status']) => {
+ setAppointments((prev) =>
+ prev.map((a) => (a.id === aptId ? { ...a, status } : a))
+ );
+ };
+
+ const handleSaveSoapNote = (note: SoapNote) => {
+ setSoapNotes((prev) => {
+ const idx = prev.findIndex((s) => s.id === note.id);
+ if (idx >= 0) {
+ const copy = [...prev];
+ copy[idx] = note;
+ return copy;
+ }
+ return [...prev, note];
+ });
+ setActiveSoapNote(note);
+ };
+
+ const handleGenerateSuperbillFromNote = (note: SoapNote) => {
+ const newSb: Superbill = {
+ id: `sb-${Date.now()}`,
+ tenantId: activeTenant.id,
+ invoiceNumber: `SB-2026-${Math.floor(1000 + Math.random() * 9000)}`,
+ patientId: activePatient.id,
+ patientName: `${activePatient.firstName} ${activePatient.lastName}`,
+ patientDob: activePatient.dob,
+ patientAddress: activePatient.address,
+ providerName: note.providerName,
+ providerNpi: activeProvider.npi,
+ clinicName: activeTenant.name,
+ clinicAddress: activeTenant.address,
+ clinicTaxId: activeTenant.taxId,
+ dateOfService: note.date,
+ posCode: '11 (Office)',
+ icd10Codes: note.icd10Codes,
+ items: note.cptCodes.map((cpt) => ({
+ cptCode: cpt.code,
+ description: cpt.description,
+ units: 1,
+ rate: cpt.fee,
+ total: cpt.fee,
+ })),
+ totalAmount: note.cptCodes.reduce((sum, c) => sum + c.fee, 0),
+ patientPaid: note.cptCodes.reduce((sum, c) => sum + c.fee, 0),
+ balanceDue: 0,
+ paymentMethod: 'Stripe Card',
+ generatedAt: new Date().toISOString(),
+ };
+
+ setSuperbills((prev) => [newSb, ...prev]);
+ setActiveSuperbill(newSb);
+ setClinicTab('billing');
+ };
+
+ const handleMarkPaid = (superbillId: string, method: Superbill['paymentMethod']) => {
+ setSuperbills((prev) =>
+ prev.map((sb) =>
+ sb.id === superbillId
+ ? { ...sb, balanceDue: 0, patientPaid: sb.totalAmount, paymentMethod: method }
+ : sb
+ )
+ );
+ if (activeSuperbill.id === superbillId) {
+ setActiveSuperbill((prev) => ({
+ ...prev,
+ balanceDue: 0,
+ patientPaid: prev.totalAmount,
+ paymentMethod: method,
+ }));
+ }
+ };
+
+ const handlePatientBookingComplete = (newAptData: any) => {
+ const newApt: Appointment = {
+ id: `apt-${Date.now()}`,
+ tenantId: activeTenant.id,
+ patientId: `pat-${Date.now()}`,
+ ...newAptData,
+ };
+ setAppointments((prev) => [newApt, ...prev]);
+ };
+
+ const handleAddTenant = (newTenant: ClinicTenant) => {
+ setTenants((prev) => [...prev, newTenant]);
+ };
+
+ const handleSwitchTenant = (tenantId: string) => {
+ setActiveTenantId(tenantId);
+ setPortalMode('clinic');
+ setClinicTab('calendar');
+ };
+
return (
-
-
-
-
);
}
diff --git a/src/components/admin/SuperAdminView.tsx b/src/components/admin/SuperAdminView.tsx
new file mode 100644
index 0000000..ef50a0a
--- /dev/null
+++ b/src/components/admin/SuperAdminView.tsx
@@ -0,0 +1,359 @@
+'use client';
+
+import React, { useState } from 'react';
+import { ClinicTenant } from '@/types/clinical';
+import {
+ Building2,
+ TrendingUp,
+ DollarSign,
+ Users,
+ Plus,
+ ExternalLink,
+ ShieldCheck,
+ CheckCircle2,
+ Sparkles,
+ Zap,
+ Globe,
+ Settings,
+} from 'lucide-react';
+
+interface SuperAdminViewProps {
+ tenants: ClinicTenant[];
+ onAddTenant: (tenant: ClinicTenant) => void;
+ onSwitchTenant: (tenantId: string) => void;
+}
+
+export const SuperAdminView: React.FC = ({
+ tenants,
+ onAddTenant,
+ onSwitchTenant,
+}) => {
+ const [showProvisionModal, setShowProvisionModal] = useState(false);
+ const [newClinicName, setNewClinicName] = useState('');
+ const [newSlug, setNewSlug] = useState('');
+ const [newDoctorName, setNewDoctorName] = useState('');
+ const [newNpi, setNewNpi] = useState('');
+ const [newPlan, setNewPlan] = useState<'Starter' | 'Pro Clinic' | 'Multi-Doc Enterprise'>('Pro Clinic');
+ const [isProvisioning, setIsProvisioning] = useState(false);
+ const [provisionSuccess, setProvisionSuccess] = useState(false);
+
+ const totalMRR = tenants.reduce((sum, t) => sum + t.mrr, 0) + 3120; // 24 clinics total simulated
+ const totalClinics = tenants.length + 21; // 24 active clinics
+
+ const handleNameChange = (val: string) => {
+ setNewClinicName(val);
+ setNewSlug(
+ val
+ .toLowerCase()
+ .replace(/[^a-z0-9]/g, '-')
+ .replace(/-+/g, '-')
+ .replace(/^-|-$/g, '')
+ );
+ };
+
+ const handleProvisionSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ setIsProvisioning(true);
+
+ setTimeout(() => {
+ const created: ClinicTenant = {
+ id: `tenant-${Date.now()}`,
+ name: newClinicName,
+ slug: newSlug,
+ domain: `${newSlug}.mediusa.app`,
+ phone: '(555) 839-2041',
+ email: `contact@${newSlug}.com`,
+ address: '100 Wellness Way, Suite 10',
+ cityStateZip: 'Irvine, CA 92618',
+ npi: newNpi || '1992019481',
+ taxId: '82-9481920',
+ logoText: newClinicName.slice(0, 10).toUpperCase(),
+ brandColor: '#0d9488',
+ accentColor: '#14b8a6',
+ plan: newPlan,
+ mrr: newPlan === 'Starter' ? 99 : newPlan === 'Pro Clinic' ? 149 : 199,
+ stripeConnected: true,
+ createdAt: new Date().toISOString().split('T')[0],
+ };
+
+ onAddTenant(created);
+ setIsProvisioning(false);
+ setProvisionSuccess(true);
+
+ setTimeout(() => {
+ setProvisionSuccess(false);
+ setShowProvisionModal(false);
+ onSwitchTenant(created.id);
+ }, 1200);
+ }, 1500);
+ };
+
+ return (
+
+ {/* Super-Admin Agency Banner */}
+
+
+
+
+
+
+
+ AI PILOTS / MEDIUSA AGENCY ENGINE
+
+
+
+ Clinic OS Multi-Tenant Command Center
+
+
+ Autonomous Practice Management SaaS Platform. Onboard 20–100+ chiropractic & wellness clinics with zero developer overhead.
+
+
+
+
setShowProvisionModal(true)}
+ className="px-5 py-2.5 rounded-xl bg-gradient-to-r from-teal-500 to-emerald-500 hover:from-teal-400 hover:to-emerald-400 text-slate-950 text-xs font-black flex items-center gap-2 shadow-lg shadow-teal-500/20 transition shrink-0"
+ >
+
+ Provision New Clinic (60s)
+
+
+
+ {/* High-Level SaaS Metrics */}
+
+
+
+ Current SaaS MRR
+
+
+
+ ${totalMRR.toLocaleString()}.00
+
+
+ +$596.00 added this month
+
+
+
+
+
+ Target MRR @ 100 Clinics
+
+
+
$17,900.00
+
Based on $179 avg clinic subscription
+
+
+
+
+ Active Clinic Tenants
+
+
+
{totalClinics} Clinics
+
100% white-label retention
+
+
+
+
+ Active Patients Managed
+
+
+
3,842
+
Across California & US clinics
+
+
+
+ {/* Active Clinic Tenant Registry */}
+
+
+
+
Client Tenant Registry
+
+ Each clinic operates on its isolated schema with custom branding and domain routing.
+
+
+
+ {tenants.length} Primary Demo Instances Loaded
+
+
+
+
+ {tenants.map((t) => (
+
+
+
+
+
{t.name}
+
+ {t.plan} (${t.mrr}/mo)
+
+
+ Stripe Active
+
+
+
+
+
+
+ https://{t.domain}
+
+ •
+ NPI: {t.npi}
+ •
+ EIN: {t.taxId}
+ •
+ Created: {t.createdAt}
+
+
+
+
+ onSwitchTenant(t.id)}
+ className="px-3.5 py-1.5 bg-teal-500 hover:bg-teal-400 text-slate-950 font-bold text-xs rounded-xl shadow transition flex items-center gap-1.5"
+ >
+
+ Launch Clinic OS
+
+
+
+ ))}
+
+
+
+ {/* 60-Second Instant Clinic Provisioning Modal */}
+ {showProvisionModal && (
+
+
+
+
+
+
+
+
+
+ 60-Second Instant Clinic Provisioning
+
+
+ Creates database tenant, seed templates & custom domain
+
+
+
+
+
+ {provisionSuccess ? (
+
+
+
Clinic Provisioned Successfully!
+
+ Tenant schema generated. Redirecting to newly created white-labeled instance...
+
+
+ ) : (
+
+ )}
+
+
+ )}
+
+ );
+};
diff --git a/src/components/billing/SuperbillView.tsx b/src/components/billing/SuperbillView.tsx
new file mode 100644
index 0000000..1471a33
--- /dev/null
+++ b/src/components/billing/SuperbillView.tsx
@@ -0,0 +1,346 @@
+'use client';
+
+import React, { useState } from 'react';
+import { Superbill, ClinicTenant } from '@/types/clinical';
+import { generateSuperbillPdf } from '@/lib/pdf-generator';
+import {
+ FileText,
+ Download,
+ CreditCard,
+ CheckCircle2,
+ ShieldAlert,
+ ArrowLeft,
+ DollarSign,
+ Printer,
+ Sparkles,
+ ExternalLink,
+} from 'lucide-react';
+
+interface SuperbillViewProps {
+ superbill: Superbill;
+ activeTenant: ClinicTenant;
+ onBack: () => void;
+ onMarkPaid: (superbillId: string, method: Superbill['paymentMethod']) => void;
+}
+
+export const SuperbillView: React.FC = ({
+ superbill,
+ activeTenant,
+ onBack,
+ onMarkPaid,
+}) => {
+ const [showPaymentModal, setShowPaymentModal] = useState(false);
+ const [isProcessingStripe, setIsProcessingStripe] = useState(false);
+ const [paymentSuccess, setPaymentSuccess] = useState(false);
+
+ const handleDownloadPdf = () => {
+ generateSuperbillPdf(superbill);
+ };
+
+ const handleStripePay = (method: Superbill['paymentMethod']) => {
+ setIsProcessingStripe(true);
+ setTimeout(() => {
+ setIsProcessingStripe(false);
+ setPaymentSuccess(true);
+ onMarkPaid(superbill.id, method);
+ setTimeout(() => {
+ setShowPaymentModal(false);
+ setPaymentSuccess(false);
+ }, 1500);
+ }, 1200);
+ };
+
+ return (
+
+ {/* Top Header Bar */}
+
+
+
+
+
+
+
+
+ Superbill {superbill.invoiceNumber}
+
+
+ {superbill.balanceDue === 0 ? 'Paid in Full' : 'Balance Due'}
+
+
+
+ Clean Medical Claim Standard (CMS-1500 / 837P Ready) for {superbill.patientName}
+
+
+
+
+
+
+
+ Download PDF Superbill
+
+
+ {superbill.balanceDue > 0 && (
+ setShowPaymentModal(true)}
+ className="px-4 py-2 rounded-xl bg-teal-500 hover:bg-teal-400 text-slate-950 text-xs font-bold flex items-center gap-1.5 shadow-lg shadow-teal-500/20 transition"
+ >
+
+ Collect with Stripe
+
+ )}
+
+
+
+ {/* Main Printed Superbill Card Simulation */}
+
+ {/* Clinic & Statement Header */}
+
+
+
+ PRACTICE MANAGEMENT SUPERBILL
+
+
{superbill.clinicName}
+
{superbill.clinicAddress}
+
+ Tax ID / EIN: {superbill.clinicTaxId} • POS:{' '}
+ {superbill.posCode}
+
+
+
+
+
Invoice Number
+
{superbill.invoiceNumber}
+
Date of Service
+
{superbill.dateOfService}
+
+
+
+ {/* Provider & Patient 2-Col Info */}
+
+ {/* Provider */}
+
+
+ Rendering Provider
+
+
{superbill.providerName}
+
+ National Provider Identifier (NPI):{' '}
+ {superbill.providerNpi}
+
+
Specialty: Chiropractic Clinical Biomechanics
+
+
+ {/* Patient */}
+
+
+ Patient Demographics
+
+
{superbill.patientName}
+
DOB: {superbill.patientDob}
+
Address: {superbill.patientAddress}
+
+
+
+ {/* Diagnosis ICD-10 Section */}
+
+
+ Primary Diagnosis Codes (ICD-10-CM)
+
+
+ {superbill.icd10Codes.map((icd, index) => (
+
+
+ {index + 1}
+
+ {icd.code}
+ {icd.description}
+
+ ))}
+
+
+
+ {/* Procedures Table */}
+
+
+ Rendered Procedures (CPT Codes)
+
+
+
+
+
+ CPT Code
+ Service Description
+ Units
+ Fee
+ Total
+
+
+
+ {superbill.items.map((item) => (
+
+ {item.cptCode}
+ {item.description}
+ {item.units}
+ ${item.rate.toFixed(2)}
+
+ ${item.total.toFixed(2)}
+
+
+ ))}
+
+
+
+
+
+ {/* Financial Summary */}
+
+
+
+ This Superbill contains all required claim elements (CMS-1500 Boxes 21, 24, 25, 31, 33)
+ for direct patient submission to their private health insurance or FSA/HSA reimbursement plan.
+
+
+ Payment Method: {superbill.paymentMethod}
+
+
+
+
+
+ Total Charges:
+ ${superbill.totalAmount.toFixed(2)}
+
+
+ Patient Paid:
+ -${superbill.patientPaid.toFixed(2)}
+
+
+ Balance Due:
+ ${superbill.balanceDue.toFixed(2)}
+
+
+
+
+
+ {/* Stripe Payment Modal */}
+ {showPaymentModal && (
+
+
+
+
+
+
+
+
+
Stripe Connect Checkout
+
Direct to {activeTenant.name}
+
+
+
+
+
+
+ Amount Due:
+
+ ${superbill.balanceDue.toFixed(2)}
+
+
+
+ {paymentSuccess ? (
+
+
+
Payment Processed Successfully!
+
+ Stripe Charge ID: ch_3P18f92Ksk921
+
+
+ ) : (
+ <>
+
+ Select Payment Method
+
+
+
handleStripePay('Stripe Card')}
+ className="p-3 bg-slate-800 hover:bg-slate-700 border border-slate-700 rounded-xl flex items-center justify-between transition"
+ >
+
+
+ Credit / Debit Card (Apple Pay)
+
+
+ Instant
+
+
+
+
handleStripePay('HSA/FSA')}
+ className="p-3 bg-slate-800 hover:bg-slate-700 border border-slate-700 rounded-xl flex items-center justify-between transition"
+ >
+
+
+ HSA / FSA Health Benefit Card
+
+
+ Tax-Free
+
+
+
+
handleStripePay('Cash')}
+ className="p-3 bg-slate-800 hover:bg-slate-700 border border-slate-700 rounded-xl flex items-center justify-between transition"
+ >
+
+
+ Cash / In-Person Check
+
+
+ No Fee
+
+
+
+ >
+ )}
+
+
+ {!paymentSuccess && (
+
+ setShowPaymentModal(false)}
+ className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-slate-300 text-xs font-semibold rounded-xl transition"
+ >
+ Close
+
+
+ )}
+
+
+ )}
+
+ );
+};
diff --git a/src/components/calendar/CalendarView.tsx b/src/components/calendar/CalendarView.tsx
new file mode 100644
index 0000000..251525a
--- /dev/null
+++ b/src/components/calendar/CalendarView.tsx
@@ -0,0 +1,237 @@
+'use client';
+
+import React, { useState } from 'react';
+import { Appointment, ClinicTenant, Provider } from '@/types/clinical';
+import {
+ Calendar as CalendarIcon,
+ Clock,
+ User,
+ Plus,
+ CheckCircle,
+ AlertCircle,
+ PlayCircle,
+ XCircle,
+ ChevronLeft,
+ ChevronRight,
+ Filter,
+} from 'lucide-react';
+
+interface CalendarViewProps {
+ appointments: Appointment[];
+ providers: Provider[];
+ activeTenant: ClinicTenant;
+ onSelectAppointment: (apt: Appointment) => void;
+ onUpdateStatus: (aptId: string, status: Appointment['status']) => void;
+ onNewAppointmentClick: () => void;
+}
+
+export const CalendarView: React.FC = ({
+ appointments,
+ providers,
+ activeTenant,
+ onSelectAppointment,
+ onUpdateStatus,
+ onNewAppointmentClick,
+}) => {
+ const [selectedProviderId, setSelectedProviderId] = useState('all');
+ const [activeDateStr, setActiveDateStr] = useState('2026-09-05');
+
+ const filteredAppointments = appointments.filter(
+ (a) => selectedProviderId === 'all' || a.providerId === selectedProviderId
+ );
+
+ const getStatusBadge = (status: Appointment['status']) => {
+ switch (status) {
+ case 'completed':
+ return (
+
+ Completed
+
+ );
+ case 'in_room':
+ return (
+
+ In Operatory
+
+ );
+ case 'arrived':
+ return (
+
+ Arrived / Waiting
+
+ );
+ case 'confirmed':
+ return (
+
+ Confirmed
+
+ );
+ case 'booked':
+ return (
+
+ Booked
+
+ );
+ case 'no_show':
+ return (
+
+ No Show
+
+ );
+ }
+ };
+
+ return (
+
+ {/* Action Header */}
+
+
+
+
+
+
+
+ Saturday, September 5, 2026
+
+
+
+
+
+
+ {/* Provider Filter */}
+
+ setSelectedProviderId('all')}
+ className={`px-3 py-1 rounded-lg font-medium transition ${
+ selectedProviderId === 'all'
+ ? 'bg-teal-500 text-slate-950 font-bold shadow'
+ : 'text-slate-400 hover:text-white'
+ }`}
+ >
+ All Providers
+
+ {providers.map((p) => (
+ setSelectedProviderId(p.id)}
+ className={`px-3 py-1 rounded-lg font-medium transition ${
+ selectedProviderId === p.id
+ ? 'bg-teal-500 text-slate-950 font-bold shadow'
+ : 'text-slate-400 hover:text-white'
+ }`}
+ >
+ {p.name}
+
+ ))}
+
+
+
+
+
+ Book New Patient
+
+
+
+ {/* Grid of Appointments */}
+
+ {filteredAppointments.map((apt) => (
+
+
+ {/* Top Row: Time & Status */}
+
+
+
+
+ {apt.time}
+
+
+ {apt.durationMinutes} min
+
+
+ {getStatusBadge(apt.status)}
+
+
+ {/* Patient & Service Details */}
+
+
+ {apt.patientName}
+
+
+ {apt.serviceType}
+
+
+ Provider: {apt.providerName}
+ •
+ {apt.room}
+
+
+ {apt.notes && (
+
+ "{apt.notes}"
+
+ )}
+
+
+
+ {/* Action Bar */}
+
+
onSelectAppointment(apt)}
+ className="px-3 py-1.5 rounded-lg bg-teal-500/10 hover:bg-teal-500/20 text-teal-300 text-xs font-semibold border border-teal-500/30 transition flex items-center gap-1.5"
+ >
+
+ Open SOAP Chart
+
+
+
+ {apt.status === 'booked' && (
+ onUpdateStatus(apt.id, 'arrived')}
+ className="px-2.5 py-1 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 text-[11px] font-medium"
+ >
+ Check In
+
+ )}
+ {apt.status === 'arrived' && (
+ onUpdateStatus(apt.id, 'in_room')}
+ className="px-2.5 py-1 rounded-lg bg-amber-500/20 hover:bg-amber-500/30 text-amber-300 text-[11px] font-medium border border-amber-500/30"
+ >
+ Move to Table
+
+ )}
+ {apt.status === 'in_room' && (
+ onUpdateStatus(apt.id, 'completed')}
+ className="px-2.5 py-1 rounded-lg bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-300 text-[11px] font-medium border border-emerald-500/30"
+ >
+ Mark Done
+
+ )}
+
+
+
+ ))}
+
+
+ );
+};
diff --git a/src/components/charting/SoapChartEditor.tsx b/src/components/charting/SoapChartEditor.tsx
new file mode 100644
index 0000000..1b39d78
--- /dev/null
+++ b/src/components/charting/SoapChartEditor.tsx
@@ -0,0 +1,478 @@
+'use client';
+
+import React, { useState } from 'react';
+import { SoapNote, Patient, Provider, SpinalAdjustmentEntry, CptCodeItem, Icd10CodeItem } from '@/types/clinical';
+import { SpineVisualizer } from '@/components/ui/SpineVisualizer';
+import { AmbientAudioRecorder } from '@/components/ui/AmbientAudioRecorder';
+import { STANDARD_CPT_CODES, STANDARD_ICD10_CODES } from '@/lib/mock-data';
+import {
+ FileText,
+ Sparkles,
+ CheckCircle,
+ Copy,
+ PenTool,
+ Save,
+ DollarSign,
+ ChevronLeft,
+ Tag,
+ ShieldCheck,
+ AlertCircle,
+} from 'lucide-react';
+
+interface SoapChartEditorProps {
+ patient: Patient;
+ provider: Provider;
+ initialSoapNote?: SoapNote;
+ onSaveSoapNote: (note: SoapNote) => void;
+ onGenerateSuperbill: (note: SoapNote) => void;
+ onBackToCalendar: () => void;
+}
+
+export const SoapChartEditor: React.FC = ({
+ patient,
+ provider,
+ initialSoapNote,
+ onSaveSoapNote,
+ onGenerateSuperbill,
+ onBackToCalendar,
+}) => {
+ const [subjective, setSubjective] = useState(
+ initialSoapNote?.subjective ||
+ `Patient presents for scheduled visit ${patient.carePlan.completedVisits + 1} of ${
+ patient.carePlan.totalVisits
+ }. Chief complaint: ${patient.chiefComplaint}. VAS pain reported at 4/10.`
+ );
+ const [objective, setObjective] = useState(
+ initialSoapNote?.objective ||
+ 'Postural examination reveals mild anterior head carriage and unleveling of right iliac crest. Motion palpation identifies segmental hypomobility with paraspinal guarding.'
+ );
+ const [assessment, setAssessment] = useState(
+ initialSoapNote?.assessment ||
+ 'Segmental and somatic dysfunction of lumbar and cervical spine. Patient progressing steadily toward functional goals outlined in care plan.'
+ );
+ const [plan, setPlan] = useState(
+ initialSoapNote?.plan ||
+ '1. High velocity low amplitude (HVLA) manipulative therapy delivered to listed subluxations.\n2. Prescribed postural home stabilization exercises.\n3. Return in 3 days for scheduled care plan visit.'
+ );
+ const [adjustments, setAdjustments] = useState(
+ initialSoapNote?.spinalAdjustments || [
+ { vertebra: 'L4', region: 'Lumbar', listing: 'Right Posterior (RP)', technique: 'Diversified' },
+ { vertebra: 'Sacrum', region: 'Pelvis/Sacrum', listing: 'Right Sacral Base Anterior', technique: 'Thompson Drop' },
+ ]
+ );
+ const [selectedIcd10, setSelectedIcd10] = useState(
+ initialSoapNote?.icd10Codes || [STANDARD_ICD10_CODES[2], STANDARD_ICD10_CODES[5]] // M99.03 & M54.50
+ );
+ const [selectedCpt, setSelectedCpt] = useState(
+ initialSoapNote?.cptCodes || [STANDARD_CPT_CODES[0], STANDARD_CPT_CODES[3]] // 98940 & 97140
+ );
+ const [vasScore, setVasScore] = useState(initialSoapNote?.vasScore || 3);
+ const [isSigned, setIsSigned] = useState(initialSoapNote?.status === 'signed');
+ const [signedTimestamp, setSignedTimestamp] = useState(initialSoapNote?.signedAt);
+
+ // Ambient AI Scribe callback
+ const handleApplyExtractedSoap = (data: {
+ vasScore: number;
+ subjective: string;
+ objective: string;
+ assessment: string;
+ plan: string;
+ spinalAdjustments: SpinalAdjustmentEntry[];
+ icd10: string[];
+ cpt: string[];
+ }) => {
+ setVasScore(data.vasScore);
+ setSubjective(data.subjective);
+ setObjective(data.objective);
+ setAssessment(data.assessment);
+ setPlan(data.plan);
+
+ if (data.spinalAdjustments && data.spinalAdjustments.length > 0) {
+ setAdjustments(data.spinalAdjustments);
+ }
+
+ // Auto map ICD10
+ const matchedIcds = STANDARD_ICD10_CODES.filter((icd) => data.icd10.includes(icd.code));
+ if (matchedIcds.length > 0) setSelectedIcd10(matchedIcds);
+
+ // Auto map CPT
+ const matchedCpts = STANDARD_CPT_CODES.filter((cpt) => data.cpt.includes(cpt.code));
+ if (matchedCpts.length > 0) setSelectedCpt(matchedCpts);
+ };
+
+ const handleToggleAdjustment = (entry: SpinalAdjustmentEntry) => {
+ setAdjustments((prev) => {
+ const exists = prev.some((a) => a.vertebra === entry.vertebra);
+ if (exists) {
+ return prev.filter((a) => a.vertebra !== entry.vertebra);
+ } else {
+ return [...prev, entry];
+ }
+ });
+ };
+
+ const handleCloneLastNote = () => {
+ 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.');
+ setPlan('1. Diversified adjustment delivered to indicated segments.\n2. Manual myofascial release 10 minutes.\n3. Continue active home rehabilitation.');
+ };
+
+ const handleSignChart = () => {
+ const now = new Date().toISOString();
+ setIsSigned(true);
+ setSignedTimestamp(now);
+
+ const savedNote: SoapNote = {
+ id: initialSoapNote?.id || `soap-${Date.now()}`,
+ tenantId: patient.tenantId,
+ patientId: patient.id,
+ patientName: `${patient.firstName} ${patient.lastName}`,
+ providerId: provider.id,
+ providerName: provider.name,
+ date: '2026-09-05',
+ status: 'signed',
+ vasScore,
+ subjective,
+ objective,
+ assessment,
+ plan,
+ spinalAdjustments: adjustments,
+ icd10Codes: selectedIcd10,
+ cptCodes: selectedCpt,
+ signedAt: now,
+ signedBy: `${provider.name}, ${provider.credentials} (NPI ${provider.npi})`,
+ };
+
+ onSaveSoapNote(savedNote);
+ };
+
+ const handleCreateSuperbillClick = () => {
+ const savedNote: SoapNote = {
+ id: initialSoapNote?.id || `soap-${Date.now()}`,
+ tenantId: patient.tenantId,
+ patientId: patient.id,
+ patientName: `${patient.firstName} ${patient.lastName}`,
+ providerId: provider.id,
+ providerName: provider.name,
+ date: '2026-09-05',
+ status: isSigned ? 'signed' : 'draft',
+ vasScore,
+ subjective,
+ objective,
+ assessment,
+ plan,
+ spinalAdjustments: adjustments,
+ icd10Codes: selectedIcd10,
+ cptCodes: selectedCpt,
+ signedAt: signedTimestamp,
+ signedBy: `${provider.name}, ${provider.credentials}`,
+ };
+
+ onGenerateSuperbill(savedNote);
+ };
+
+ return (
+
+ {/* Top Breadcrumb & Patient Header */}
+
+
+
+
+
+
+
+
+
+ {patient.firstName} {patient.lastName}
+
+
+ Care Plan: Visit {patient.carePlan.completedVisits + 1} of {patient.carePlan.totalVisits}
+
+ {isSigned ? (
+
+ Signed & Locked
+
+ ) : (
+
+ In Progress (Draft)
+
+ )}
+
+
+
+ DOB: {patient.dob}
+ •
+ Insurance: {patient.insuranceName}
+ •
+ Attending: {provider.name}
+
+
+
+
+ {/* Action buttons */}
+
+
+
+ Clone Last Note
+
+
+
+
+ {isSigned ? 'Signed by Doctor' : 'Sign & Complete Note'}
+
+
+
+
+ Generate Superbill
+
+
+
+
+ {/* Ambient AI Clinical Scribe Section */}
+
+
+ {/* 2D Spine Visualizer Subluxation Clicker */}
+
+
+ {/* Structured SOAP Fields Grid */}
+
+ {/* Subjective */}
+
+
+
+
+
+ S
+
+ Subjective Complaint & History
+
+ VAS: {vasScore}/10
+
+
+
+ Auto-populated from Intake and Ambient Scribe.
+
+
+
+ {/* Objective */}
+
+
+
+
+
+ O
+
+ Objective Findings & Palpation
+
+
+ {adjustments.length} Segment(s) Listed
+
+
+
+
+ Vertebrae selected in 2D Spine Map sync automatically.
+
+
+
+ {/* Assessment */}
+
+
+
+
+
+ A
+
+ Clinical Assessment & Progress
+
+
+
+
+ Maps to ICD-10 diagnostic codes below.
+
+
+
+ {/* Plan */}
+
+
+
+
+
+ P
+
+ Treatment Plan & Home Care
+
+
+
+
+ Determines CPT procedure line items on Superbill.
+
+
+
+
+ {/* ICD-10 & CPT Billing Code Selectors */}
+
+ {/* ICD-10 Codes */}
+
+
+
+
+ ICD-10 Diagnostic Codes
+
+ {selectedIcd10.length} Selected
+
+
+ {STANDARD_ICD10_CODES.map((item) => {
+ const active = selectedIcd10.some((c) => c.code === item.code);
+ return (
+ {
+ if (active) {
+ setSelectedIcd10((prev) => prev.filter((c) => c.code !== item.code));
+ } else {
+ setSelectedIcd10((prev) => [...prev, item]);
+ }
+ }}
+ className={`px-2.5 py-1.5 rounded-lg text-xs font-medium text-left transition ${
+ active
+ ? 'bg-teal-500 text-slate-950 font-bold shadow-sm'
+ : 'bg-slate-800 text-slate-300 hover:bg-slate-700'
+ }`}
+ >
+ {item.code}
+ {item.description}
+
+ );
+ })}
+
+
+
+ {/* CPT Codes */}
+
+
+
+
+ CPT Procedure Codes & Fee Schedule
+
+
+ Total: ${selectedCpt.reduce((sum, c) => sum + c.fee, 0)}
+
+
+
+ {STANDARD_CPT_CODES.map((item) => {
+ const active = selectedCpt.some((c) => c.code === item.code);
+ return (
+
{
+ if (active) {
+ setSelectedCpt((prev) => prev.filter((c) => c.code !== item.code));
+ } else {
+ setSelectedCpt((prev) => [...prev, item]);
+ }
+ }}
+ className={`px-2.5 py-1.5 rounded-lg text-xs font-medium text-left transition flex items-center justify-between gap-2 ${
+ active
+ ? 'bg-indigo-600 text-white font-bold shadow-sm'
+ : 'bg-slate-800 text-slate-300 hover:bg-slate-700'
+ }`}
+ >
+
+ {item.code}
+ {item.description}
+
+ ${item.fee}
+
+ );
+ })}
+
+
+
+
+ {/* Signature Attestation Footer */}
+ {isSigned && (
+
+
+
+
+
Electronically Signed by: {provider.name}, {provider.credentials} (NPI {provider.npi})
+
+ Timestamp: {signedTimestamp || '2026-09-05T09:25:00-07:00'} • Immutable Legal Record
+
+
+
+
+ Open Superbill
+
+
+ )}
+
+ );
+};
diff --git a/src/components/intake/PatientPortalView.tsx b/src/components/intake/PatientPortalView.tsx
new file mode 100644
index 0000000..2a0f43f
--- /dev/null
+++ b/src/components/intake/PatientPortalView.tsx
@@ -0,0 +1,410 @@
+'use client';
+
+import React, { useState } from 'react';
+import { ClinicTenant, Provider } from '@/types/clinical';
+import { BodyPainMap } from '@/components/ui/BodyPainMap';
+import { DigitalSignaturePad } from '@/components/ui/DigitalSignaturePad';
+import {
+ Calendar,
+ Clock,
+ User,
+ CheckCircle2,
+ Sparkles,
+ MapPin,
+ Phone,
+ ArrowRight,
+ ShieldCheck,
+} from 'lucide-react';
+
+interface PatientPortalViewProps {
+ activeTenant: ClinicTenant;
+ providers: Provider[];
+ onBookingComplete: (newAppointmentData: any) => void;
+}
+
+export const PatientPortalView: React.FC = ({
+ activeTenant,
+ providers,
+ onBookingComplete,
+}) => {
+ const [step, setStep] = useState<'service' | 'intake' | 'confirmed'>('service');
+
+ // Booking selections
+ const [selectedProvider, setSelectedProvider] = useState(providers[0]);
+ const [selectedService, setSelectedService] = useState('Initial Chiropractic Exam & Adjustment');
+ const [selectedDate, setSelectedDate] = useState('2026-09-08');
+ const [selectedTime, setSelectedTime] = useState('10:30 AM');
+
+ // Intake form state
+ const [fullName, setFullName] = useState('Jessica Morales');
+ const [dob, setDob] = useState('1991-08-14');
+ const [phone, setPhone] = useState('(555) 302-9912');
+ const [email, setEmail] = useState('jess.morales@example.com');
+ const [selectedPainAreas, setSelectedPainAreas] = useState([
+ 'Cervical Spine (Neck)',
+ 'Left Trapezius / Shoulder',
+ ]);
+ const [vasScore, setVasScore] = useState(6);
+ const [painNatures, setPainNatures] = useState([
+ 'Sharp / Stabbing',
+ 'Tingling / Pins & Needles',
+ ]);
+ const [signature, setSignature] = useState('');
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ const handleToggleArea = (area: string) => {
+ setSelectedPainAreas((prev) =>
+ prev.includes(area) ? prev.filter((a) => a !== area) : [...prev, area]
+ );
+ };
+
+ const handleToggleNature = (nature: string) => {
+ setPainNatures((prev) =>
+ prev.includes(nature) ? prev.filter((n) => n !== nature) : [...prev, nature]
+ );
+ };
+
+ const handleSubmitIntake = (e: React.FormEvent) => {
+ e.preventDefault();
+ setIsSubmitting(true);
+ setTimeout(() => {
+ setIsSubmitting(false);
+ setStep('confirmed');
+ onBookingComplete({
+ patientName: fullName,
+ patientPhone: phone,
+ providerId: selectedProvider.id,
+ providerName: selectedProvider.name,
+ date: selectedDate,
+ time: selectedTime,
+ serviceType: selectedService,
+ status: 'booked',
+ room: 'Table 1',
+ fee: 145,
+ notes: `Intake complete. Chief complaint: Neck/Shoulder pain (VAS ${vasScore}/10).`,
+ });
+ }, 1200);
+ };
+
+ return (
+
+ {/* Branded Clinic Header (100% White-Label) */}
+
+
+
+
+
+ {activeTenant.logoText}
+
+
+
{activeTenant.name}
+
+
+
+ {activeTenant.address}, {activeTenant.cityStateZip}
+
+
+
+ {activeTenant.phone}
+
+
+
+
+
+
+ White-Label Patient Portal
+
+
+
+ {/* Wizard Progress Steps */}
+
+
+ 1. Select Service & Time
+
+
→
+
+ 2. Paperless Intake & Pain Map
+
+
→
+
+ 3. Confirmed
+
+
+
+ {/* Step 1: Select Service & Doctor */}
+ {step === 'service' && (
+
+
+
Choose Your Chiropractic Provider
+
+ Select a doctor licensed in state-of-the-art spinal biomechanics and gentle adjustment techniques.
+
+
+
+ {providers.map((p) => {
+ const isChosen = selectedProvider.id === p.id;
+ return (
+
setSelectedProvider(p)}
+ className={`flex items-center gap-3 p-4 rounded-xl border text-left transition ${
+ isChosen
+ ? 'bg-slate-800 border-teal-500/80 text-white shadow-lg'
+ : 'bg-slate-950/60 border-slate-800 text-slate-300 hover:bg-slate-800/40'
+ }`}
+ >
+
+ {p.name
+ .split(' ')
+ .map((n) => n[0])
+ .join('')}
+
+
+
{p.name}
+
{p.title}
+
{p.specialty}
+
+
+ );
+ })}
+
+
+
+
+
Select Appointment Type
+
+ {[
+ { name: 'Initial Chiropractic Exam & Adjustment', dur: '45 mins', fee: '$145' },
+ { name: 'Follow-Up Spinal CMT & Decompression', dur: '20 mins', fee: '$75' },
+ { name: 'Triton Computerized Disc Decompression', dur: '30 mins', fee: '$95' },
+ ].map((svc) => (
+
setSelectedService(svc.name)}
+ className={`p-4 rounded-xl border text-left transition flex flex-col justify-between ${
+ selectedService === svc.name
+ ? 'bg-teal-500/10 border-teal-500/80 text-white shadow'
+ : 'bg-slate-950/60 border-slate-800 text-slate-400 hover:bg-slate-800/40'
+ }`}
+ >
+
+
{svc.name}
+
{svc.dur}
+
+ {svc.fee}
+
+ ))}
+
+
+
+
+
Pick Date & Available Slot
+
+ {['09:00 AM', '10:30 AM', '01:15 PM', '03:45 PM'].map((t) => (
+ setSelectedTime(t)}
+ className={`p-3 rounded-xl border text-center font-bold transition font-mono ${
+ selectedTime === t
+ ? 'bg-teal-500 text-slate-950 shadow-md shadow-teal-500/20'
+ : 'bg-slate-950/60 border-slate-800 text-slate-300 hover:bg-slate-800'
+ }`}
+ >
+
+ {t}
+
+ ))}
+
+
+
+
+
setStep('intake')}
+ className="px-6 py-3 rounded-xl bg-teal-500 hover:bg-teal-400 text-slate-950 text-xs font-bold flex items-center gap-2 shadow-lg shadow-teal-500/20 transition"
+ >
+ Continue to Digital Intake
+
+
+
+
+ )}
+
+ {/* Step 2: Paperless Intake & Body Pain Map */}
+ {step === 'intake' && (
+
+ )}
+
+ {/* Step 3: Confirmed Screen */}
+ {step === 'confirmed' && (
+
+
+
+
+
+
You're All Set, {fullName}!
+
+ Your appointment has been confirmed with {selectedProvider.name} at{' '}
+ {activeTenant.name} .
+
+
+
+
+ Date & Time:
+
+ {selectedDate} at {selectedTime}
+
+
+
+ Service:
+ {selectedService}
+
+
+ Paperless Intake:
+ Completed & Signed
+
+
+
+
+ A confirmation SMS with calendar link and operatory directions has been sent to{' '}
+ {phone} .
+
+
+
setStep('service')}
+ className="mt-4 px-4 py-2 bg-slate-800 hover:bg-slate-700 text-slate-300 text-xs font-semibold rounded-xl transition"
+ >
+ Book Another Patient
+
+
+ )}
+
+ );
+};
diff --git a/src/components/retention/RetentionView.tsx b/src/components/retention/RetentionView.tsx
new file mode 100644
index 0000000..1a926ca
--- /dev/null
+++ b/src/components/retention/RetentionView.tsx
@@ -0,0 +1,346 @@
+'use client';
+
+import React, { useState } from 'react';
+import { Patient, ClinicTenant } from '@/types/clinical';
+import {
+ Users,
+ AlertTriangle,
+ MessageSquare,
+ TrendingUp,
+ CheckCircle,
+ Clock,
+ Sparkles,
+ PhoneCall,
+ Calendar,
+ Send,
+ X,
+} from 'lucide-react';
+
+interface RetentionViewProps {
+ patients: Patient[];
+ activeTenant: ClinicTenant;
+ onSelectPatientChart: (patient: Patient) => void;
+}
+
+export const RetentionView: React.FC = ({
+ patients,
+ activeTenant,
+ onSelectPatientChart,
+}) => {
+ const [selectedPatientForSms, setSelectedPatientForSms] = useState(null);
+ const [customSmsMessage, setCustomSmsMessage] = useState('');
+ const [isSendingSms, setIsSendingSms] = useState(false);
+ const [sentToast, setSentToast] = useState(false);
+ const [filterType, setFilterType] = useState<'all' | 'dropout_risk' | 'active'>('dropout_risk');
+
+ const dropoutPatients = patients.filter((p) => p.status === 'dropout_risk');
+ const activePatients = patients.filter((p) => p.status === 'active');
+
+ const displayedPatients =
+ filterType === 'dropout_risk'
+ ? dropoutPatients
+ : filterType === 'active'
+ ? activePatients
+ : patients;
+
+ const handleOpenSmsModal = (patient: Patient) => {
+ setSelectedPatientForSms(patient);
+ setCustomSmsMessage(
+ `Hi ${patient.firstName}! Dr. Vance noticed you're due for visit ${
+ patient.carePlan.completedVisits + 1
+ } of your ${patient.carePlan.title}. We want to make sure your progress stays on track! Click here to pick a quick 15-min adjustment slot this week: https://${
+ activeTenant.domain
+ }/book?ref=careplan`
+ );
+ };
+
+ const handleSendSms = () => {
+ setIsSendingSms(true);
+ setTimeout(() => {
+ setIsSendingSms(false);
+ setSentToast(true);
+ if (selectedPatientForSms) {
+ selectedPatientForSms.status = 'reactivated';
+ }
+ setTimeout(() => {
+ setSentToast(false);
+ setSelectedPatientForSms(null);
+ }, 1500);
+ }, 1000);
+ };
+
+ return (
+
+ {/* Top Value Metric Cards */}
+
+
+
+ Care Plan Retention
+
+
+
84.2%
+
+ +18% higher than Jane App
+
+
+
+
+
+
Patients at Dropout Risk
+
+
+
+ {dropoutPatients.length} Patients
+
+
Missed expected cadence > 10 days
+
+
+
+
+ Revenue at Risk
+ $
+
+
$2,140.00
+
Unbilled care plan visits
+
+
+
+
+ Recovered This Month
+
+
+
+$3,850.00
+
Via AI Autonomous SMS
+
+
+
+ {/* Main Table / Patient List Header */}
+
+
+
+
+
+ Care Plan Adherence & Reactivation Radar
+
+
+ Identifies patients who have dropped off their prescribed spinal treatment plans before completing their clinical goals.
+
+
+
+
+ setFilterType('dropout_risk')}
+ className={`px-3 py-1 rounded-lg font-medium transition ${
+ filterType === 'dropout_risk'
+ ? 'bg-amber-500 text-slate-950 font-bold shadow'
+ : 'text-slate-400 hover:text-white'
+ }`}
+ >
+ Dropout Risk ({dropoutPatients.length})
+
+ setFilterType('active')}
+ className={`px-3 py-1 rounded-lg font-medium transition ${
+ filterType === 'active'
+ ? 'bg-teal-500 text-slate-950 font-bold shadow'
+ : 'text-slate-400 hover:text-white'
+ }`}
+ >
+ On Track ({activePatients.length})
+
+ setFilterType('all')}
+ className={`px-3 py-1 rounded-lg font-medium transition ${
+ filterType === 'all'
+ ? 'bg-indigo-600 text-white font-bold shadow'
+ : 'text-slate-400 hover:text-white'
+ }`}
+ >
+ All Patients ({patients.length})
+
+
+
+
+ {/* Patient Rows */}
+
+ {displayedPatients.map((p) => {
+ const isAtRisk = p.status === 'dropout_risk';
+ const progressPct = Math.round(
+ (p.carePlan.completedVisits / p.carePlan.totalVisits) * 100
+ );
+
+ return (
+
+
+
+
+ {p.firstName} {p.lastName}
+
+ {isAtRisk ? (
+
+ {p.daysSinceLastVisit} Days Since Visit
+
+ ) : (
+
+ On Track
+
+ )}
+
+
+
+ Care Plan: {p.carePlan.title} ({p.carePlan.frequency})
+
+
+
+
+
+
+ {p.carePlan.completedVisits}/{p.carePlan.totalVisits}
+
+
+
+
Phone: {p.phone}
+
•
+
Last Visit: {p.lastVisitDate}
+
+
+
+ {/* Actions */}
+
+ onSelectPatientChart(p)}
+ className="px-3 py-1.5 bg-slate-800 hover:bg-slate-700 text-slate-200 text-xs font-semibold rounded-lg transition"
+ >
+ View Chart
+
+
+ handleOpenSmsModal(p)}
+ className={`px-3 py-1.5 text-xs font-bold rounded-lg flex items-center gap-1.5 transition ${
+ isAtRisk
+ ? 'bg-amber-500 hover:bg-amber-400 text-slate-950 shadow-lg shadow-amber-500/20'
+ : 'bg-teal-500/20 hover:bg-teal-500/30 text-teal-300 border border-teal-500/40'
+ }`}
+ >
+
+ {isAtRisk ? 'Send AI Reactivation SMS' : 'Message Patient'}
+
+
+
+ );
+ })}
+
+
+
+ {/* SMS Reactivation Modal */}
+ {selectedPatientForSms && (
+
+
+
+
+
+
+
+
+
+ Autonomous SMS Reactivation Dispatch
+
+
+ To: {selectedPatientForSms.firstName} {selectedPatientForSms.lastName} ({selectedPatientForSms.phone})
+
+
+
+
setSelectedPatientForSms(null)}
+ className="text-slate-400 hover:text-white p-1"
+ >
+
+
+
+
+
+
+
+ Sending Clinic Line: {' '}
+ {activeTenant.phone}
+
+
+ AI Pilots Gateway
+
+
+
+
+
+ Personalized 2-Way Message (Editable)
+
+
+
+ {sentToast && (
+
+
+ SMS Dispatched! Patient status updated to Reactivated.
+
+ )}
+
+
+
+
+ Auto-fills calendar slots when patient clicks.
+
+
+
+ setSelectedPatientForSms(null)}
+ className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-slate-300 text-xs font-semibold rounded-xl transition"
+ >
+ Cancel
+
+
+ {isSendingSms ? (
+ <>
+
+ Sending SMS...
+ >
+ ) : (
+ <>
+
+ Send Reactivation Text
+ >
+ )}
+
+
+
+
+
+ )}
+
+ );
+};
diff --git a/src/components/ui/AmbientAudioRecorder.tsx b/src/components/ui/AmbientAudioRecorder.tsx
new file mode 100644
index 0000000..d693cf6
--- /dev/null
+++ b/src/components/ui/AmbientAudioRecorder.tsx
@@ -0,0 +1,256 @@
+'use client';
+
+import React, { useState, useEffect } from 'react';
+import { Mic, MicOff, Sparkles, Volume2, Play, Pause, RotateCcw, CheckCircle2, AlertCircle } from 'lucide-react';
+import { SAMPLE_AUDIO_PRESETS } from '@/lib/mock-data';
+
+interface AmbientAudioRecorderProps {
+ onApplyExtractedSoap: (soapData: {
+ vasScore: number;
+ subjective: string;
+ objective: string;
+ assessment: string;
+ plan: string;
+ spinalAdjustments: Array<{ vertebra: string; region: any; listing: string; technique: any; notes?: string }>;
+ icd10: string[];
+ cpt: string[];
+ }) => void;
+}
+
+export const AmbientAudioRecorder: React.FC = ({
+ onApplyExtractedSoap,
+}) => {
+ const [isRecording, setIsRecording] = useState(false);
+ const [recordingSeconds, setRecordingSeconds] = useState(0);
+ const [selectedPreset, setSelectedPreset] = useState(SAMPLE_AUDIO_PRESETS[0]);
+ const [isProcessingAI, setIsProcessingAI] = useState(false);
+ const [liveTranscript, setLiveTranscript] = useState('');
+ const [showAppliedToast, setShowAppliedToast] = useState(false);
+
+ // Timer simulation
+ useEffect(() => {
+ let interval: any = null;
+ if (isRecording) {
+ interval = setInterval(() => {
+ setRecordingSeconds((prev) => prev + 1);
+ }, 1000);
+ } else {
+ clearInterval(interval);
+ }
+ return () => clearInterval(interval);
+ }, [isRecording]);
+
+ const toggleRecording = () => {
+ if (!isRecording) {
+ setIsRecording(true);
+ setRecordingSeconds(0);
+ setLiveTranscript('Listening to ambient doctor-patient dialogue in operatory...');
+ // Simulate live ambient audio transcription
+ setTimeout(() => {
+ setLiveTranscript(selectedPreset.audioTranscript);
+ }, 2500);
+ } else {
+ setIsRecording(false);
+ }
+ };
+
+ const handleSelectPreset = (preset: typeof SAMPLE_AUDIO_PRESETS[0]) => {
+ setSelectedPreset(preset);
+ if (!isRecording) {
+ setLiveTranscript(preset.audioTranscript);
+ }
+ };
+
+ const handleSynthesizeSoap = () => {
+ setIsProcessingAI(true);
+ setTimeout(() => {
+ setIsProcessingAI(false);
+ onApplyExtractedSoap({
+ vasScore: selectedPreset.extractedSOAP.vasScore,
+ subjective: selectedPreset.extractedSOAP.subjective,
+ objective: selectedPreset.extractedSOAP.objective,
+ assessment: selectedPreset.extractedSOAP.assessment,
+ plan: selectedPreset.extractedSOAP.plan,
+ spinalAdjustments: selectedPreset.extractedSOAP.spinalAdjustments as any,
+ icd10: selectedPreset.extractedSOAP.icd10,
+ cpt: selectedPreset.extractedSOAP.cpt,
+ });
+ setShowAppliedToast(true);
+ setTimeout(() => setShowAppliedToast(false), 4000);
+ }, 1200);
+ };
+
+ const formatTime = (secs: number) => {
+ const mins = Math.floor(secs / 60);
+ const remaining = secs % 60;
+ return `${mins.toString().padStart(2, '0')}:${remaining.toString().padStart(2, '0')}`;
+ };
+
+ return (
+
+ {/* Top Banner */}
+
+
+
+
+
+
+
+ Mediusa Ambient Clinical AI Scribe
+
+
+ Powered by gpt-5.4-mini Clinical Engine
+
+
+
+ Zero typing required. Scribe listens to ambient doctor-patient encounter and converts conversational dialogue into compliant SOAP + CPT/ICD-10 codes.
+
+
+
+ {/* Recording Status / Mic Button */}
+
+ {isRecording && (
+
+
+ LIVE {formatTime(recordingSeconds)}
+
+ )}
+
+
+ {isRecording ? (
+ <>
+
+ Stop Listening
+ >
+ ) : (
+ <>
+
+ Start Ambient Scribe
+ >
+ )}
+
+
+
+
+ {/* Waveform Graphic Animation */}
+
+
+
+
+ Operatory Ambient Stream
+
+
+ 44.1kHz • 24-bit • HIPAA Speech Encryption
+
+
+
+ {/* Dynamic Animated Bars */}
+
+ {[
+ 12, 28, 45, 18, 62, 85, 40, 92, 70, 30, 80, 65, 45, 90, 35, 75, 55, 20, 68, 88,
+ 42, 78, 52, 22, 60, 95, 38, 72, 58, 25, 48, 82, 32, 64, 44, 15,
+ ].map((height, i) => (
+
+ ))}
+
+
+
+ {/* Preset Encounter Selector & Live Transcript View */}
+
+ {/* Left 4 Cols: Presets */}
+
+
+ Clinical Encounter Presets (1-Click Demo)
+
+
+ {SAMPLE_AUDIO_PRESETS.map((preset) => (
+
handleSelectPreset(preset)}
+ className={`w-full text-left p-2.5 rounded-xl border transition text-xs ${
+ selectedPreset.id === preset.id
+ ? 'bg-slate-800 border-teal-500/60 text-white shadow-sm'
+ : 'bg-slate-900/60 border-slate-800 text-slate-400 hover:bg-slate-800/40 hover:text-slate-200'
+ }`}
+ >
+ {preset.title}
+ Encounter Duration: {preset.duration}
+
+ ))}
+
+
+
+ {isProcessingAI ? (
+ <>
+
+ AI Extracting SOAP...
+ >
+ ) : (
+ <>
+
+ Extract SOAP & Auto-Codes
+ >
+ )}
+
+
+
+ {/* Right 8 Cols: Dialogue Transcript */}
+
+
+
+ Encounter Dialogue Feed
+ Live Whisper Stream
+
+
+ {liveTranscript || selectedPreset.audioTranscript}
+
+
+
+
+
+
+ Auto-detects Subluxations, VAS score, CPT 98940, ICD-10 M99.0x
+
+ HIPAA BAA Compliant
+
+
+
+
+ {showAppliedToast && (
+
+
+
+
+ Success! Encounter conversation extracted into Subjective, Objective, Assessment, Plan, Spine segments, and Billing codes.
+
+
+
+ )}
+
+ );
+};
diff --git a/src/components/ui/BodyPainMap.tsx b/src/components/ui/BodyPainMap.tsx
new file mode 100644
index 0000000..39ea800
--- /dev/null
+++ b/src/components/ui/BodyPainMap.tsx
@@ -0,0 +1,182 @@
+'use client';
+
+import React from 'react';
+import { Activity, AlertCircle, Check } from 'lucide-react';
+
+interface BodyPainMapProps {
+ selectedAreas: string[];
+ onToggleArea: (area: string) => void;
+ vasScore: number;
+ onChangeVasScore: (score: number) => void;
+ painNatures: string[];
+ onTogglePainNature: (nature: string) => void;
+ readOnly?: boolean;
+}
+
+const BODY_ZONES = [
+ { id: 'Cervical Spine (Neck)', label: 'Neck / Cervical Spine', side: 'Posterior' },
+ { id: 'Left Trapezius / Shoulder', label: 'Left Shoulder / Trap', side: 'Posterior' },
+ { id: 'Right Trapezius / Shoulder', label: 'Right Shoulder / Trap', side: 'Posterior' },
+ { id: 'Thoracic (Mid-Back)', label: 'Mid-Back / Ribs', side: 'Posterior' },
+ { id: 'Lumbar Spine (Low Back)', label: 'Lower Back / Lumbar', side: 'Posterior' },
+ { id: 'Sacroiliac (SI Joint) / Pelvis', label: 'SI Joints / Pelvis', side: 'Posterior' },
+ { id: 'Right Glute / Sciatic Nerve', label: 'Right Glute & Sciatica', side: 'Posterior' },
+ { id: 'Left Glute / Sciatic Nerve', label: 'Left Glute & Sciatica', side: 'Posterior' },
+ { id: 'Head / Occipital', label: 'Head / Base of Skull (Headaches)', side: 'Posterior' },
+ { id: 'Bilateral Knees', label: 'Knees / Gait Imbalance', side: 'Anterior' },
+];
+
+const PAIN_NATURE_OPTIONS = [
+ 'Sharp / Stabbing',
+ 'Dull Chronic Ache',
+ 'Burning Heat',
+ 'Shooting / Radiating',
+ 'Tingling / Pins & Needles',
+ 'Numbness / Loss of Sensation',
+ 'Throbbing Tension',
+];
+
+export const BodyPainMap: React.FC = ({
+ selectedAreas,
+ onToggleArea,
+ vasScore,
+ onChangeVasScore,
+ painNatures,
+ onTogglePainNature,
+ readOnly = false,
+}) => {
+ return (
+
+
+
+
+
+ Interactive Pain & Symptom Locator
+
+
+ Tap the areas on your body where you experience pain, tension, or nerve radiation.
+
+
+
+ Areas Selected:
+
+ {selectedAreas.length}
+
+
+
+
+
+ {/* Pain Hotspots Grid (7 cols) */}
+
+
+ Select Pain Regions
+
+
+ {BODY_ZONES.map((zone) => {
+ const isSelected = selectedAreas.includes(zone.id);
+ return (
+
onToggleArea(zone.id)}
+ className={`flex items-center justify-between p-3 rounded-xl border text-left text-xs transition ${
+ isSelected
+ ? 'bg-teal-500/20 border-teal-500/60 text-teal-200 shadow-sm'
+ : 'bg-slate-800/60 border-slate-700/60 text-slate-300 hover:bg-slate-800'
+ }`}
+ >
+
+
{zone.label}
+
{zone.side} Chain
+
+ {isSelected ? (
+
+
+
+ ) : (
+
+ )}
+
+ );
+ })}
+
+
+
+ {/* VAS Pain Scale & Pain Nature (5 cols) */}
+
+
+ {/* Visual Analog Scale (VAS) Slider */}
+
+
+
+ Visual Analog Scale (VAS)
+
+ = 7
+ ? 'bg-red-500/20 text-red-400 border border-red-500/30'
+ : vasScore >= 4
+ ? 'bg-amber-500/20 text-amber-400 border border-amber-500/30'
+ : 'bg-teal-500/20 text-teal-400 border border-teal-500/30'
+ }`}
+ >
+ {vasScore} / 10
+
+
+
+
onChangeVasScore(parseInt(e.target.value))}
+ className="w-full h-2 bg-slate-700 rounded-lg appearance-none cursor-pointer accent-teal-500"
+ />
+
+
+ 0 (No Pain)
+ 5 (Moderate)
+ 10 (Severe)
+
+
+
+ {/* Pain Nature Checkboxes */}
+
+
+ Nature of Pain Sensation
+
+
+ {PAIN_NATURE_OPTIONS.map((nature) => {
+ const isChecked = painNatures.includes(nature);
+ return (
+ onTogglePainNature(nature)}
+ className={`px-2.5 py-1 rounded-lg text-xs font-medium transition ${
+ isChecked
+ ? 'bg-indigo-600 text-white font-semibold shadow-sm'
+ : 'bg-slate-800 text-slate-400 hover:bg-slate-700 hover:text-slate-200'
+ }`}
+ >
+ {nature}
+
+ );
+ })}
+
+
+
+
+
+
+
Maps directly into Provider SOAP & ICD-10 diagnostic codes.
+
+
+
+
+ );
+};
diff --git a/src/components/ui/DigitalSignaturePad.tsx b/src/components/ui/DigitalSignaturePad.tsx
new file mode 100644
index 0000000..04f8f16
--- /dev/null
+++ b/src/components/ui/DigitalSignaturePad.tsx
@@ -0,0 +1,122 @@
+'use client';
+
+import React, { useRef, useState, useEffect } from 'react';
+import { PenTool, RotateCcw, Check } from 'lucide-react';
+
+interface DigitalSignaturePadProps {
+ onSaveSignature: (signatureData: string) => void;
+ signerName: string;
+}
+
+export const DigitalSignaturePad: React.FC = ({
+ onSaveSignature,
+ signerName,
+}) => {
+ const canvasRef = useRef(null);
+ const [isDrawing, setIsDrawing] = useState(false);
+ const [hasDrawn, setHasDrawn] = useState(false);
+
+ useEffect(() => {
+ const canvas = canvasRef.current;
+ if (!canvas) return;
+ const ctx = canvas.getContext('2d');
+ if (!ctx) return;
+ ctx.strokeStyle = '#2dd4bf'; // Teal 400
+ ctx.lineWidth = 2.5;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+ }, []);
+
+ const startDrawing = (e: React.MouseEvent | React.TouchEvent) => {
+ const canvas = canvasRef.current;
+ if (!canvas) return;
+ const ctx = canvas.getContext('2d');
+ if (!ctx) return;
+
+ setIsDrawing(true);
+ setHasDrawn(true);
+
+ const rect = canvas.getBoundingClientRect();
+ const x = 'touches' in e ? e.touches[0].clientX - rect.left : e.clientX - rect.left;
+ const y = 'touches' in e ? e.touches[0].clientY - rect.top : e.clientY - rect.top;
+
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ };
+
+ const draw = (e: React.MouseEvent | React.TouchEvent) => {
+ if (!isDrawing) return;
+ const canvas = canvasRef.current;
+ if (!canvas) return;
+ const ctx = canvas.getContext('2d');
+ if (!ctx) return;
+
+ const rect = canvas.getBoundingClientRect();
+ const x = 'touches' in e ? e.touches[0].clientX - rect.left : e.clientX - rect.left;
+ const y = 'touches' in e ? e.touches[0].clientY - rect.top : e.clientY - rect.top;
+
+ ctx.lineTo(x, y);
+ ctx.stroke();
+ };
+
+ const stopDrawing = () => {
+ setIsDrawing(false);
+ const canvas = canvasRef.current;
+ if (canvas && hasDrawn) {
+ onSaveSignature(canvas.toDataURL('image/png'));
+ }
+ };
+
+ const clearCanvas = () => {
+ const canvas = canvasRef.current;
+ if (!canvas) return;
+ const ctx = canvas.getContext('2d');
+ if (!ctx) return;
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ setHasDrawn(false);
+ onSaveSignature('');
+ };
+
+ return (
+
+
+
+
+
Digital Signature Pad
+ {signerName &&
({signerName}) }
+
+ {hasDrawn && (
+
+
+ Clear
+
+ )}
+
+
+
+
+ {!hasDrawn && (
+
+ Sign with finger or mouse here (HIPAA Certified)
+
+ )}
+
+
+ );
+};
diff --git a/src/components/ui/SpineVisualizer.tsx b/src/components/ui/SpineVisualizer.tsx
new file mode 100644
index 0000000..8f23db1
--- /dev/null
+++ b/src/components/ui/SpineVisualizer.tsx
@@ -0,0 +1,457 @@
+'use client';
+
+import React, { useState } from 'react';
+import { SpinalAdjustmentEntry } from '@/types/clinical';
+import { Check, X, ShieldAlert, Zap, Sparkles, Activity } from 'lucide-react';
+
+interface SpineVisualizerProps {
+ adjustments: SpinalAdjustmentEntry[];
+ onToggleAdjustment: (entry: SpinalAdjustmentEntry) => void;
+ readOnly?: boolean;
+}
+
+interface VertebraDef {
+ id: string;
+ name: string;
+ shortName: string;
+ region: 'Cervical' | 'Thoracic' | 'Lumbar' | 'Pelvis/Sacrum';
+ commonSymptoms: string;
+}
+
+const VERTEBRAE_LIST: VertebraDef[] = [
+ // Cervical
+ { id: 'C1', name: 'Atlas (C1)', shortName: 'C1', region: 'Cervical', commonSymptoms: 'Headaches, migraines, dizziness, high BP' },
+ { id: 'C2', name: 'Axis (C2)', shortName: 'C2', region: 'Cervical', commonSymptoms: 'Sinus issues, ear pain, eye fatigue' },
+ { id: 'C3', name: 'C3 Vertebra', shortName: 'C3', region: 'Cervical', commonSymptoms: 'Facial neuralgia, tinnitus, neck stiffness' },
+ { id: 'C4', name: 'C4 Vertebra', shortName: 'C4', region: 'Cervical', commonSymptoms: 'Hay fever, hearing loss, diaphragm' },
+ { id: 'C5', name: 'C5 Vertebra', shortName: 'C5', region: 'Cervical', commonSymptoms: 'Vocal cords, hoarseness, shoulder pain' },
+ { id: 'C6', name: 'C6 Vertebra', shortName: 'C6', region: 'Cervical', commonSymptoms: 'Neck pain, upper arm pain, tonsillitis' },
+ { id: 'C7', name: 'C7 Vertebra', shortName: 'C7', region: 'Cervical', commonSymptoms: 'Bursitis, colds, thyroid conditions' },
+
+ // Thoracic
+ { id: 'T1', name: 'T1 Vertebra', shortName: 'T1', region: 'Thoracic', commonSymptoms: 'Arms, wrists & hands, asthma' },
+ { id: 'T2', name: 'T2 Vertebra', shortName: 'T2', region: 'Thoracic', commonSymptoms: 'Heart conditions, chest pain' },
+ { id: 'T3', name: 'T3 Vertebra', shortName: 'T3', region: 'Thoracic', commonSymptoms: 'Lungs, bronchial tubes, pleurisy' },
+ { id: 'T4', name: 'T4 Vertebra', shortName: 'T4', region: 'Thoracic', commonSymptoms: 'Gallbladder, jaundice, shingles' },
+ { id: 'T5', name: 'T5 Vertebra', shortName: 'T5', region: 'Thoracic', commonSymptoms: 'Liver, low BP, poor circulation' },
+ { id: 'T6', name: 'T6 Vertebra', shortName: 'T6', region: 'Thoracic', commonSymptoms: 'Stomach, heartburn, indigestion' },
+ { id: 'T7', name: 'T7 Vertebra', shortName: 'T7', region: 'Thoracic', commonSymptoms: 'Pancreas, ulcers, gastritis' },
+ { id: 'T8', name: 'T8 Vertebra', shortName: 'T8', region: 'Thoracic', commonSymptoms: 'Spleen, lowered immune resistance' },
+ { id: 'T9', name: 'T9 Vertebra', shortName: 'T9', region: 'Thoracic', commonSymptoms: 'Adrenal glands, hives, allergies' },
+ { id: 'T10', name: 'T10 Vertebra', shortName: 'T10', region: 'Thoracic', commonSymptoms: 'Kidneys, nephritis, chronic fatigue' },
+ { id: 'T11', name: 'T11 Vertebra', shortName: 'T11', region: 'Thoracic', commonSymptoms: 'Skin disorders, acne, eczema' },
+ { id: 'T12', name: 'T12 Vertebra', shortName: 'T12', region: 'Thoracic', commonSymptoms: 'Small intestines, rheumatisms, gas' },
+
+ // Lumbar
+ { id: 'L1', name: 'L1 Vertebra', shortName: 'L1', region: 'Lumbar', commonSymptoms: 'Large intestines, constipation, colitis' },
+ { id: 'L2', name: 'L2 Vertebra', shortName: 'L2', region: 'Lumbar', commonSymptoms: 'Appendix, cramps, varicose veins' },
+ { id: 'L3', name: 'L3 Vertebra', shortName: 'L3', region: 'Lumbar', commonSymptoms: 'Bladder, knee pain, menstrual cramps' },
+ { id: 'L4', name: 'L4 Vertebra', shortName: 'L4', region: 'Lumbar', commonSymptoms: 'Prostate, sciatica, lumbago, difficult urination' },
+ { id: 'L5', name: 'L5 Vertebra', shortName: 'L5', region: 'Lumbar', commonSymptoms: 'Poor circulation in legs, cold feet, weak ankles' },
+
+ // Pelvis / Sacrum
+ { id: 'Sacrum', name: 'Sacrum (S1-S5)', shortName: 'Sacrum', region: 'Pelvis/Sacrum', commonSymptoms: 'Sacroiliac pain, spinal curvatures, pelvic lean' },
+ { id: 'Left Ilium', name: 'Left Ilium (SI Joint)', shortName: 'L-SI', region: 'Pelvis/Sacrum', commonSymptoms: 'Left SI joint fixation, antalgic posture' },
+ { id: 'Right Ilium', name: 'Right Ilium (SI Joint)', shortName: 'R-SI', region: 'Pelvis/Sacrum', commonSymptoms: 'Right SI joint fixation, leg length disparity' },
+];
+
+const TECHNIQUES = [
+ 'Diversified',
+ 'Thompson Drop',
+ 'Activator',
+ 'Gonstead',
+ 'Webster',
+ 'Flexion-Distraction',
+] as const;
+
+const COMMON_LISTINGS = [
+ 'Posterior (P)',
+ 'Right Posterior (RP)',
+ 'Left Posterior (LP)',
+ 'Right Lateral (R)',
+ 'Left Lateral (L)',
+ 'Anterior (A)',
+ 'Rotation / Fixation',
+];
+
+export const SpineVisualizer: React.FC = ({
+ adjustments,
+ onToggleAdjustment,
+ readOnly = false,
+}) => {
+ const [selectedVertebra, setSelectedVertebra] = useState(null);
+ const [activeListing, setActiveListing] = useState('Right Posterior (RP)');
+ const [activeTechnique, setActiveTechnique] = useState('Diversified');
+ const [activeFilter, setActiveFilter] = useState<'All' | 'Cervical' | 'Thoracic' | 'Lumbar' | 'Pelvis/Sacrum'>('All');
+
+ const filteredVertebrae = VERTEBRAE_LIST.filter(
+ (v) => activeFilter === 'All' || v.region === activeFilter
+ );
+
+ const isAdjusted = (id: string) => adjustments.some((a) => a.vertebra === id);
+ const getAdjustment = (id: string) => adjustments.find((a) => a.vertebra === id);
+
+ const handleOpenModal = (v: VertebraDef) => {
+ if (readOnly) return;
+ const existing = getAdjustment(v.id);
+ if (existing) {
+ setActiveListing(existing.listing);
+ setActiveTechnique(existing.technique);
+ } else {
+ setActiveListing('Right Posterior (RP)');
+ setActiveTechnique(v.region === 'Cervical' ? 'Diversified' : v.region === 'Lumbar' ? 'Thompson Drop' : 'Diversified');
+ }
+ setSelectedVertebra(v);
+ };
+
+ const handleSaveListing = () => {
+ if (!selectedVertebra) return;
+ onToggleAdjustment({
+ vertebra: selectedVertebra.id,
+ region: selectedVertebra.region,
+ listing: activeListing,
+ technique: activeTechnique,
+ notes: `${activeTechnique} adjustment delivered to ${selectedVertebra.id}`,
+ });
+ setSelectedVertebra(null);
+ };
+
+ const handleRemoveListing = (vertebraId: string) => {
+ const existing = getAdjustment(vertebraId);
+ if (existing) {
+ onToggleAdjustment(existing);
+ }
+ setSelectedVertebra(null);
+ };
+
+ return (
+
+ {/* Header bar */}
+
+
+
+
+
+
+
+ Interactive 2D Spine Subluxation Visualizer
+
+
+ {adjustments.length} Listings Adjusted
+
+
+
+ Rapid click-to-chart anatomical interface. Tap any spinal segment to assign listing & technique in < 5 seconds.
+
+
+
+ {/* Region Filter Buttons */}
+
+ {(['All', 'Cervical', 'Thoracic', 'Lumbar', 'Pelvis/Sacrum'] as const).map((region) => (
+ setActiveFilter(region)}
+ className={`px-2.5 py-1 rounded-lg font-medium transition-all whitespace-nowrap ${
+ activeFilter === region
+ ? 'bg-teal-500 text-white shadow-sm'
+ : 'text-slate-400 hover:text-white hover:bg-slate-700/50'
+ }`}
+ >
+ {region}
+
+ ))}
+
+
+
+ {/* Main Spine Grid Layout */}
+
+ {/* Visual Column / Spine Segment Buttons (8 cols) */}
+
+
+ {filteredVertebrae.map((v) => {
+ const active = isAdjusted(v.id);
+ const adj = getAdjustment(v.id);
+
+ const regionColor =
+ v.region === 'Cervical'
+ ? 'border-indigo-500/40 hover:border-indigo-400'
+ : v.region === 'Thoracic'
+ ? 'border-blue-500/40 hover:border-blue-400'
+ : v.region === 'Lumbar'
+ ? 'border-teal-500/40 hover:border-teal-400'
+ : 'border-purple-500/40 hover:border-purple-400';
+
+ const activeBg =
+ v.region === 'Cervical'
+ ? 'bg-gradient-to-r from-indigo-950 to-slate-900 border-indigo-400 text-indigo-200'
+ : v.region === 'Thoracic'
+ ? 'bg-gradient-to-r from-blue-950 to-slate-900 border-blue-400 text-blue-200'
+ : v.region === 'Lumbar'
+ ? 'bg-gradient-to-r from-teal-950 to-slate-900 border-teal-400 text-teal-200'
+ : 'bg-gradient-to-r from-purple-950 to-slate-900 border-purple-400 text-purple-200';
+
+ return (
+
handleOpenModal(v)}
+ className={`relative flex items-center justify-between p-2.5 rounded-xl border text-left transition-all duration-150 group ${
+ active ? `${activeBg} shadow-lg shadow-teal-950/20` : `bg-slate-800/40 ${regionColor} text-slate-300 hover:bg-slate-800/80`
+ }`}
+ >
+
+
+ {v.shortName}
+
+
+
{v.name}
+
+ {active && adj ? `${adj.listing} • ${adj.technique}` : v.region}
+
+
+
+
+ {active ? (
+
+
+
+ ) : (
+
+ )}
+
+ );
+ })}
+
+
+
+ {/* Right Details Panel: Active Encounters & Clinical Notes (4 cols) */}
+
+
+
+
+ Visit Adjustment Summary
+
+
+ {adjustments.length} Segment(s)
+
+
+
+ {adjustments.length === 0 ? (
+
+
+
No vertebrae selected.
+
+ Click any vertebra on the left to add adjustment listing.
+
+
+ ) : (
+
+ {adjustments.map((item) => (
+
+
+
+ {item.vertebra}
+ ({item.region})
+
+
+ {item.listing}
+
+
+ Technique: {item.technique}
+
+
+
+ {!readOnly && (
+
handleRemoveListing(item.vertebra)}
+ className="text-slate-500 hover:text-red-400 p-1 transition-colors"
+ title="Remove adjustment"
+ >
+
+
+ )}
+
+ ))}
+
+ )}
+
+
+ {/* Quick Subluxation Preset Macros */}
+ {!readOnly && (
+
+
+ Chiropractic Quick Macros
+
+
+ {
+ onToggleAdjustment({
+ vertebra: 'C1',
+ region: 'Cervical',
+ listing: 'Right Lateral / Posterior',
+ technique: 'Diversified',
+ });
+ onToggleAdjustment({
+ vertebra: 'C5',
+ region: 'Cervical',
+ listing: 'Bilateral Facet Fixation',
+ technique: 'Diversified',
+ });
+ }}
+ className="px-2 py-1.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded text-[11px] font-medium transition text-left truncate"
+ >
+ + Cervical Protocol
+
+ {
+ onToggleAdjustment({
+ vertebra: 'L4',
+ region: 'Lumbar',
+ listing: 'Right Posterior (RP)',
+ technique: 'Diversified',
+ });
+ onToggleAdjustment({
+ vertebra: 'Sacrum',
+ region: 'Pelvis/Sacrum',
+ listing: 'Right Sacral Base Anterior',
+ technique: 'Thompson Drop',
+ });
+ }}
+ className="px-2 py-1.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded text-[11px] font-medium transition text-left truncate"
+ >
+ + L4/SI Protocol
+
+
+
+ )}
+
+
+
+ {/* Interactive Adjustment Modal / Drawer */}
+ {selectedVertebra && (
+
+
+
+
+
+ {selectedVertebra.shortName}
+
+
+
{selectedVertebra.name}
+
{selectedVertebra.region} Spine
+
+
+
setSelectedVertebra(null)}
+ className="text-slate-400 hover:text-white p-1"
+ >
+
+
+
+
+
+ {/* Common Clinical Symptoms Reference */}
+
+ Anatomical Correlate: {' '}
+ {selectedVertebra.commonSymptoms}
+
+
+ {/* Subluxation Listing Selector */}
+
+
+ Subluxation Listing / Motion Restriction
+
+
+ {COMMON_LISTINGS.map((listing) => (
+ setActiveListing(listing)}
+ className={`px-3 py-2 rounded-lg text-xs font-medium text-left transition ${
+ activeListing === listing
+ ? 'bg-teal-500 text-white font-semibold shadow-sm'
+ : 'bg-slate-800 text-slate-300 hover:bg-slate-700'
+ }`}
+ >
+ {listing}
+
+ ))}
+
+
+
+ {/* Technique Selector */}
+
+
+ Chiropractic Technique
+
+
+ {TECHNIQUES.map((tech) => (
+ setActiveTechnique(tech)}
+ className={`px-2 py-1.5 rounded-lg text-xs font-medium transition text-center ${
+ activeTechnique === tech
+ ? 'bg-indigo-600 text-white font-semibold shadow-sm'
+ : 'bg-slate-800 text-slate-300 hover:bg-slate-700'
+ }`}
+ >
+ {tech}
+
+ ))}
+
+
+
+
+ {/* Modal Actions */}
+
+ {isAdjusted(selectedVertebra.id) ? (
+
handleRemoveListing(selectedVertebra.id)}
+ className="px-3 py-2 rounded-xl text-xs font-semibold text-red-400 hover:bg-red-500/10 transition"
+ >
+ Clear Segment
+
+ ) : (
+
+ )}
+
+
+ setSelectedVertebra(null)}
+ className="px-4 py-2 rounded-xl text-xs font-semibold bg-slate-800 hover:bg-slate-700 text-slate-300 transition"
+ >
+ Cancel
+
+
+
+ Apply Listing
+
+
+
+
+
+ )}
+
+ );
+};
diff --git a/src/lib/mock-data.ts b/src/lib/mock-data.ts
new file mode 100644
index 0000000..ddb3725
--- /dev/null
+++ b/src/lib/mock-data.ts
@@ -0,0 +1,471 @@
+import { ClinicTenant, Provider, Patient, Appointment, SoapNote, Superbill, IntakeSubmission, CptCodeItem, Icd10CodeItem } from '@/types/clinical';
+
+export const STANDARD_CPT_CODES: CptCodeItem[] = [
+ { code: '98940', description: 'Chiropractic Manipulative Treatment (CMT); Spinal, 1-2 Regions', fee: 55 },
+ { code: '98941', description: 'Chiropractic Manipulative Treatment (CMT); Spinal, 3-4 Regions', fee: 75 },
+ { code: '98942', description: 'Chiropractic Manipulative Treatment (CMT); Spinal, 5 Regions', fee: 95 },
+ { code: '97140', description: 'Manual Therapy Techniques (Mobilization, Myofascial Release, 15 min)', fee: 45 },
+ { code: '97110', description: 'Therapeutic Exercises to Develop Strength/Endurance (15 min)', fee: 50 },
+ { code: '97014', description: 'Electrical Stimulation (Unattended)', fee: 25 },
+ { code: '99203', description: 'Office Visit; New Patient, Detailed Exam & Medical Decision', fee: 145 },
+];
+
+export const STANDARD_ICD10_CODES: Icd10CodeItem[] = [
+ { code: 'M99.01', description: 'Segmental and somatic dysfunction of cervical region' },
+ { code: 'M99.02', description: 'Segmental and somatic dysfunction of thoracic region' },
+ { code: 'M99.03', description: 'Segmental and somatic dysfunction of lumbar region' },
+ { code: 'M99.04', description: 'Segmental and somatic dysfunction of sacral region' },
+ { code: 'M99.05', description: 'Segmental and somatic dysfunction of pelvic region' },
+ { code: 'M54.50', description: 'Low back pain, unspecified' },
+ { code: 'M54.2', description: 'Cervicalgia (neck pain)' },
+ { code: 'M54.16', description: 'Radiculopathy, lumbar region (Sciatica)' },
+ { code: 'G44.209', description: 'Tension-type headache, unspecified' },
+];
+
+export const INITIAL_TENANTS: ClinicTenant[] = [
+ {
+ id: 'tenant-1',
+ name: 'Apex Spine & Wellness Clinic',
+ slug: 'apex-spine',
+ domain: 'apex.mediusa.app',
+ phone: '(555) 234-8901',
+ email: 'hello@apexspine.clinic',
+ address: '1420 Meridian Ave, Suite 300',
+ cityStateZip: 'San Jose, CA 95125',
+ npi: '1942857391',
+ taxId: '84-2918471',
+ logoText: 'APEX SPINE',
+ brandColor: '#0d9488', // Teal 600
+ accentColor: '#14b8a6',
+ plan: 'Pro Clinic',
+ mrr: 149,
+ stripeConnected: true,
+ createdAt: '2026-01-15',
+ },
+ {
+ id: 'tenant-2',
+ name: 'Origins of Wellness Chiropractic',
+ slug: 'origins-wellness',
+ domain: 'origins.mediusa.app',
+ phone: '(555) 789-1234',
+ email: 'care@originsofwellness.com',
+ address: '880 Palmdale Blvd, Suite B',
+ cityStateZip: 'Palmdale, CA 93551',
+ npi: '1839201948',
+ taxId: '95-3029182',
+ logoText: 'ORIGINS',
+ brandColor: '#0284c7', // Sky 600
+ accentColor: '#38bdf8',
+ plan: 'Pro Clinic',
+ mrr: 149,
+ stripeConnected: true,
+ createdAt: '2026-02-01',
+ },
+ {
+ id: 'tenant-3',
+ name: 'Elevate Sports & Spine Rehab',
+ slug: 'elevate-rehab',
+ domain: 'elevate.mediusa.app',
+ phone: '(555) 441-9022',
+ email: 'team@elevatespine.com',
+ address: '420 Olympic Blvd',
+ cityStateZip: 'Los Angeles, CA 90015',
+ npi: '1720394812',
+ taxId: '93-4819203',
+ logoText: 'ELEVATE',
+ brandColor: '#6366f1', // Indigo 500
+ accentColor: '#818cf8',
+ plan: 'Multi-Doc Enterprise',
+ mrr: 199,
+ stripeConnected: true,
+ createdAt: '2026-02-18',
+ },
+];
+
+export const INITIAL_PROVIDERS: Provider[] = [
+ {
+ id: 'prov-1',
+ tenantId: 'tenant-1',
+ name: 'Dr. Marcus Vance',
+ title: 'Lead Chiropractor & Clinic Director',
+ credentials: 'D.C., CCSP, CSCS',
+ specialty: 'Sports Chiropractic & Spinal Biomechanics',
+ npi: '1942857391',
+ email: 'dr.vance@apexspine.clinic',
+ phone: '(555) 234-8902',
+ avatarUrl: 'https://images.unsplash.com/photo-1622253692010-333f2da6031d?w=150&auto=format&fit=crop&q=80',
+ color: '#0d9488',
+ },
+ {
+ id: 'prov-2',
+ tenantId: 'tenant-1',
+ name: 'Dr. Elena Rostova',
+ title: 'Associate Chiropractor',
+ credentials: 'D.C., Webster Certified',
+ specialty: 'Prenatal, Pediatric & Family Wellness',
+ npi: '1628491029',
+ email: 'dr.rostova@apexspine.clinic',
+ phone: '(555) 234-8903',
+ avatarUrl: 'https://images.unsplash.com/photo-1594824813571-638f026385a8?w=150&auto=format&fit=crop&q=80',
+ color: '#0284c7',
+ },
+];
+
+export const INITIAL_PATIENTS: Patient[] = [
+ {
+ id: 'pat-1',
+ tenantId: 'tenant-1',
+ firstName: 'Marcus',
+ lastName: 'Chen',
+ email: 'marcus.chen@example.com',
+ phone: '(555) 392-8172',
+ dob: '1988-04-14',
+ gender: 'Male',
+ address: '381 Willow Street, San Jose, CA',
+ insuranceName: 'Anthem Blue Cross PPO',
+ insuranceId: 'XED9381029',
+ chiefComplaint: 'Sharp lower back pain with right glute radiation after deadlifts',
+ lastVisitDate: '2026-09-02',
+ nextAppointmentDate: '2026-09-06',
+ daysSinceLastVisit: 3,
+ status: 'active',
+ carePlan: {
+ title: 'Lumbar Disc Decompression & Stabilization Protocol',
+ totalVisits: 12,
+ completedVisits: 6,
+ frequency: '2x / week for 6 weeks',
+ targetCondition: 'L4-L5 Disc Bulge with Sciatica',
+ startDate: '2026-08-10',
+ status: 'on_track',
+ },
+ },
+ {
+ id: 'pat-2',
+ tenantId: 'tenant-1',
+ firstName: 'Sarah',
+ lastName: 'Holloway',
+ email: 's.holloway@example.com',
+ phone: '(555) 819-3011',
+ dob: '1993-11-20',
+ gender: 'Female',
+ address: '924 Lincoln Ave, San Jose, CA',
+ insuranceName: 'Aetna Open Choice',
+ insuranceId: 'W192840192',
+ chiefComplaint: 'Cervicogenic headaches and upper trap burning from desk posture',
+ lastVisitDate: '2026-08-18',
+ nextAppointmentDate: undefined,
+ daysSinceLastVisit: 18,
+ status: 'dropout_risk',
+ carePlan: {
+ title: 'Cervical Postural Realignment & Headache Relief',
+ totalVisits: 8,
+ completedVisits: 3,
+ frequency: '1x / week for 8 weeks',
+ targetCondition: 'C1-C2 Subluxation & Upper Cross Syndrome',
+ startDate: '2026-07-28',
+ status: 'at_risk',
+ },
+ },
+ {
+ id: 'pat-3',
+ tenantId: 'tenant-1',
+ firstName: 'David',
+ lastName: 'Miller',
+ email: 'dmiller.tech@example.com',
+ phone: '(555) 442-9901',
+ dob: '1979-06-03',
+ gender: 'Male',
+ address: '110 Hamilton Ct, Campbell, CA',
+ insuranceName: 'UnitedHealthcare Choice Plus',
+ insuranceId: 'UH9920194',
+ chiefComplaint: 'Mid-back thoracic stiffness and restricted rotation on golf swing',
+ lastVisitDate: '2026-09-04',
+ nextAppointmentDate: '2026-09-11',
+ daysSinceLastVisit: 1,
+ status: 'active',
+ carePlan: {
+ title: 'Thoracic Mobility & Biomechanical Alignment',
+ totalVisits: 6,
+ completedVisits: 2,
+ frequency: '1x / week for 6 weeks',
+ targetCondition: 'T4-T8 Hypomobility',
+ startDate: '2026-08-25',
+ status: 'on_track',
+ },
+ },
+ {
+ id: 'pat-4',
+ tenantId: 'tenant-1',
+ firstName: 'Amanda',
+ lastName: 'Torres',
+ email: 'amanda.t@example.com',
+ phone: '(555) 902-1456',
+ dob: '1995-02-18',
+ gender: 'Female',
+ address: '542 Race St, San Jose, CA',
+ insuranceName: 'Cigna Open Access',
+ insuranceId: 'CG882910',
+ chiefComplaint: 'Pelvic asymmetry and SI joint catching during third trimester',
+ lastVisitDate: '2026-09-01',
+ nextAppointmentDate: '2026-09-08',
+ daysSinceLastVisit: 4,
+ status: 'active',
+ carePlan: {
+ title: 'Webster Technique Pelvic Balance & Comfort',
+ totalVisits: 10,
+ completedVisits: 5,
+ frequency: '1x / week until delivery',
+ targetCondition: 'Sacroiliac Dysfunction & Round Ligament Tension',
+ startDate: '2026-08-01',
+ status: 'on_track',
+ },
+ },
+ {
+ id: 'pat-5',
+ tenantId: 'tenant-1',
+ firstName: 'James',
+ lastName: 'Kowalski',
+ email: 'j.kowalski@example.com',
+ phone: '(555) 601-3329',
+ dob: '1965-09-12',
+ gender: 'Male',
+ address: '782 Minnesota Ave, San Jose, CA',
+ insuranceName: 'Medicare Part B',
+ insuranceId: '1EG4-TE8-MK99',
+ chiefComplaint: 'Chronic lumbar facet syndrome and bilateral morning stiffness',
+ lastVisitDate: '2026-08-12',
+ nextAppointmentDate: undefined,
+ daysSinceLastVisit: 24,
+ status: 'dropout_risk',
+ carePlan: {
+ title: 'Spinal Decompression & Maintenance Care',
+ totalVisits: 12,
+ completedVisits: 7,
+ frequency: 'Every 2 weeks',
+ targetCondition: 'Degenerative Disc Disease L3-S1',
+ startDate: '2026-06-15',
+ status: 'at_risk',
+ },
+ },
+];
+
+export const INITIAL_APPOINTMENTS: Appointment[] = [
+ {
+ id: 'apt-1',
+ tenantId: 'tenant-1',
+ patientId: 'pat-1',
+ patientName: 'Marcus Chen',
+ patientPhone: '(555) 392-8172',
+ providerId: 'prov-1',
+ providerName: 'Dr. Marcus Vance',
+ date: '2026-09-05',
+ time: '09:00 AM',
+ durationMinutes: 20,
+ serviceType: 'Spinal Adjustment & Decompression',
+ status: 'completed',
+ room: 'Table 1 (Zenith Hi-Lo)',
+ fee: 75,
+ notes: 'Patient reports VAS down to 3/10. Focus on L4-L5 flexion distraction.',
+ },
+ {
+ id: 'apt-2',
+ tenantId: 'tenant-1',
+ patientId: 'pat-3',
+ patientName: 'David Miller',
+ patientPhone: '(555) 442-9901',
+ providerId: 'prov-1',
+ providerName: 'Dr. Marcus Vance',
+ date: '2026-09-05',
+ time: '10:00 AM',
+ durationMinutes: 15,
+ serviceType: 'Subluxation Check & CMT',
+ status: 'in_room',
+ room: 'Table 2 (Drop Table)',
+ fee: 55,
+ notes: 'Check T6 anteriority and bilateral rib cage excursion.',
+ },
+ {
+ id: 'apt-3',
+ tenantId: 'tenant-1',
+ patientId: 'pat-4',
+ patientName: 'Amanda Torres',
+ patientPhone: '(555) 902-1456',
+ providerId: 'prov-2',
+ providerName: 'Dr. Elena Rostova',
+ date: '2026-09-05',
+ time: '11:15 AM',
+ durationMinutes: 30,
+ serviceType: 'Webster Technique & Sacral Adjustment',
+ status: 'arrived',
+ room: 'Suite 2 (Pregnancy Cushion)',
+ fee: 85,
+ notes: 'Check right sacral rotation and round ligament tone.',
+ },
+ {
+ id: 'apt-4',
+ tenantId: 'tenant-1',
+ patientId: 'pat-2',
+ patientName: 'Sarah Holloway',
+ patientPhone: '(555) 819-3011',
+ providerId: 'prov-1',
+ providerName: 'Dr. Marcus Vance',
+ date: '2026-09-05',
+ time: '02:00 PM',
+ durationMinutes: 20,
+ serviceType: 'Cervical Spinal Alignment',
+ status: 'confirmed',
+ room: 'Table 1',
+ fee: 75,
+ notes: 'Recheck C2 lateral slip and suboccipital tension.',
+ },
+ {
+ id: 'apt-5',
+ tenantId: 'tenant-1',
+ patientId: 'pat-5',
+ patientName: 'James Kowalski',
+ patientPhone: '(555) 601-3329',
+ providerId: 'prov-1',
+ providerName: 'Dr. Marcus Vance',
+ date: '2026-09-05',
+ time: '03:30 PM',
+ durationMinutes: 30,
+ serviceType: 'Triton Lumbar Decompression Therapy',
+ status: 'booked',
+ room: 'Decompression Suite',
+ fee: 95,
+ },
+];
+
+export const INITIAL_SOAP_NOTES: SoapNote[] = [
+ {
+ id: 'soap-1',
+ tenantId: 'tenant-1',
+ patientId: 'pat-1',
+ patientName: 'Marcus Chen',
+ providerId: 'prov-1',
+ providerName: 'Dr. Marcus Vance',
+ appointmentId: 'apt-1',
+ date: '2026-09-05',
+ status: 'signed',
+ vasScore: 3,
+ subjective: 'Patient reports noticeable reduction in morning stiffness. Sciatic sensation into right calf has resolved; occasional dull ache localized to right L5 facet upon prolonged sitting (> 45 min). Rated 3/10 today vs 7/10 at intake.',
+ objective: 'Inspection reveals reduced antalgic lean. Active Lumbar ROM: Flexion 75 deg (mild tightness), Extension 18 deg. Palpation demonstrates segmental fixation at L4-L5 and right sacral base anteriority. Paraspinal hypertonicity reduced in right quadratus lumborum.',
+ assessment: 'Patient showing favorable progression in care plan visit 6 of 12. Segmental somatic dysfunction of lumbar spine (M99.03) and pelvic region (M99.05) stabilizing under manual decompression.',
+ plan: '1. Diversified CMT delivered to L4 (Right Mamillary) and Right Sacral Base.\n2. Flexion-Distraction therapy L4-L5 at 12 lbs traction for 8 minutes.\n3. Prescribed Bird-Dog and McGill Big 3 core stabilization home exercises.\n4. Follow-up adjustment scheduled in 3 days.',
+ spinalAdjustments: [
+ { vertebra: 'L4', region: 'Lumbar', listing: 'Right Mamillary Posterior (RP)', technique: 'Diversified', notes: 'Audible cavitation, immediate release' },
+ { vertebra: 'L5', region: 'Lumbar', listing: 'L5 Flexion Restricted', technique: 'Flexion-Distraction', notes: '8 minutes gentle rhythmic traction' },
+ { vertebra: 'Sacrum', region: 'Pelvis/Sacrum', listing: 'Right Sacral Base Anterior', technique: 'Thompson Drop', notes: 'Double drop piece protocol' },
+ ],
+ icd10Codes: [
+ { code: 'M99.03', description: 'Segmental dysfunction of lumbar region' },
+ { code: 'M99.05', description: 'Segmental dysfunction of pelvic region' },
+ { code: 'M54.50', description: 'Low back pain, unspecified' },
+ ],
+ cptCodes: [
+ { code: '98940', description: 'Chiropractic Manipulative Treatment (CMT); Spinal, 1-2 Regions', fee: 55 },
+ { code: '97140', description: 'Manual Therapy Techniques (15 min)', fee: 45 },
+ ],
+ signedAt: '2026-09-05T09:25:00-07:00',
+ signedBy: 'Dr. Marcus Vance, D.C. (NPI 1942857391)',
+ },
+];
+
+export const INITIAL_SUPERBILLS: Superbill[] = [
+ {
+ id: 'sb-1',
+ tenantId: 'tenant-1',
+ invoiceNumber: 'SB-2026-0901',
+ patientId: 'pat-1',
+ patientName: 'Marcus Chen',
+ patientDob: '1988-04-14',
+ patientAddress: '381 Willow Street, San Jose, CA 95125',
+ providerName: 'Dr. Marcus Vance, D.C.',
+ providerNpi: '1942857391',
+ clinicName: 'Apex Spine & Wellness Clinic',
+ clinicAddress: '1420 Meridian Ave, Suite 300, San Jose, CA 95125',
+ clinicTaxId: '84-2918471',
+ dateOfService: '2026-09-05',
+ posCode: '11 (Office)',
+ icd10Codes: [
+ { code: 'M99.03', description: 'Segmental somatic dysfunction of lumbar region' },
+ { code: 'M99.05', description: 'Segmental somatic dysfunction of pelvic region' },
+ { code: 'M54.50', description: 'Low back pain, unspecified' },
+ ],
+ items: [
+ { cptCode: '98940', description: 'CMT Spinal, 1-2 Regions (Lumbar/Sacral)', units: 1, rate: 55, total: 55 },
+ { cptCode: '97140', description: 'Manual Therapy Techniques / Myofascial Release', units: 1, rate: 45, total: 45 },
+ ],
+ totalAmount: 100,
+ patientPaid: 100,
+ balanceDue: 0,
+ paymentMethod: 'Stripe Card',
+ generatedAt: '2026-09-05T09:30:00-07:00',
+ },
+];
+
+export const INITIAL_INTAKE_SUBMISSIONS: IntakeSubmission[] = [
+ {
+ id: 'intake-1',
+ tenantId: 'tenant-1',
+ patientName: 'Jessica Morales',
+ dob: '1991-08-14',
+ phone: '(555) 302-9912',
+ email: 'jess.morales@example.com',
+ chiefComplaints: ['Neck Pain', 'Shoulder Blade Tightness', 'Numbness in Left Fingers'],
+ painAreas: ['Cervical Spine', 'Left Trapezius', 'Left Medial Scapula'],
+ vasScore: 6,
+ painNature: ['Shooting Pain', 'Dull Ache', 'Tingling / Pins & Needles'],
+ symptomsOnset: '3 weeks ago following a motor vehicle rear-end collision',
+ medications: 'Ibuprofen 600mg PRN',
+ priorChiropractic: true,
+ signatureName: 'Jessica Morales',
+ submittedAt: '2026-09-05T11:45:00-07:00',
+ status: 'pending_review',
+ },
+];
+
+export const SAMPLE_AUDIO_PRESETS = [
+ {
+ id: 'acute-lumbar',
+ title: 'Encounter: Acute L4-L5 Disc & Sciatica Follow-Up',
+ duration: '1m 15s',
+ audioTranscript: `Dr. Vance: "Good morning Marcus. How did the lower back hold up since Wednesday's adjustment?"
+Marcus: "Hey Doc, morning stiffness is way down. The numbness down my right hamstring is pretty much gone. Still getting an ache right over that lower belt line if I sit for more than 40 minutes at work, maybe a 3 out of 10."
+Dr. Vance: "Great, let's take a look. Face down on the hi-lo table please. Palpating L4 and L5... definitely still feeling that right-sided fixation at L4 mamillary, and your right sacral base is shifted anterior about a quarter inch. Left SI is moving freely now. I'm going to set the drop piece for the sacrum... deep breath in, let it all the way out... [Drop release]. Perfect. Now on your left side facing me for L4 Diversified... nice clear cavitation there. We will run 8 minutes on the flexion distraction table to keep that disc hydrated. Keep up your bird-dogs at home, and let's see you Tuesday to keep your 12-visit stabilization on track."`,
+ extractedSOAP: {
+ vasScore: 3,
+ subjective: "Patient reports morning stiffness is significantly reduced. Radiation/numbness into right hamstring has resolved. Mild localized dull ache persists across the lower lumbar belt line after sitting > 40 minutes. VAS rated 3/10 (improved from initial 7/10).",
+ objective: "Physical exam reveals improved lumbar postural alignment. Motion palpation demonstrates persistent right-sided fixation at L4 mamillary process and right anterior sacral base subluxation. Left sacroiliac joint displays restored articulation.",
+ assessment: "Subacute L4-L5 disc injury and segmental dysfunction lumbar region (M99.03) with secondary pelvic dysfunction (M99.05). Demonstrating excellent compliance and functional milestone recovery on care plan visit 6/12.",
+ plan: "1. High-velocity low-amplitude (HVLA) Diversified adjustment to L4 in side posture.\n2. Thompson drop table adjustment to right sacral base.\n3. Flexion-distraction axial traction L4-L5 for 8 minutes.\n4. Continue home McGill Big 3 stabilization. Follow up in 3 days for next care plan visit.",
+ spinalAdjustments: [
+ { vertebra: 'L4', region: 'Lumbar', listing: 'RP (Right Posterior)', technique: 'Diversified', notes: 'Clear cavitation, restored rotation' },
+ { vertebra: 'Sacrum', region: 'Pelvis/Sacrum', listing: 'Right Base Anterior', technique: 'Thompson Drop', notes: 'Single drop release' },
+ ],
+ icd10: ['M99.03', 'M99.05', 'M54.50'],
+ cpt: ['98940', '97140'],
+ },
+ },
+ {
+ id: 'cervical-headache',
+ title: 'Encounter: Cervicogenic Headache & Atlas Subluxation',
+ duration: '0m 52s',
+ audioTranscript: `Dr. Elena: "Hi Sarah, how has your neck been feeling with the new ergonomic monitor setup?"
+Sarah: "Hi Dr. Elena! The sharp migraines are down, but I still get that heavy throbbing behind my right eye and burning at the base of my skull by 3 PM every day."
+Dr. Elena: "Let's check cervical motion. Rotation to the right is restricted at 55 degrees with suboccipital spasm. Motion palpation shows C1 Atlas right lateral and posterior listing, and C5-C6 bilateral facet restriction. Let's do gentle Atlas specific diversified adjustment on the right... gentle breath out... [click]. Excellent. Re-checking range of motion: right rotation cleared to 80 degrees smoothly. I'm going to apply 5 minutes of suboccipital release. Come back in 5 days."`,
+ extractedSOAP: {
+ vasScore: 4,
+ subjective: "Patient reports resolution of severe acute migraine episodes. Throbbing occipital pain radiating to right retro-orbital area persists toward late afternoon with desk work. Rated 4/10.",
+ objective: "Active cervical rotation to the right restricted to 55 degrees (normal 80) with palpable hypertonicity in right rectus capitis and obliquus capitis. Palpation reveals C1 Atlas Right Lateral/Posterior listing and C5-C6 facet imbrication.",
+ assessment: "Cervicogenic tension headache (G44.209) secondary to C1-C2 segmental subluxation (M99.01) and postural cervicalgia (M54.2).",
+ plan: "1. Specific diversified Atlas (C1) contact right lateral mass adjustment.\n2. C5-C6 bilateral cervical seated toggle recoil.\n3. Manual myofascial release to suboccipital triangle (5 mins).\n4. Follow-up appointment scheduled in 5 days.",
+ spinalAdjustments: [
+ { vertebra: 'C1', region: 'Cervical', listing: 'Atlas Right Lateral Posterior (ASR)', technique: 'Diversified', notes: 'Immediate cervical rotation clearance' },
+ { vertebra: 'C5', region: 'Cervical', listing: 'Bilateral Facet Fixation', technique: 'Activator', notes: 'Pressure 3 setting' },
+ ],
+ icd10: ['M99.01', 'M54.2', 'G44.209'],
+ cpt: ['98940', '97140'],
+ },
+ },
+];
diff --git a/src/lib/pdf-generator.ts b/src/lib/pdf-generator.ts
new file mode 100644
index 0000000..cb758bd
--- /dev/null
+++ b/src/lib/pdf-generator.ts
@@ -0,0 +1,178 @@
+import jsPDF from 'jspdf';
+import { Superbill } from '@/types/clinical';
+
+export function generateSuperbillPdf(superbill: Superbill) {
+ const doc = new jsPDF({
+ orientation: 'portrait',
+ unit: 'pt',
+ format: 'letter',
+ });
+
+ const margin = 40;
+ let y = margin;
+
+ // Header Banner
+ doc.setFillColor(15, 23, 42); // Slate 900
+ doc.rect(0, 0, doc.internal.pageSize.getWidth(), 80, 'F');
+
+ doc.setFont('helvetica', 'bold');
+ doc.setTextColor(255, 255, 255);
+ doc.setFontSize(20);
+ doc.text('MEDICAL SUPERBILL & STATEMENT', margin, 42);
+
+ doc.setFont('helvetica', 'normal');
+ doc.setFontSize(10);
+ doc.setTextColor(148, 163, 184); // Slate 400
+ doc.text('Comprehensive Out-of-Network Insurance Reimbursement Form', margin, 60);
+
+ doc.setTextColor(255, 255, 255);
+ doc.text(`Invoice #: ${superbill.invoiceNumber}`, doc.internal.pageSize.getWidth() - margin - 150, 42);
+ doc.text(`Date of Service: ${superbill.dateOfService}`, doc.internal.pageSize.getWidth() - margin - 150, 60);
+
+ y = 110;
+
+ // Two columns: Clinic (Billing Provider) & Patient Details
+ doc.setFont('helvetica', 'bold');
+ doc.setFontSize(11);
+ doc.setTextColor(15, 23, 42);
+ doc.text('BILLING PROVIDER & CLINIC', margin, y);
+ doc.text('PATIENT INFORMATION', 320, y);
+
+ doc.setDrawColor(226, 232, 240);
+ doc.line(margin, y + 6, 280, y + 6);
+ doc.line(320, y + 6, doc.internal.pageSize.getWidth() - margin, y + 6);
+
+ y += 22;
+ doc.setFont('helvetica', 'normal');
+ doc.setFontSize(9);
+ doc.setTextColor(51, 65, 85);
+
+ // Clinic Info
+ doc.text(superbill.clinicName, margin, y);
+ doc.text(superbill.clinicAddress, margin, y + 14);
+ doc.text(`Billing Provider: ${superbill.providerName}`, margin, y + 28);
+ doc.text(`Provider NPI: ${superbill.providerNpi} | Tax ID: ${superbill.clinicTaxId}`, margin, y + 42);
+ doc.text(`Place of Service (POS): ${superbill.posCode}`, margin, y + 56);
+
+ // Patient Info
+ doc.text(`Name: ${superbill.patientName}`, 320, y);
+ doc.text(`DOB: ${superbill.patientDob}`, 320, y + 14);
+ doc.text(`Address: ${superbill.patientAddress}`, 320, y + 28);
+ doc.text(`Payment Status: ${superbill.paymentMethod} (PAID IN FULL)`, 320, y + 42);
+
+ y += 85;
+
+ // Diagnosis (ICD-10) Section
+ doc.setFont('helvetica', 'bold');
+ doc.setFontSize(11);
+ doc.setTextColor(15, 23, 42);
+ doc.text('DIAGNOSIS CODES (ICD-10-CM)', margin, y);
+ doc.line(margin, y + 6, doc.internal.pageSize.getWidth() - margin, y + 6);
+
+ y += 20;
+ doc.setFont('helvetica', 'normal');
+ doc.setFontSize(9);
+ doc.setTextColor(51, 65, 85);
+
+ superbill.icd10Codes.forEach((icd, idx) => {
+ doc.setFont('helvetica', 'bold');
+ doc.text(`(${idx + 1}) ${icd.code}`, margin, y);
+ doc.setFont('helvetica', 'normal');
+ doc.text(` - ${icd.description}`, margin + 65, y);
+ y += 15;
+ });
+
+ y += 15;
+
+ // Procedure Line Items Table
+ doc.setFont('helvetica', 'bold');
+ doc.setFontSize(11);
+ doc.setTextColor(15, 23, 42);
+ doc.text('PROCEDURES & SERVICES (CPT CODES)', margin, y);
+ doc.line(margin, y + 6, doc.internal.pageSize.getWidth() - margin, y + 6);
+
+ y += 18;
+
+ // Table Header
+ doc.setFillColor(241, 245, 249);
+ doc.rect(margin, y, doc.internal.pageSize.getWidth() - (margin * 2), 22, 'F');
+ doc.setFont('helvetica', 'bold');
+ doc.setFontSize(9);
+ doc.setTextColor(71, 85, 105);
+ doc.text('CPT CODE', margin + 8, y + 15);
+ doc.text('DESCRIPTION', margin + 80, y + 15);
+ doc.text('UNITS', 400, y + 15);
+ doc.text('RATE', 450, y + 15);
+ doc.text('TOTAL', 505, y + 15);
+
+ y += 24;
+
+ doc.setFont('helvetica', 'normal');
+ doc.setFontSize(9);
+ doc.setTextColor(30, 41, 59);
+
+ superbill.items.forEach((item) => {
+ doc.text(item.cptCode, margin + 8, y + 14);
+ doc.text(item.description, margin + 80, y + 14);
+ doc.text(String(item.units), 405, y + 14);
+ doc.text(`$${item.rate.toFixed(2)}`, 450, y + 14);
+ doc.text(`$${item.total.toFixed(2)}`, 505, y + 14);
+
+ doc.setDrawColor(241, 245, 249);
+ doc.line(margin, y + 20, doc.internal.pageSize.getWidth() - margin, y + 20);
+ y += 22;
+ });
+
+ y += 20;
+
+ // Summary Totals Box
+ const summaryX = 350;
+ doc.setFillColor(248, 250, 252);
+ doc.rect(summaryX, y, doc.internal.pageSize.getWidth() - margin - summaryX, 70, 'F');
+ doc.rect(summaryX, y, doc.internal.pageSize.getWidth() - margin - summaryX, 70, 'S');
+
+ doc.setFont('helvetica', 'normal');
+ doc.text('Total Charges:', summaryX + 15, y + 20);
+ doc.text(`$${superbill.totalAmount.toFixed(2)}`, 505, y + 20);
+
+ doc.text('Patient Amount Paid:', summaryX + 15, y + 38);
+ doc.text(`$${superbill.patientPaid.toFixed(2)}`, 505, y + 38);
+
+ doc.setFont('helvetica', 'bold');
+ doc.text('Balance Due:', summaryX + 15, y + 56);
+ doc.text(`$${superbill.balanceDue.toFixed(2)}`, 505, y + 56);
+
+ y += 95;
+
+ // Practitioner Attestation & Signature
+ doc.setFont('helvetica', 'bold');
+ doc.setFontSize(9);
+ doc.setTextColor(15, 23, 42);
+ doc.text('PRACTITIONER ATTESTATION & SIGNATURE', margin, y);
+ doc.line(margin, y + 4, doc.internal.pageSize.getWidth() - margin, y + 4);
+
+ y += 16;
+ doc.setFont('helvetica', 'normal');
+ doc.setFontSize(8);
+ doc.setTextColor(100, 116, 139);
+ doc.text(
+ 'I certify that the services listed above were medically necessary and personally rendered by me or under my direct supervision on the date indicated.',
+ margin,
+ y
+ );
+
+ y += 25;
+ doc.setFont('helvetica', 'bold');
+ doc.setTextColor(15, 23, 42);
+ doc.text(`Electronically Signed by: ${superbill.providerName}`, margin, y);
+ doc.setFont('helvetica', 'normal');
+ doc.text(`Timestamp: ${superbill.generatedAt}`, margin, y + 12);
+ doc.text(`Verification ID: MED-${superbill.id.toUpperCase()}`, margin, y + 24);
+
+ // Footer Branding
+ doc.setFontSize(8);
+ doc.setTextColor(148, 163, 184);
+ doc.text('Generated via Mediusa Clinic OS • Clean Claim Direct Superbill Standard', margin, 760);
+
+ doc.save(`Superbill_${superbill.invoiceNumber}_${superbill.patientName.replace(/\s+/g, '_')}.pdf`);
+}
diff --git a/src/types/clinical.ts b/src/types/clinical.ts
new file mode 100644
index 0000000..2c77e9f
--- /dev/null
+++ b/src/types/clinical.ts
@@ -0,0 +1,175 @@
+export interface ClinicTenant {
+ id: string;
+ name: string;
+ slug: string;
+ domain: string;
+ phone: string;
+ email: string;
+ address: string;
+ cityStateZip: string;
+ npi: string;
+ taxId: string;
+ logoText: string;
+ brandColor: string;
+ accentColor: string;
+ plan: 'Starter' | 'Pro Clinic' | 'Multi-Doc Enterprise';
+ mrr: number;
+ stripeConnected: boolean;
+ createdAt: string;
+}
+
+export interface Provider {
+ id: string;
+ tenantId: string;
+ name: string;
+ title: string;
+ credentials: string; // e.g., "D.C., CCSP"
+ specialty: string;
+ npi: string;
+ email: string;
+ phone: string;
+ avatarUrl: string;
+ color: string;
+}
+
+export interface CarePlan {
+ title: string;
+ totalVisits: number;
+ completedVisits: number;
+ frequency: string; // e.g. "2x / week for 6 weeks"
+ targetCondition: string;
+ startDate: string;
+ status: 'on_track' | 'lagging' | 'at_risk' | 'completed';
+}
+
+export interface Patient {
+ id: string;
+ tenantId: string;
+ firstName: string;
+ lastName: string;
+ email: string;
+ phone: string;
+ dob: string;
+ gender: string;
+ address: string;
+ insuranceName: string;
+ insuranceId: string;
+ carePlan: CarePlan;
+ lastVisitDate: string;
+ nextAppointmentDate?: string;
+ status: 'active' | 'dropout_risk' | 'reactivated' | 'discharged';
+ chiefComplaint: string;
+ daysSinceLastVisit: number;
+}
+
+export type AppointmentStatus = 'booked' | 'confirmed' | 'arrived' | 'in_room' | 'completed' | 'no_show';
+
+export interface Appointment {
+ id: string;
+ tenantId: string;
+ patientId: string;
+ patientName: string;
+ patientPhone: string;
+ providerId: string;
+ providerName: string;
+ date: string; // YYYY-MM-DD
+ time: string; // HH:MM AM/PM
+ durationMinutes: number;
+ serviceType: string;
+ status: AppointmentStatus;
+ room: string;
+ notes?: string;
+ fee: number;
+}
+
+export interface SpinalAdjustmentEntry {
+ vertebra: string; // e.g. "C2", "L5"
+ region: 'Cervical' | 'Thoracic' | 'Lumbar' | 'Pelvis/Sacrum';
+ listing: string; // e.g., "Right Lateral / Posterior"
+ technique: 'Diversified' | 'Thompson Drop' | 'Activator' | 'Gonstead' | 'Webster' | 'Flexion-Distraction';
+ notes?: string;
+}
+
+export interface CptCodeItem {
+ code: string;
+ description: string;
+ fee: number;
+}
+
+export interface Icd10CodeItem {
+ code: string;
+ description: string;
+}
+
+export interface SoapNote {
+ id: string;
+ tenantId: string;
+ patientId: string;
+ patientName: string;
+ providerId: string;
+ providerName: string;
+ appointmentId?: string;
+ date: string;
+ status: 'draft' | 'signed';
+ subjective: string;
+ objective: string;
+ assessment: string;
+ plan: string;
+ spinalAdjustments: SpinalAdjustmentEntry[];
+ icd10Codes: Icd10CodeItem[];
+ cptCodes: CptCodeItem[];
+ vasScore: number; // 0-10
+ signedAt?: string;
+ signedBy?: string;
+}
+
+export interface SuperbillLineItem {
+ cptCode: string;
+ description: string;
+ units: number;
+ rate: number;
+ total: number;
+}
+
+export interface Superbill {
+ id: string;
+ tenantId: string;
+ invoiceNumber: string;
+ patientId: string;
+ patientName: string;
+ patientDob: string;
+ patientAddress: string;
+ providerName: string;
+ providerNpi: string;
+ clinicName: string;
+ clinicAddress: string;
+ clinicTaxId: string;
+ dateOfService: string;
+ posCode: string; // Place of Service "11 - Office"
+ icd10Codes: Icd10CodeItem[];
+ items: SuperbillLineItem[];
+ totalAmount: number;
+ patientPaid: number;
+ balanceDue: number;
+ paymentMethod: 'Stripe Card' | 'HSA/FSA' | 'Cash' | 'Unpaid';
+ generatedAt: string;
+}
+
+export interface IntakeSubmission {
+ id: string;
+ tenantId: string;
+ patientName: string;
+ dob: string;
+ phone: string;
+ email: string;
+ chiefComplaints: string[];
+ painAreas: string[];
+ vasScore: number;
+ painNature: string[]; // ['Sharp', 'Dull Ache', 'Shooting']
+ symptomsOnset: string;
+ medications: string;
+ priorChiropractic: boolean;
+ signatureName: string;
+ submittedAt: string;
+ status: 'pending_review' | 'imported_to_chart';
+}