feat(portal): replace mock data with real session-driven API calls #152

Merged
groombook-engineer[bot] merged 25 commits from feat/gro-203-rbac-super-user into main 2026-03-29 07:08:35 +00:00
2 changed files with 17 additions and 13 deletions
Showing only changes of commit c91f29d542 - Show all commits
+8 -5
View File
@@ -236,20 +236,23 @@ export function App() {
);
}
// Still loading auth state or setup check
if (authDisabled === null || sessionLoading || needsSetup === null) return null;
// Still loading auth state or setup check (skip setup check in dev mode)
if (authDisabled === null || sessionLoading) return null;
// Dev mode: show login selector
// Dev mode: show login selector (no setup check needed in dev mode)
if (authDisabled && location.pathname === "/login") {
return <DevLoginSelector />;
}
// Dev mode: use dev login selector
// Dev mode: use dev login selector (no setup check needed in dev mode)
if (authDisabled && !getDevUser()) {
return <Navigate to="/login" replace />;
}
// Production mode: if no session, show login page (avoids redirect loops)
// Production: need setup check
if (needsSetup === null) return null;
// Production mode: if no session, redirect to Authentik sign-in
if (!authDisabled && !session) {
return <LoginPage />;
}
+9 -8
View File
@@ -122,21 +122,22 @@ export function CustomerPortal() {
const isReadOnly = session?.status === "active";
const renderSection = () => {
const sessionId = session?.id ?? null;
switch (activeSection) {
case "dashboard":
return <Dashboard onNavigate={handleNavClick} readOnly={!!isReadOnly} onReschedule={handleReschedule} />;
return <Dashboard onNavigate={handleNavClick} readOnly={!!isReadOnly} sessionId={sessionId} clientName={clientName} onReschedule={handleReschedule} />;
case "appointments":
return <AppointmentsSection readOnly={!!isReadOnly} sessionId={session?.id ?? null} />;
return <AppointmentsSection readOnly={!!isReadOnly} sessionId={sessionId} />;
case "pets":
return <PetProfiles readOnly={!!isReadOnly} />;
return <PetProfiles readOnly={!!isReadOnly} sessionId={sessionId} />;
case "reports":
return <ReportCards />;
return <ReportCards sessionId={sessionId} />;
case "billing":
return <BillingPayments readOnly={!!isReadOnly} />;
return <BillingPayments readOnly={!!isReadOnly} sessionId={sessionId} />;
case "messages":
return <Communication readOnly={!!isReadOnly} />;
return <Communication readOnly={!!isReadOnly} sessionId={sessionId} />;
case "settings":
return <AccountSettings readOnly={!!isReadOnly} />;
return <AccountSettings readOnly={!!isReadOnly} sessionId={sessionId} />;
}
};
@@ -279,7 +280,7 @@ export function CustomerPortal() {
</h1>
</div>
<div className="flex items-center gap-3">
<span className="text-sm text-stone-600">Hi, {CUSTOMER.name.split(" ")[0]}</span>
<span className="text-sm text-stone-600">Hi, {clientName.split(" ")[0] || "Guest"}</span>
<div className="w-8 h-8 rounded-full flex items-center justify-center text-white text-sm font-medium" style={{ background: branding.accentColor }}>
SM
</div>