import { AgentSidebar } from "@agent-native/core/client/agent-chat";
import { agentNativePath, appPath } from "@agent-native/core/client/api-path";
import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
import { openCommandMenu } from "@agent-native/core/client/navigation";
import { OrgSwitcher } from "@agent-native/core/client/org";
import { FeedbackButton } from "@agent-native/core/client/ui";
import {
HeaderActionsProvider,
SidebarFooterActions,
} from "@agent-native/toolkit/app-shell";
import {
IconFlame,
IconLoader2,
IconChartBar,
IconSettings,
IconLayoutSidebarLeftCollapse,
IconLayoutSidebarLeftExpand,
IconSearch,
} from "@tabler/icons-react";
import {
useIsFetching,
useIsMutating,
useQuery,
useQueryClient,
} from "@tanstack/react-query";
import { useState, useEffect } from "react";
import { Link, useLocation, useNavigate } from "react-router";
import { Button } from "@/components/ui/button";
import { Sheet, SheetContent, SheetTitle } from "@/components/ui/sheet";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { apiFetch } from "@/lib/api";
import { cn } from "@/lib/utils";
import { Header } from "./Header";
const navItems = [
{ icon: IconFlame, labelKey: "navigation.entry", href: "/" },
{ icon: IconChartBar, labelKey: "navigation.analytics", href: "/analytics" },
];
const bottomNavItems = [
{ icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
];
export function AppLayout({ children }: { children: React.ReactNode }) {
const location = useLocation();
const navigate = useNavigate();
const queryClient = useQueryClient();
const t = useT();
const [sidebarOpen, setSidebarOpen] = useState(false);
const [desktopSidebarCollapsed, setDesktopSidebarCollapsed] = useState(() => {
if (typeof window === "undefined") return false;
return window.localStorage.getItem("macros:left-sidebar-collapsed") === "1";
});
const isAnalytics = location.pathname === "/analytics";
const isSettings = location.pathname.startsWith("/settings");
const isAgent = location.pathname.startsWith("/agent");
// Auto-close sidebar on route change (mobile)
useEffect(() => {
setSidebarOpen(false);
}, [location.pathname]);
useEffect(() => {
window.localStorage.setItem(
"macros:left-sidebar-collapsed",
desktopSidebarCollapsed ? "1" : "0",
);
}, [desktopSidebarCollapsed]);
// Navigation state sync - write current view to application state
useEffect(() => {
const view = isAgent
? "agent"
: isSettings
? "settings"
: isAnalytics
? "analytics"
: "entry";
apiFetch(agentNativePath("/_agent-native/application-state/navigation"), {
method: "PUT",
body: JSON.stringify({ view, path: location.pathname }),
}).catch(() => {});
}, [location.pathname, isAgent, isAnalytics, isSettings]);
// useDbSync invalidates this key when the agent writes a navigate command.
const { data: navCommand } = useQuery({
queryKey: ["navigate-command"],
queryFn: async () => {
try {
const res = await fetch(
agentNativePath("/_agent-native/application-state/navigate"),
);
if (!res.ok) return null;
return await res.json();
} catch {
return null;
}
},
});
useEffect(() => {
if (navCommand) {
const commandValue =
"value" in navCommand ? navCommand.value : navCommand;
const cmd =
typeof commandValue === "string"
? JSON.parse(commandValue)
: commandValue;
if (cmd.view === "analytics") {
navigate("/analytics");
} else if (cmd.view === "settings") {
navigate("/settings");
} else if (cmd.view === "agent") {
navigate("/agent");
} else if (cmd.view === "entry") {
navigate("/");
}
// Clear the command
fetch(agentNativePath("/_agent-native/application-state/navigate"), {
method: "DELETE",
}).catch(() => {});
queryClient.setQueryData(["navigate-command"], null);
}
}, [navCommand, navigate, queryClient]);
return (