import { Routes, Route, Link, useLocation, Navigate } from "react-router-dom"; import { useEffect, useState } from "react"; import { AppointmentsPage } from "./pages/Appointments.js"; import { ClientsPage } from "./pages/Clients.js"; import { ServicesPage } from "./pages/Services.js"; import { StaffPage } from "./pages/Staff.js"; import { InvoicesPage } from "./pages/Invoices.js"; import { BookPage } from "./pages/Book.js"; import { ReportsPage } from "./pages/Reports.js"; import { GroupBookingPage } from "./pages/GroupBooking.js"; import { SettingsPage } from "./pages/Settings.js"; import { BookingConfirmedPage } from "./pages/BookingConfirmed.js"; import { BookingCancelledPage } from "./pages/BookingCancelled.js"; import { BookingErrorPage } from "./pages/BookingError.js"; import { CustomerPortal } from "./portal/CustomerPortal.js"; import { DevLoginSelector, getDevUser } from "./pages/DevLoginSelector.js"; import { DevSessionIndicator } from "./components/DevSessionIndicator.js"; import { BrandingProvider, useBranding } from "./BrandingContext.js"; import { GlobalSearch } from "./components/GlobalSearch.js"; import { useSession, signIn } from "./lib/auth-client.js"; const NAV_LINKS = [ { to: "/admin", label: "Appointments" }, { to: "/admin/clients", label: "Clients" }, { to: "/admin/services", label: "Services" }, { to: "/admin/staff", label: "Staff" }, { to: "/admin/invoices", label: "Invoices" }, { to: "/admin/group-bookings", label: "Group Bookings" }, { to: "/admin/reports", label: "Reports" }, { to: "/admin/settings", label: "Settings" }, { to: "/", label: "Customer Portal" }, ]; function AdminLayout() { const location = useLocation(); const { branding } = useBranding(); const logoSrc = branding.logoBase64 && branding.logoMimeType ? `data:${branding.logoMimeType};base64,${branding.logoBase64}` : null; return (
} /> } /> } /> } /> } /> } /> } /> } /> } />
); } export function App() { const location = useLocation(); const [authDisabled, setAuthDisabled] = useState(null); const { data: session, isPending: sessionLoading } = useSession(); useEffect(() => { fetch("/api/dev/config") .then((r) => r.json()) .then((data) => setAuthDisabled(data.authDisabled === true)) .catch(() => setAuthDisabled(false)); }, []); // Public booking redirect pages — no auth or portal chrome needed if (location.pathname === "/booking/confirmed") { return ; } if (location.pathname === "/booking/cancelled") { return ; } if (location.pathname === "/booking/error") { return ; } // Still loading auth state if (authDisabled === null || sessionLoading) return null; // Dev mode: show login selector if (authDisabled && location.pathname === "/login") { return ; } // Dev mode: use dev login selector if (authDisabled && !getDevUser()) { return ; } // Production mode: if no session, redirect to Authentik sign-in if (!authDisabled && !session) { signIn.social({ provider: "authentik" }); return null; } return ( {location.pathname.startsWith("/admin") ? ( <> } /> {authDisabled && } ) : ( <> {authDisabled && } )} ); }