From 26e933fb6c3644973ecd766c29952d7b46ceffb2 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 2 Jun 2026 22:29:30 +0300 Subject: [PATCH] Auth guard: auto-select an existing clinic instead of onboarding If a signed-in user has no active clinic but already belongs to one, select it automatically; only users with zero clinics are sent to onboarding. Fixes being asked to create a clinic on every login. Co-Authored-By: Claude Opus 4.8 --- frontend/components/auth/app-auth-guard.tsx | 36 +++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/frontend/components/auth/app-auth-guard.tsx b/frontend/components/auth/app-auth-guard.tsx index 987e73b..382b9ed 100644 --- a/frontend/components/auth/app-auth-guard.tsx +++ b/frontend/components/auth/app-auth-guard.tsx @@ -1,28 +1,46 @@ "use client"; import { useRouter } from "next/navigation"; -import { type ReactNode, useEffect } from "react"; +import { type ReactNode, useEffect, useRef } from "react"; import { authClient } from "@/lib/auth-client"; -// Authoritative client-side gate for the app shell: requires a session and an -// active clinic, otherwise redirects to login / onboarding. The API enforces -// the same rules server-side. +// Authoritative client-side gate for the app shell. Requires a session and an +// active clinic. If the user is signed in without an active clinic but already +// belongs to one, we select it automatically; onboarding is only for users +// with no clinics at all. The API enforces the same access rules server-side. export function AppAuthGuard({ children }: { children: ReactNode }) { const router = useRouter(); - const { data, isPending } = authClient.useSession(); + const { data: session, isPending } = authClient.useSession(); + const { data: orgs, isPending: orgsPending } = + authClient.useListOrganizations(); + const settingActive = useRef(false); - const ready = Boolean(data?.user && data.session?.activeOrganizationId); + const hasUser = Boolean(session?.user); + const activeOrgId = session?.session?.activeOrganizationId ?? null; useEffect(() => { if (isPending) return; - if (!data?.user) { + if (!hasUser) { router.replace("/login"); - } else if (!data.session?.activeOrganizationId) { + return; + } + if (activeOrgId) return; + + // Signed in but no active clinic selected yet. + if (orgsPending) return; + const first = orgs?.[0]; + if (first) { + if (!settingActive.current) { + settingActive.current = true; + void authClient.organization.setActive({ organizationId: first.id }); + } + } else { router.replace("/onboarding"); } - }, [data, isPending, router]); + }, [isPending, hasUser, activeOrgId, orgsPending, orgs, router]); + const ready = hasUser && Boolean(activeOrgId); if (!ready) { return (