diff --git a/apps/web/src/app/(authenticated)/mission-control/page.tsx b/apps/web/src/app/(authenticated)/mission-control/page.tsx new file mode 100644 index 0000000..8ea71b9 --- /dev/null +++ b/apps/web/src/app/(authenticated)/mission-control/page.tsx @@ -0,0 +1,5 @@ +import { MissionControlLayout } from "@/components/mission-control/MissionControlLayout"; + +export default function MissionControlPage(): React.JSX.Element { + return ; +} diff --git a/apps/web/src/components/layout/AppSidebar.tsx b/apps/web/src/components/layout/AppSidebar.tsx index d0cbd97..6126c42 100644 --- a/apps/web/src/components/layout/AppSidebar.tsx +++ b/apps/web/src/components/layout/AppSidebar.tsx @@ -156,6 +156,26 @@ function IconTerminal(): React.JSX.Element { ); } +function IconMissionControl(): React.JSX.Element { + return ( + + ); +} + function IconSettings(): React.JSX.Element { return ( , }, + { + href: "/mission-control", + label: "Mission Control", + icon: , + }, ], }, { diff --git a/apps/web/src/components/mission-control/GlobalAgentRoster.tsx b/apps/web/src/components/mission-control/GlobalAgentRoster.tsx new file mode 100644 index 0000000..778d06d --- /dev/null +++ b/apps/web/src/components/mission-control/GlobalAgentRoster.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; + +export function GlobalAgentRoster(): React.JSX.Element { + return ( + + + Agent Roster + + + No active agents + + + ); +} diff --git a/apps/web/src/components/mission-control/MissionControlLayout.tsx b/apps/web/src/components/mission-control/MissionControlLayout.tsx new file mode 100644 index 0000000..135409b --- /dev/null +++ b/apps/web/src/components/mission-control/MissionControlLayout.tsx @@ -0,0 +1,21 @@ +"use client"; + +import { GlobalAgentRoster } from "@/components/mission-control/GlobalAgentRoster"; +import { MissionControlPanel } from "@/components/mission-control/MissionControlPanel"; + +const DEFAULT_PANEL_SLOTS = ["panel-1", "panel-2", "panel-3", "panel-4"] as const; + +export function MissionControlLayout(): React.JSX.Element { + return ( +
+
+ +
+ +
+
+
+ ); +} diff --git a/apps/web/src/components/mission-control/MissionControlPanel.tsx b/apps/web/src/components/mission-control/MissionControlPanel.tsx new file mode 100644 index 0000000..f17d37a --- /dev/null +++ b/apps/web/src/components/mission-control/MissionControlPanel.tsx @@ -0,0 +1,17 @@ +"use client"; + +import { OrchestratorPanel } from "@/components/mission-control/OrchestratorPanel"; + +interface MissionControlPanelProps { + panels: readonly string[]; +} + +export function MissionControlPanel({ panels }: MissionControlPanelProps): React.JSX.Element { + return ( +
+ {panels.map((panelId) => ( + + ))} +
+ ); +} diff --git a/apps/web/src/components/mission-control/OrchestratorPanel.tsx b/apps/web/src/components/mission-control/OrchestratorPanel.tsx new file mode 100644 index 0000000..6bf841a --- /dev/null +++ b/apps/web/src/components/mission-control/OrchestratorPanel.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; + +export function OrchestratorPanel(): React.JSX.Element { + return ( + + + Orchestrator Panel + + + Select an agent + + + ); +} diff --git a/apps/web/src/hooks/useMissionControl.ts b/apps/web/src/hooks/useMissionControl.ts new file mode 100644 index 0000000..3a5a429 --- /dev/null +++ b/apps/web/src/hooks/useMissionControl.ts @@ -0,0 +1,10 @@ +interface UseMissionControlResult { + sessions: []; + loading: boolean; + error: null; +} + +// Stub — will be wired in P2-002 +export function useMissionControl(): UseMissionControlResult { + return { sessions: [], loading: false, error: null }; +}