Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/app/differentials/diagnoses/[slug]/error.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
"use client";

import { useEffect } from "react";
import { AlertTriangle, RefreshCw } from "lucide-react";
import { primaryControl } from "@/components/ui-primitives";
import { cn } from "@/components/ui-primitives";

export default function ErrorBoundary({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
useEffect(() => {
console.error("Unhandled runtime error captured in differentials diagnoses segment:", error);
}, [error]);

return (
<div className="flex min-h-[50vh] flex-col items-center justify-center bg-[color:var(--surface-lux)] px-4 font-sans text-[color:var(--text)] select-none">
<div className="w-full max-w-md rounded-2xl border border-[color:var(--border)] bg-[color:var(--surface-raised)] p-6 shadow-[var(--shadow-elevated)] text-center">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-[color:var(--danger-soft)] text-[color:var(--danger)]">
<AlertTriangle className="h-6 w-6" />
</div>

<h1 className="mt-4 text-lg font-semibold tracking-tight text-[color:var(--text-heading)]">
Failed to load differential details
</h1>

<p className="mt-2 text-sm text-[color:var(--text-muted)] leading-relaxed">
An unexpected error occurred while fetching the differential diagnosis details.
</p>

{error.digest && (
<div className="mt-4 rounded-lg bg-[color:var(--surface-subtle)] p-2 text-xs font-mono text-[color:var(--text-muted)]">
Digest: {error.digest}
</div>
)}

<div className="mt-6 flex flex-col gap-2">
<button
type="button"
onClick={() => reset()}
className={cn(primaryControl, "flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium")}
>
<RefreshCw className="h-4 w-4" />
Try again
</button>
</div>
</div>
</div>
);
}
5 changes: 5 additions & 0 deletions src/app/differentials/diagnoses/[slug]/loading.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
import { ModeHomeRouteLoading } from "@/components/mode-home-page-skeleton";

export default function Loading() {
return <ModeHomeRouteLoading />;
}
47 changes: 47 additions & 0 deletions src/app/differentials/presentations/[slug]/error.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
"use client";

import { useEffect } from "react";
import { AlertTriangle, RefreshCw } from "lucide-react";
import { primaryControl } from "@/components/ui-primitives";
import { cn } from "@/components/ui-primitives";

export default function ErrorBoundary({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
useEffect(() => {
console.error("Unhandled runtime error captured in differentials presentations segment:", error);
}, [error]);

return (
<div className="flex min-h-[50vh] flex-col items-center justify-center bg-[color:var(--surface-lux)] px-4 font-sans text-[color:var(--text)] select-none">
<div className="w-full max-w-md rounded-2xl border border-[color:var(--border)] bg-[color:var(--surface-raised)] p-6 shadow-[var(--shadow-elevated)] text-center">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-[color:var(--danger-soft)] text-[color:var(--danger)]">
<AlertTriangle className="h-6 w-6" />
</div>

<h1 className="mt-4 text-lg font-semibold tracking-tight text-[color:var(--text-heading)]">
Failed to load presentation workflow
</h1>

<p className="mt-2 text-sm text-[color:var(--text-muted)] leading-relaxed">
An unexpected error occurred while fetching the differential presentation workflow details.
</p>

{error.digest && (
<div className="mt-4 rounded-lg bg-[color:var(--surface-subtle)] p-2 text-xs font-mono text-[color:var(--text-muted)]">
Digest: {error.digest}
</div>
)}

<div className="mt-6 flex flex-col gap-2">
<button
type="button"
onClick={() => reset()}
className={cn(primaryControl, "flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium")}
>
<RefreshCw className="h-4 w-4" />
Try again
</button>
</div>
</div>
</div>
);
}
5 changes: 5 additions & 0 deletions src/app/differentials/presentations/[slug]/loading.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
import { ModeHomeRouteLoading } from "@/components/mode-home-page-skeleton";

export default function Loading() {
return <ModeHomeRouteLoading />;
}
47 changes: 47 additions & 0 deletions src/app/medications/[slug]/error.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
"use client";

import { useEffect } from "react";
import { AlertTriangle, RefreshCw } from "lucide-react";
import { primaryControl } from "@/components/ui-primitives";
import { cn } from "@/components/ui-primitives";

export default function ErrorBoundary({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
useEffect(() => {
console.error("Unhandled runtime error captured in medications segment:", error);
}, [error]);

return (
<div className="flex min-h-[50vh] flex-col items-center justify-center bg-[color:var(--surface-lux)] px-4 font-sans text-[color:var(--text)] select-none">
<div className="w-full max-w-md rounded-2xl border border-[color:var(--border)] bg-[color:var(--surface-raised)] p-6 shadow-[var(--shadow-elevated)] text-center">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-[color:var(--danger-soft)] text-[color:var(--danger)]">
<AlertTriangle className="h-6 w-6" />
</div>

<h1 className="mt-4 text-lg font-semibold tracking-tight text-[color:var(--text-heading)]">
Failed to load medication details
</h1>

<p className="mt-2 text-sm text-[color:var(--text-muted)] leading-relaxed">
An unexpected error occurred while fetching the prescribing details.
</p>

{error.digest && (
<div className="mt-4 rounded-lg bg-[color:var(--surface-subtle)] p-2 text-xs font-mono text-[color:var(--text-muted)]">
Digest: {error.digest}
</div>
)}

<div className="mt-6 flex flex-col gap-2">
<button
type="button"
onClick={() => reset()}
className={cn(primaryControl, "flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium")}
>
<RefreshCw className="h-4 w-4" />
Try again
</button>
</div>
</div>
</div>
);
}
5 changes: 5 additions & 0 deletions src/app/medications/[slug]/loading.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
import { ModeHomeRouteLoading } from "@/components/mode-home-page-skeleton";

export default function Loading() {
return <ModeHomeRouteLoading />;
}
7 changes: 2 additions & 5 deletions src/components/ClinicalDashboard.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@
ChevronRight,
CircleUserRound,
Clock3,
Copy,

Check warning on line 15 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'Copy' is defined but never used

Check warning on line 15 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'Copy' is defined but never used
ExternalLink,
FileImage,
FileText,
Expand All@@ -29,7 +29,7 @@
LockKeyhole,
Palette,
PanelTop,
Plus,

Check warning on line 32 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'Plus' is defined but never used

Check warning on line 32 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'Plus' is defined but never used
Quote,
RefreshCw,
Search,
Expand All@@ -48,7 +48,7 @@
import {
type CSSProperties,
type FormEvent,
type RefObject,

Check warning on line 51 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'RefObject' is defined but never used

Check warning on line 51 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'RefObject' is defined but never used
useCallback,
useEffect,
useMemo,
Expand All@@ -57,12 +57,12 @@
} from "react";
import { AccessibleTable } from "@/components/AccessibleTable";
import {
DocumentOrganizationBadges,

Check warning on line 60 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'DocumentOrganizationBadges' is defined but never used

Check warning on line 60 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'DocumentOrganizationBadges' is defined but never used
documentDisplayTitle,

Check warning on line 61 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'documentDisplayTitle' is defined but never used

Check warning on line 61 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'documentDisplayTitle' is defined but never used
documentOrganizationProfile,

Check warning on line 62 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'documentOrganizationProfile' is defined but never used

Check warning on line 62 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'documentOrganizationProfile' is defined but never used
} from "@/components/DocumentOrganizationBadges";
import { DocumentTagCloud } from "@/components/DocumentTagCloud";

Check warning on line 64 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'DocumentTagCloud' is defined but never used

Check warning on line 64 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'DocumentTagCloud' is defined but never used
import { DocumentManagementActions, type DocumentDeleteResult } from "@/components/DocumentManagementActions";

Check warning on line 65 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'DocumentManagementActions' is defined but never used

Check warning on line 65 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'DocumentManagementActions' is defined but never used
import { useDismissableLayer } from "@/components/use-dismissable-layer";
import { formatCompactCitationLabel } from "@/lib/citations";
import { extractSafetyFindings } from "@/lib/clinical-safety";
Expand All@@ -75,13 +75,13 @@
clinicalDivider,
cn,
EmptyState,
fieldControlPlain,

Check warning on line 78 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'fieldControlPlain' is defined but never used

Check warning on line 78 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'fieldControlPlain' is defined but never used
fieldControlWithIcon,
fieldIcon,
floatingControl,
iconTilePremium,
metadataPill,
panelSubtle,

Check warning on line 84 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'panelSubtle' is defined but never used

Check warning on line 84 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions/ verify

'panelSubtle' is defined but never used
primaryControl,
SourceProvenance,
SourceStatusBadge,
Expand DownExpand Up@@ -2154,16 +2154,13 @@
useEffect(() => {
const previous = prevAuthStatusRef.current;
prevAuthStatusRef.current = authStatus;
if (
(authStatus === "signed_out" || authStatus === "expired") &&
(previous === "authenticated" || previous === "loading")
) {
if ((authStatus === "signed_out" || authStatus === "expired") && previous === "authenticated") {
resetAnswerThread();
setAnswer(null);
setSources([]);
latestAnswerTurnRef.current = null;
}
}, [authStatus]);
}, [authStatus, resetAnswerThread]);
const supabaseEnvStatus = setupChecks.find((check) => check.id === "env")?.status;
const browserAuthUnavailableDemoFallback = !auth.isConfigured && supabaseEnvStatus !== "ready";
const localNoAuthMode = isLocalNoAuthMode();
Expand Down
23 changes: 22 additions & 1 deletion tests/ui-smoke.spec.ts
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
import type { Route } from "playwright-core";
import { expect, test, type Locator, type Page } from "playwright/test";
import { answerThreadStorageKey } from "../src/lib/answer-thread-storage";
import { demoAnswer, demoDocuments, getDemoDocument, getDemoDocumentPayload } from "../src/lib/demo-data";
import { deriveGovernanceFromSections } from "../src/lib/medication-records";
import { getMedicationRecord, loadMedicationSnapshot } from "../src/lib/medication-snapshot";
Expand DownExpand Up@@ -551,6 +552,23 @@ async function waitForDemoDashboardReady(page: Page) {
await expect(page.getByRole("button", { name: "Open answer options" })).toBeVisible({ timeout: 30000 });
}

async function waitForPersistedAnswerThread(page: Page, minPriorTurns = 1) {
await expect
.poll(async () =>
page.evaluate((storageKey) => {
try {
const raw = window.localStorage.getItem(storageKey);
if (!raw) return 0;
const parsed = JSON.parse(raw) as { priorTurns?: unknown[] };
return Array.isArray(parsed.priorTurns) ? parsed.priorTurns.length : 0;
} catch {
return 0;
}
}, answerThreadStorageKey),
)
.toBeGreaterThanOrEqual(minPriorTurns);
}

async function openGuide(page: Page) {
const viewport = page.viewportSize();
const dialog = page.getByRole("dialog", { name: "Clinical KB guide" });
Expand DownExpand Up@@ -1243,9 +1261,12 @@ test.describe("Clinical KB UI smoke coverage", () => {
await expect(page).toHaveURL(/\?mode=answer&q=what\+about\+renal\+impairment\%3F&run=1/);
await expectNoPageHorizontalOverflow(page);

await waitForPersistedAnswerThread(page, 1);
await page.reload();
await waitForDemoDashboardReady(page);
await expect(page.getByTestId("user-question-bubble")).toHaveCount(2, { timeout: uiAssertionTimeoutMs });
await expect(async () => {
await expect(page.getByTestId("user-question-bubble")).toHaveCount(2);
}).toPass({ timeout: 15_000 });
await expect(page.getByTestId("user-question-bubble").first()).toContainText(firstQuestion);
await expect(page.getByTestId("user-question-bubble").nth(1)).toContainText(followUp);
await expect(page.locator('[data-dashboard-stage="answer-thread-turn"][data-collapsed="true"]')).toHaveCount(1);
Expand Down
9 changes: 7 additions & 2 deletions tests/ui-tools.spec.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,9 +97,12 @@ async function commandSurfaceOpensAbovePill(page: Page, hintPattern: RegExp) {
{ timeout: 10_000 },
);
await input.click();
await input.press("ArrowDown");
await expect(async () => {
await input.press("ArrowDown");
await expect(page.getByText(hintPattern)).toBeVisible();
await expect(page.getByRole("listbox").first()).toBeVisible();
}).toPass({ timeout: 15_000 });

await expect(page.getByText(hintPattern)).toBeVisible();
const listbox = page.getByRole("listbox").first();
await expect(listbox).toBeVisible();

Expand DownExpand Up@@ -407,6 +410,8 @@ test.describe("Clinical KB applications launcher", () => {
await page.setViewportSize({ width: 390, height: 820 });
await gotoLauncher(page, "/services?q=13YARN&focus=1&run=1");
await expect(page.getByRole("button", { name: "Mode Services" })).toBeVisible();
await expect(visibleGlobalSearchInput(page).first()).toBeVisible();
await page.waitForLoadState("networkidle", { timeout: 15_000 }).catch(() => undefined);
await commandSurfaceOpensAbovePill(page, /Searching services/i);
await expectNoPageHorizontalOverflow(page);
});
Expand Down