Skip to content
1 change: 1 addition & 0 deletions docs/site-map.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -1017,6 +1017,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir
- `/mockups/caring-contacts/team` - Route discovered from app directory Source: `src/app/mockups/caring-contacts/team/page.tsx`.
- `/mockups/caring-contacts/templates` - Route discovered from app directory Source: `src/app/mockups/caring-contacts/templates/page.tsx`.
- `/mockups/caring-contacts/templates/[pathwayId]` - Route discovered from app directory Source: `src/app/mockups/caring-contacts/templates/[pathwayId]/page.tsx`.
- `/mockups/development` - Route discovered from app directory Source: `src/app/mockups/development/page.tsx`.
- `/mockups/document-navigation-contract` - Route discovered from app directory Source: `src/app/mockups/document-navigation-contract/page.tsx`.
- `/mockups/document-navigation-final` - Route discovered from app directory Source: `src/app/mockups/document-navigation-final/page.tsx`.
- `/mockups/document-navigation-final-review` - Route discovered from app directory Source: `src/app/mockups/document-navigation-final-review/page.tsx`.
Expand Down
98 changes: 98 additions & 0 deletions src/app/mockups/development/page.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
import type { Metadata } from "next";
import Link from "next/link";
import { ArrowRight, FlaskConical, ShieldAlert } from "lucide-react";

import { CARING_CONTACT_MOCKUP_ROUTES } from "@/components/caring-contacts/mockups/routes";

export const metadata: Metadata = {
title: "Development · Clinical KB",
description: "In-progress surfaces, off by default in a production deploy.",
};
Comment thread
BigSimmo marked this conversation as resolved.

// The index of what is being built. It lives under /mockups so it inherits the
// namespace's production gate (`mockupsEnabled()` in the mockups layout) rather
// than needing a second one: always on outside production, and 404 in a
// production deploy unless that deploy sets NEXT_PUBLIC_MOCKUPS_ENABLED=true —
// exactly like the surfaces it links to.
const DEVELOPMENT_SURFACES = [
{
id: "caring-contacts",
name: "Caring Contact",
summary:
"Linked prototype of the one-way caring-contacts coordination workflow: 13 routes, the activation flow, and the offline, permission, session-expiry, conflict and recovery states.",
href: CARING_CONTACT_MOCKUP_ROUTES.today,
status: "Synthetic prototype",
entries: [
{ label: "Today", href: CARING_CONTACT_MOCKUP_ROUTES.today },
{ label: "Patients", href: CARING_CONTACT_MOCKUP_ROUTES.patients },
{ label: "Schedule", href: CARING_CONTACT_MOCKUP_ROUTES.schedule },
{ label: "Templates", href: CARING_CONTACT_MOCKUP_ROUTES.templates },
{ label: "System states", href: CARING_CONTACT_MOCKUP_ROUTES.systemStates },
],
},
] as const;

export default function DevelopmentIndexPage() {
return (
<main className="mx-auto grid w-full max-w-[64rem] gap-6 px-4 py-8 sm:px-6" data-testid="development-index">
<header className="grid gap-2">
<p className="inline-flex items-center gap-2 text-xs font-extrabold uppercase tracking-wide text-[color:var(--clinical-accent)]">
<FlaskConical aria-hidden="true" className="size-icon-sm" />
Development
</p>
<h1 className="text-2xl font-extrabold text-[color:var(--text-heading)] sm:text-3xl">In-progress surfaces</h1>
<p className="max-w-3xl text-sm leading-6 text-[color:var(--text-muted)]">
Work being built, reachable from Settings while it is in development. These routes are not part of the
clinical product, and a production deploy 404s them unless it explicitly opts in.
</p>
</header>

<p className="flex items-start gap-2 rounded-xl border border-[color:var(--warning)]/30 bg-[color:var(--warning-soft)] px-4 py-3 text-sm leading-6 text-[color:var(--text)]">
<ShieldAlert aria-hidden="true" className="mt-0.5 size-icon-sm shrink-0 text-[color:var(--warning)]" />
<span>
<strong className="font-extrabold text-[color:var(--text-heading)]">Synthetic data only.</strong> No patient,
message, schedule or team record on these surfaces is real, and nothing here is validated clinical decision
support.
</span>
</p>

<ul className="grid gap-4">
{DEVELOPMENT_SURFACES.map((surface) => (
<li
key={surface.id}
className="grid gap-3 rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] p-5 shadow-[var(--shadow-inset)]"
>
<div className="flex flex-wrap items-center gap-x-3 gap-y-1">
<h2 className="text-lg font-extrabold text-[color:var(--text-heading)]">{surface.name}</h2>
<span className="rounded-full border border-[color:var(--border)] px-2 py-0.5 text-xs font-bold text-[color:var(--text-muted)]">
{surface.status}
</span>
</div>
<p className="max-w-3xl text-sm leading-6 text-[color:var(--text-muted)]">{surface.summary}</p>

<Link
href={surface.href}
className="inline-flex min-h-tap w-full items-center justify-center gap-2 rounded-lg bg-[color:var(--command)] px-4 text-sm font-extrabold text-[color:var(--command-contrast)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)] sm:w-auto"
data-testid={`development-open-${surface.id}`}
>
Open {surface.name} prototype
<ArrowRight aria-hidden="true" className="size-icon-sm" />
</Link>

<div className="flex flex-wrap gap-2 border-t border-[color:var(--border)] pt-3">
{surface.entries.map((entry) => (
<Link
key={entry.href}
href={entry.href}
className="inline-flex min-h-tap items-center rounded-lg border border-[color:var(--border)] px-3 text-xs font-bold text-[color:var(--text)] hover:bg-[color:var(--surface-subtle)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]"
>
{entry.label}
</Link>
))}
</div>
</li>
))}
</ul>
</main>
);
}
12 changes: 6 additions & 6 deletions src/components/clinical-dashboard/settings-dialog.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -1043,19 +1043,19 @@ export function SettingsDialog({
note="In-progress surfaces, reachable only in development builds. Not clinical content."
>
<div className="rounded-xl border border-[color:var(--border-lux)] bg-[color:var(--surface-lux)] p-4 shadow-[var(--e2),var(--shadow-inset)] lg:rounded-xl lg:bg-[color:var(--surface)] lg:shadow-[var(--shadow-inset)]">
<p className="text-sm font-semibold leading-5 text-[color:var(--text-heading)]">Caring Contact</p>
<p className="text-sm font-semibold leading-5 text-[color:var(--text-heading)]">Development page</p>
<p className="mt-1 text-sm font-medium leading-5 text-[color:var(--text-muted)]">
Linked prototype of the caring-contacts workflow. Synthetic data only — no patient record, message
or schedule here is real.
Index of the surfaces being built, including the Caring Contact prototype. Synthetic data only — no
patient record, message or schedule on them is real.
</p>
<Link
href="/mockups/caring-contacts"
href="/mockups/development"
onClick={onClose}
className={cn(floatingControl, "mt-3 min-h-10 w-full gap-2 text-sm")}
data-testid="settings-row-caring-contact-prototype"
data-testid="settings-row-development-page"
>
<FlaskConical aria-hidden="true" className="h-4 w-4" />
Open Caring Contact prototype
Open Development page
<span className="ml-auto text-xs font-semibold text-[color:var(--text-muted)]">Temporary</span>
</Link>
</div>
Expand Down
8 changes: 4 additions & 4 deletions tests/settings-dialog-actions.dom.test.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -101,16 +101,16 @@ describe("SettingsDialog — destructive and account actions", () => {
// built. It is gated to development builds, matching `mockupsEnabled()`, and the
// rail must not advertise a section the body does not render. The route is a
// mockup, so the entry navigates through <Link> and closes the sheet behind it.
it("opens the Caring Contact prototype from a gated Development section", () => {
it("opens the Development page from a gated Development section", () => {
renderDialog();
const development = document.querySelector('[data-settings-section="development"]');
expect(development).not.toBeNull();
expect(development).toHaveTextContent("Development");
expect(development).toHaveTextContent("Synthetic data only");

const prototypeLink = screen.getByTestId("settings-row-caring-contact-prototype");
expect(prototypeLink).toHaveAttribute("href", "/mockups/caring-contacts");
expect(prototypeLink).toHaveTextContent("Open Caring Contact prototype");
const prototypeLink = screen.getByTestId("settings-row-development-page");
expect(prototypeLink).toHaveAttribute("href", "/mockups/development");
expect(prototypeLink).toHaveTextContent("Open Development page");
expect(prototypeLink).toHaveTextContent("Temporary");
expect(development?.contains(prototypeLink)).toBe(true);

Expand Down
Loading