frontend: make AI kill-switch a true clinic-wide master switch

The "Enable AI assistant" toggle already disabled the AI for everyone
(including owners/admins) at the policy layer, but the copy read as an
employee-only control and the Analysis surface stayed visible. Clarify
that the master switch covers admins too, and close the gaps: hide the
Analysis nav/command entry and redirect /analysis (alongside the chat
home) to /patients when AI is disabled. The employee-only toggle remains
the secondary option that keeps AI for owners/admins.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalid Abdi
2026-06-18 19:53:31 +03:00
parent 9a913147fb
commit 67cafdac3d
4 changed files with 20 additions and 9 deletions
+8 -3
View File
@@ -56,9 +56,14 @@ export function AppAuthGuard({ children }: { children: ReactNode }) {
router.replace(defaultLandingFor(role));
return;
}
// AI kill-switch: the chat home ("/") is off for this user — send them to
// patients (clinical roles always have it; non-clinical never land on "/").
if (!aiLoading && !aiAllowed && pathname === "/") {
// AI kill-switch: the AI surfaces — chat home ("/") and Analysis — are off
// for this user (a full clinic disable also covers owners/admins). Send them
// to patients (clinical roles always have it; non-clinical never land here).
if (
!aiLoading &&
!aiAllowed &&
(pathname === "/" || pathname === "/analysis")
) {
router.replace("/patients");
}
}, [ready, role, pathname, router, aiAllowed, aiLoading]);
+4 -1
View File
@@ -76,7 +76,10 @@ export function CommandPaletteProvider({ children }: { children: ReactNode }) {
// Filtered by role so reception can't jump to clinical pages, and by
// the AI kill-switch so the disabled chat isn't listed.
items: visibleNavItems(role)
.filter((item) => aiAllowed || item.id !== "new-chat")
.filter(
(item) =>
aiAllowed || (item.id !== "new-chat" && item.id !== "analysis"),
)
.flatMap((item) =>
item.subs?.length
? item.subs.map((sub) => ({
@@ -33,9 +33,12 @@ export function DashboardSidebar() {
const isCollapsed = state === "collapsed";
// Hide clinical nav from non-clinical roles (e.g. reception). See lib/roles.ts.
// Also drop the AI "New chat" entry when the clinic's AI kill-switch applies.
// Also drop the AI surfaces ("New chat" + "Analysis") when the clinic's AI
// kill-switch applies — a full disable hides them for owners/admins too.
const dashboardRoutes: Route[] = visibleNavItems(role)
.filter((item) => aiAllowed || item.id !== "new-chat")
.filter(
(item) => aiAllowed || (item.id !== "new-chat" && item.id !== "analysis"),
)
.map((item) => ({
id: item.id,
title: t(item.labelKey),
@@ -1479,11 +1479,11 @@
"ai": {
"availability": {
"title": "Availability",
"description": "Control who in your clinic can use the AI assistant. When disabled, the AI page and sidebar entry are hidden and the assistant cannot be reached.",
"description": "Control who in your clinic can use the AI assistant. When disabled, every AI surface — New chat, Analysis, and the chat history — is hidden and cannot be reached.",
"enabled": "Enable AI assistant",
"enabledHint": "Turn the AI assistant on for your clinic. Off hides it for everyone.",
"enabledHint": "Master switch. Turning this off disables and hides the AI for everyone in the clinic — including owners and admins.",
"employeesOnly": "Disable for employees only",
"employeesOnlyHint": "Hide the AI from staff; owners and admins keep access.",
"employeesOnlyHint": "Keep the AI for owners and admins, but hide it from all other staff.",
"savedTitle": "AI availability updated",
"savedBody": "The change applies across your clinic.",
"readonlyEnabled": "The AI assistant is enabled for your clinic.",