import { useEffect, useRef } from "react";
import { Navigate, Outlet, Route, Routes, useLocation } from "@/lib/router";
import { useQuery } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { Layout } from "./components/Layout";
import { OnboardingWizard } from "./components/OnboardingWizard";
import { authApi } from "./api/auth";
import { healthApi } from "./api/health";
import { Dashboard } from "./pages/Dashboard";
import { Companies } from "./pages/Companies";
import { Agents } from "./pages/Agents";
import { AgentDetail } from "./pages/AgentDetail";
import { Projects } from "./pages/Projects";
import { ProjectDetail } from "./pages/ProjectDetail";
import { Issues } from "./pages/Issues";
import { IssueDetail } from "./pages/IssueDetail";
import { Goals } from "./pages/Goals";
import { GoalDetail } from "./pages/GoalDetail";
import { Approvals } from "./pages/Approvals";
import { ApprovalDetail } from "./pages/ApprovalDetail";
import { Costs } from "./pages/Costs";
import { Activity } from "./pages/Activity";
import { Inbox } from "./pages/Inbox";
import { CompanySettings } from "./pages/CompanySettings";
import { DesignGuide } from "./pages/DesignGuide";
import { OrgChart } from "./pages/OrgChart";
import { AuthPage } from "./pages/Auth";
import { BoardClaimPage } from "./pages/BoardClaim";
import { InviteLandingPage } from "./pages/InviteLanding";
import { queryKeys } from "./lib/queryKeys";
import { useCompany } from "./context/CompanyContext";
import { useDialog } from "./context/DialogContext";
function BootstrapPendingPage() {
return (
Instance setup required
No instance admin exists yet. Run this command in your Paperclip environment to generate
the first admin invite URL:
{`pnpm paperclipai auth bootstrap-ceo`}
);
}
function CloudAccessGate() {
const location = useLocation();
const healthQuery = useQuery({
queryKey: queryKeys.health,
queryFn: () => healthApi.get(),
retry: false,
});
const isAuthenticatedMode = healthQuery.data?.deploymentMode === "authenticated";
const sessionQuery = useQuery({
queryKey: queryKeys.auth.session,
queryFn: () => authApi.getSession(),
enabled: isAuthenticatedMode,
retry: false,
});
if (healthQuery.isLoading || (isAuthenticatedMode && sessionQuery.isLoading)) {
return Loading...
;
}
if (healthQuery.error) {
return (
{healthQuery.error instanceof Error ? healthQuery.error.message : "Failed to load app state"}
);
}
if (isAuthenticatedMode && healthQuery.data?.bootstrapStatus === "bootstrap_pending") {
return ;
}
if (isAuthenticatedMode && !sessionQuery.data) {
const next = encodeURIComponent(`${location.pathname}${location.search}`);
return ;
}
return ;
}
function boardRoutes() {
return (
<>
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
>
);
}
function CompanyRootRedirect() {
const { companies, selectedCompany, loading } = useCompany();
if (loading) {
return Loading...
;
}
const targetCompany = selectedCompany ?? companies[0] ?? null;
if (!targetCompany) {
return ;
}
return ;
}
function UnprefixedBoardRedirect() {
const location = useLocation();
const { companies, selectedCompany, loading } = useCompany();
if (loading) {
return Loading...
;
}
const targetCompany = selectedCompany ?? companies[0] ?? null;
if (!targetCompany) {
return ;
}
return (
);
}
function NoCompaniesStartPage() {
const { openOnboarding } = useDialog();
const opened = useRef(false);
useEffect(() => {
if (opened.current) return;
opened.current = true;
openOnboarding();
}, [openOnboarding]);
return (
Create your first company
Get started by creating a company.
);
}
export function App() {
return (
} />
} />
} />
}>
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
}>
{boardRoutes()}
);
}