2026-02-23 16:08:24 -06:00
|
|
|
import { useCallback, useEffect, useRef, useState, type UIEvent } from "react";
|
2026-02-23 14:41:21 -06:00
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
|
|
|
import { BookOpen } from "lucide-react";
|
2026-02-16 13:32:04 -06:00
|
|
|
import { Outlet } from "react-router-dom";
|
2026-02-23 14:41:21 -06:00
|
|
|
import { CompanyRail } from "./CompanyRail";
|
2026-02-16 13:32:04 -06:00
|
|
|
import { Sidebar } from "./Sidebar";
|
2026-02-23 14:41:21 -06:00
|
|
|
import { SidebarNavItem } from "./SidebarNavItem";
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
import { BreadcrumbBar } from "./BreadcrumbBar";
|
|
|
|
|
import { PropertiesPanel } from "./PropertiesPanel";
|
|
|
|
|
import { CommandPalette } from "./CommandPalette";
|
|
|
|
|
import { NewIssueDialog } from "./NewIssueDialog";
|
2026-02-17 10:53:20 -06:00
|
|
|
import { NewProjectDialog } from "./NewProjectDialog";
|
2026-02-20 13:12:39 -06:00
|
|
|
import { NewGoalDialog } from "./NewGoalDialog";
|
Build out agent management UI: detail page, create dialog, list view
Add NewAgentDialog for creating agents with adapter config. Expand
AgentDetail page with tabbed view (overview, runs, config, logs),
run history timeline, and live status. Enhance Agents list page with
richer cards and filtering. Update AgentProperties panel, API client,
query keys, and utility helpers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 12:33:04 -06:00
|
|
|
import { NewAgentDialog } from "./NewAgentDialog";
|
2026-02-17 13:24:33 -06:00
|
|
|
import { OnboardingWizard } from "./OnboardingWizard";
|
2026-02-20 13:47:13 -06:00
|
|
|
import { ToastViewport } from "./ToastViewport";
|
2026-02-23 16:08:24 -06:00
|
|
|
import { MobileBottomNav } from "./MobileBottomNav";
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
import { useDialog } from "../context/DialogContext";
|
|
|
|
|
import { usePanel } from "../context/PanelContext";
|
2026-02-17 13:24:33 -06:00
|
|
|
import { useCompany } from "../context/CompanyContext";
|
2026-02-20 10:32:32 -06:00
|
|
|
import { useSidebar } from "../context/SidebarContext";
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
import { useKeyboardShortcuts } from "../hooks/useKeyboardShortcuts";
|
2026-02-23 14:47:54 -06:00
|
|
|
import { useCompanyPageMemory } from "../hooks/useCompanyPageMemory";
|
2026-02-23 14:41:21 -06:00
|
|
|
import { healthApi } from "../api/health";
|
|
|
|
|
import { queryKeys } from "../lib/queryKeys";
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
import { cn } from "../lib/utils";
|
2026-02-16 13:32:04 -06:00
|
|
|
|
|
|
|
|
export function Layout() {
|
2026-02-20 10:32:32 -06:00
|
|
|
const { sidebarOpen, setSidebarOpen, toggleSidebar, isMobile } = useSidebar();
|
2026-02-17 13:24:33 -06:00
|
|
|
const { openNewIssue, openOnboarding } = useDialog();
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
const { panelContent, closePanel } = usePanel();
|
2026-02-23 14:41:21 -06:00
|
|
|
const { companies, loading: companiesLoading, setSelectedCompanyId } = useCompany();
|
2026-02-17 13:24:33 -06:00
|
|
|
const onboardingTriggered = useRef(false);
|
2026-02-23 16:08:24 -06:00
|
|
|
const lastMainScrollTop = useRef(0);
|
|
|
|
|
const [mobileNavVisible, setMobileNavVisible] = useState(true);
|
2026-02-23 14:41:21 -06:00
|
|
|
const { data: health } = useQuery({
|
|
|
|
|
queryKey: queryKeys.health,
|
|
|
|
|
queryFn: () => healthApi.get(),
|
|
|
|
|
retry: false,
|
|
|
|
|
});
|
2026-02-17 13:24:33 -06:00
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (companiesLoading || onboardingTriggered.current) return;
|
2026-02-23 14:41:21 -06:00
|
|
|
if (health?.deploymentMode === "authenticated") return;
|
2026-02-17 13:24:33 -06:00
|
|
|
if (companies.length === 0) {
|
|
|
|
|
onboardingTriggered.current = true;
|
|
|
|
|
openOnboarding();
|
|
|
|
|
}
|
2026-02-23 14:41:21 -06:00
|
|
|
}, [companies, companiesLoading, openOnboarding, health?.deploymentMode]);
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
|
|
|
|
|
const togglePanel = useCallback(() => {
|
|
|
|
|
if (panelContent) closePanel();
|
|
|
|
|
}, [panelContent, closePanel]);
|
|
|
|
|
|
2026-02-23 14:41:21 -06:00
|
|
|
// Cmd+1..9 to switch companies
|
|
|
|
|
const switchCompany = useCallback(
|
|
|
|
|
(index: number) => {
|
|
|
|
|
if (index < companies.length) {
|
|
|
|
|
setSelectedCompanyId(companies[index]!.id);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
[companies, setSelectedCompanyId],
|
|
|
|
|
);
|
|
|
|
|
|
2026-02-23 14:47:54 -06:00
|
|
|
useCompanyPageMemory();
|
|
|
|
|
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
useKeyboardShortcuts({
|
|
|
|
|
onNewIssue: () => openNewIssue(),
|
|
|
|
|
onToggleSidebar: toggleSidebar,
|
|
|
|
|
onTogglePanel: togglePanel,
|
2026-02-23 14:41:21 -06:00
|
|
|
onSwitchCompany: switchCompany,
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
});
|
Overhaul UI with shadcn components and new pages
Add shadcn/ui components (badge, button, card, input, select,
separator). Add company context provider. New pages: Activity,
Approvals, Companies, Costs, Org chart. Restyle existing pages
(Dashboard, Agents, Issues, Goals, Projects) with shadcn components
and dark theme. Update layout, sidebar navigation, and routing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:32 -06:00
|
|
|
|
2026-02-23 16:08:24 -06:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (!isMobile) {
|
|
|
|
|
setMobileNavVisible(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
lastMainScrollTop.current = 0;
|
|
|
|
|
setMobileNavVisible(true);
|
|
|
|
|
}, [isMobile]);
|
|
|
|
|
|
2026-02-25 21:43:49 -06:00
|
|
|
// Swipe gesture to open/close sidebar on mobile
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!isMobile) return;
|
|
|
|
|
|
|
|
|
|
const EDGE_ZONE = 30; // px from left edge to start open-swipe
|
|
|
|
|
const MIN_DISTANCE = 50; // minimum horizontal swipe distance
|
|
|
|
|
const MAX_VERTICAL = 75; // max vertical drift before we ignore
|
|
|
|
|
|
|
|
|
|
let startX = 0;
|
|
|
|
|
let startY = 0;
|
|
|
|
|
|
|
|
|
|
const onTouchStart = (e: TouchEvent) => {
|
|
|
|
|
const t = e.touches[0]!;
|
|
|
|
|
startX = t.clientX;
|
|
|
|
|
startY = t.clientY;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onTouchEnd = (e: TouchEvent) => {
|
|
|
|
|
const t = e.changedTouches[0]!;
|
|
|
|
|
const dx = t.clientX - startX;
|
|
|
|
|
const dy = Math.abs(t.clientY - startY);
|
|
|
|
|
|
|
|
|
|
if (dy > MAX_VERTICAL) return; // vertical scroll, ignore
|
|
|
|
|
|
|
|
|
|
// Swipe right from left edge → open
|
|
|
|
|
if (!sidebarOpen && startX < EDGE_ZONE && dx > MIN_DISTANCE) {
|
|
|
|
|
setSidebarOpen(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Swipe left when open → close
|
|
|
|
|
if (sidebarOpen && dx < -MIN_DISTANCE) {
|
|
|
|
|
setSidebarOpen(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
document.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
|
|
|
document.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
document.removeEventListener("touchstart", onTouchStart);
|
|
|
|
|
document.removeEventListener("touchend", onTouchEnd);
|
|
|
|
|
};
|
|
|
|
|
}, [isMobile, sidebarOpen, setSidebarOpen]);
|
|
|
|
|
|
2026-02-23 16:08:24 -06:00
|
|
|
const handleMainScroll = useCallback(
|
|
|
|
|
(event: UIEvent<HTMLElement>) => {
|
|
|
|
|
if (!isMobile) return;
|
|
|
|
|
|
|
|
|
|
const currentTop = event.currentTarget.scrollTop;
|
|
|
|
|
const delta = currentTop - lastMainScrollTop.current;
|
|
|
|
|
|
|
|
|
|
if (currentTop <= 24) {
|
|
|
|
|
setMobileNavVisible(true);
|
|
|
|
|
} else if (delta > 8) {
|
|
|
|
|
setMobileNavVisible(false);
|
|
|
|
|
} else if (delta < -8) {
|
|
|
|
|
setMobileNavVisible(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lastMainScrollTop.current = currentTop;
|
|
|
|
|
},
|
|
|
|
|
[isMobile],
|
|
|
|
|
);
|
|
|
|
|
|
2026-02-16 13:32:04 -06:00
|
|
|
return (
|
2026-02-25 21:36:06 -06:00
|
|
|
<div className="flex h-dvh bg-background text-foreground overflow-hidden pt-[env(safe-area-inset-top)]">
|
2026-02-20 10:32:32 -06:00
|
|
|
{/* Mobile backdrop */}
|
|
|
|
|
{isMobile && sidebarOpen && (
|
|
|
|
|
<div
|
|
|
|
|
className="fixed inset-0 z-40 bg-black/50"
|
|
|
|
|
onClick={() => setSidebarOpen(false)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
2026-02-23 14:41:21 -06:00
|
|
|
{/* Combined sidebar area: company rail + inner sidebar + docs bar */}
|
2026-02-20 10:32:32 -06:00
|
|
|
{isMobile ? (
|
|
|
|
|
<div
|
|
|
|
|
className={cn(
|
2026-02-25 21:36:06 -06:00
|
|
|
"fixed inset-y-0 left-0 z-50 flex flex-col overflow-hidden pt-[env(safe-area-inset-top)] transition-transform duration-200 ease-in-out",
|
2026-02-20 10:32:32 -06:00
|
|
|
sidebarOpen ? "translate-x-0" : "-translate-x-full"
|
|
|
|
|
)}
|
|
|
|
|
>
|
2026-02-25 21:36:06 -06:00
|
|
|
<div className="flex flex-1 min-h-0 overflow-hidden">
|
|
|
|
|
<CompanyRail />
|
|
|
|
|
<Sidebar />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="border-t border-r border-border px-3 py-2 bg-background">
|
|
|
|
|
<SidebarNavItem to="/docs" label="Documentation" icon={BookOpen} />
|
2026-02-23 14:41:21 -06:00
|
|
|
</div>
|
2026-02-20 10:32:32 -06:00
|
|
|
</div>
|
|
|
|
|
) : (
|
2026-02-23 14:41:21 -06:00
|
|
|
<div className="flex flex-col shrink-0 h-full">
|
|
|
|
|
<div className="flex flex-1 min-h-0">
|
|
|
|
|
<CompanyRail />
|
|
|
|
|
<div
|
|
|
|
|
className={cn(
|
|
|
|
|
"overflow-hidden transition-all duration-200 ease-in-out",
|
|
|
|
|
sidebarOpen ? "w-60" : "w-0"
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
<Sidebar />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="border-t border-r border-border px-3 py-2">
|
|
|
|
|
<SidebarNavItem to="/docs" label="Documentation" icon={BookOpen} />
|
|
|
|
|
</div>
|
2026-02-20 10:32:32 -06:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* Main content */}
|
2026-02-17 10:53:20 -06:00
|
|
|
<div className="flex-1 flex flex-col min-w-0 h-full">
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
<BreadcrumbBar />
|
2026-02-17 10:53:20 -06:00
|
|
|
<div className="flex flex-1 min-h-0">
|
2026-02-23 16:08:24 -06:00
|
|
|
<main
|
2026-02-25 21:36:06 -06:00
|
|
|
className={cn("flex-1 overflow-auto p-4 md:p-6", isMobile && "pb-[calc(5rem+env(safe-area-inset-bottom))]")}
|
2026-02-23 16:08:24 -06:00
|
|
|
onScroll={handleMainScroll}
|
|
|
|
|
>
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
<Outlet />
|
|
|
|
|
</main>
|
|
|
|
|
<PropertiesPanel />
|
|
|
|
|
</div>
|
Overhaul UI with shadcn components and new pages
Add shadcn/ui components (badge, button, card, input, select,
separator). Add company context provider. New pages: Activity,
Approvals, Companies, Costs, Org chart. Restyle existing pages
(Dashboard, Agents, Issues, Goals, Projects) with shadcn components
and dark theme. Update layout, sidebar navigation, and routing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:32 -06:00
|
|
|
</div>
|
2026-02-23 16:08:24 -06:00
|
|
|
{isMobile && <MobileBottomNav visible={mobileNavVisible} />}
|
Add shared UI primitives, contexts, and reusable components
Add shadcn components: avatar, breadcrumb, checkbox, collapsible,
command, dialog, dropdown-menu, label, popover, scroll-area, sheet,
skeleton, tabs, textarea, tooltip. Add shared components: BreadcrumbBar,
CommandPalette, CompanySwitcher, CommentThread, EmptyState, EntityRow,
FilterBar, InlineEditor, MetricCard, PageSkeleton, PriorityIcon,
PropertiesPanel, StatusIcon, SidebarNavItem/Section. Add contexts for
breadcrumbs, dialogs, and side panels. Add keyboard shortcut hook and
utility helpers. Update layout, sidebar, and main app shell.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:00 -06:00
|
|
|
<CommandPalette />
|
|
|
|
|
<NewIssueDialog />
|
2026-02-17 10:53:20 -06:00
|
|
|
<NewProjectDialog />
|
2026-02-20 13:12:39 -06:00
|
|
|
<NewGoalDialog />
|
Build out agent management UI: detail page, create dialog, list view
Add NewAgentDialog for creating agents with adapter config. Expand
AgentDetail page with tabbed view (overview, runs, config, logs),
run history timeline, and live status. Enhance Agents list page with
richer cards and filtering. Update AgentProperties panel, API client,
query keys, and utility helpers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 12:33:04 -06:00
|
|
|
<NewAgentDialog />
|
2026-02-17 13:24:33 -06:00
|
|
|
<OnboardingWizard />
|
2026-02-20 13:47:13 -06:00
|
|
|
<ToastViewport />
|
2026-02-16 13:32:04 -06:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|