diff --git a/apps/web/src/portal/CustomerPortal.tsx b/apps/web/src/portal/CustomerPortal.tsx index 80d4e5b..aa877f2 100644 --- a/apps/web/src/portal/CustomerPortal.tsx +++ b/apps/web/src/portal/CustomerPortal.tsx @@ -1,5 +1,5 @@ import { useState, useCallback, useEffect, useRef } from "react"; -import { useSearchParams } from "react-router-dom"; +import { useSearchParams, Navigate } from "react-router-dom"; import { Home, Calendar, PawPrint, FileText, CreditCard, MessageSquare, Settings, LogOut, Shield, @@ -38,6 +38,7 @@ export function CustomerPortal() { const [session, setSession] = useState(null); const [sessionExtended, setSessionExtended] = useState(false); const [clientName, setClientName] = useState(""); + const [initComplete, setInitComplete] = useState(false); const { branding } = useBranding(); const [searchParams, setSearchParams] = useSearchParams(); @@ -68,7 +69,8 @@ export function CustomerPortal() { }) .catch(() => { setSearchParams({}, { replace: true }); - }); + }) + .finally(() => setInitComplete(true)); return; } @@ -90,7 +92,11 @@ export function CustomerPortal() { setClientName(devUser.name); } }) - .catch(() => {}); + .catch(() => {}) + .finally(() => setInitComplete(true)); + } else { + // No valid session: staff dev users and unauthenticated users fall through here + setInitComplete(true); } }, []); @@ -168,6 +174,16 @@ export function CustomerPortal() { const avatarInitials = (clientName.split(" ")[0] || "G").charAt(0).toUpperCase(); + // After init completes, redirect unauthenticated users to /login and staff to /admin + // The portal chrome must NEVER be visible to users without a valid client session + if (initComplete && !session) { + const devUser = getDevUser(); + if (devUser && devUser.type === "staff") { + return ; + } + return ; + } + return (
-
-

Please sign in to view your dashboard.

-
-
- ); + return ; } const upcomingAppointments = getUpcomingAppointments();