Add command palette, footer clinic menu, patient Sheet, Analysis page, favicon

Several navigation/UX additions:

- Command palette (⌘K): components/command-palette.tsx wraps the app shell
  (mounted in app/(app)/layout.tsx) with a controlled COSS CommandDialog listing
  the nav pages; a "Quick nav" Kbd button in the sidebar footer also opens it.
  Installed @coss/kbd. Extracted the nav list into lib/nav.ts so the sidebar and
  palette share one source of truth.
- Clinic switcher moved from the sidebar body into the footer; its menu now
  opens a read-only "Clinic info" dialog and a "Create clinic" dialog instead of
  routing to /onboarding. Shared CreateClinicForm (components/clinic/) is reused
  by onboarding.
- Patients: clicking a row opens a right-side Sheet with the full record
  (components/patients/patient-detail-sheet.tsx) instead of navigating to the
  chat; PatientResult gained a vertical "column" layout for the Sheet.
- New Analysis page (app/(app)/analysis/) — a mock dashboard (revenue/profit,
  patient volume, appointments, operations) reusing Sparkline + Card + Badge.
- Logo: set metadata.icons so the new mark appears as the browser-tab favicon.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalid Abdi
2026-06-04 19:40:11 +03:00
parent 2c5624e049
commit a4fc9a4fe9
15 changed files with 796 additions and 120 deletions
+12 -1
View File
@@ -35,6 +35,9 @@ type PatientResultProps = {
fileNumber: string;
patient?: Patient;
onPatientUpdated?: (patient: Patient) => void;
// "row" = horizontal scroll (chat); "column" = full-width vertical stack
// (the Patients detail Sheet).
layout?: "row" | "column";
};
const severityVariant: Record<AllergySeverity, BadgeVariant> = {
@@ -575,6 +578,7 @@ export function PatientResult({
fileNumber,
patient,
onPatientUpdated,
layout = "row",
}: PatientResultProps) {
const [editOpen, setEditOpen] = useState(false);
// Bumped on open so the editor remounts with the latest patient data.
@@ -593,7 +597,14 @@ export function PatientResult({
}
return (
<div className="no-scrollbar flex w-full items-stretch gap-4 overflow-x-auto p-2">
<div
className={cn(
"flex w-full gap-4 p-2",
layout === "column"
? "flex-col [&_[data-slot=card]]:w-full"
: "no-scrollbar items-stretch overflow-x-auto",
)}
>
{status === "loading" || !patient ? (
<LoadingCards />
) : (