feat: add Sessions Hub page

- Add Sessions tab to navigation between Dashboard and Projects
- Show active session count badge in navigation
- Create SessionsPage with:
  - Last session section with resume button
  - Active sessions grid with open/stop actions
  - Recent sessions list
  - Create session form with project/repo/tool selectors
- Add last_session_id to user config
- Update UserConfig schemas (backend and frontend)
- Add comprehensive CSS for sessions page

Quality gates: typecheck ✓, lint ✓, build ✓
This commit is contained in:
Fusion
2026-05-19 23:06:54 +02:00
parent 4f695d7e62
commit 94aa88c154
17 changed files with 996 additions and 11 deletions
+19 -11
View File
@@ -11,6 +11,7 @@ import type { IconName } from "../utils/icons";
const NAV_ITEMS: { to: string; label: string; icon: IconName }[] = [
{ to: "/", label: "Dashboard", icon: "dashboard" },
{ to: "/sessions", label: "Sessions", icon: "terminal" },
{ to: "/projects", label: "Projects", icon: "projects" },
{ to: "/ssh-keys", label: "SSH Keys", icon: "profile" },
{ to: "/tool-types", label: "Tool Types", icon: "code" },
@@ -83,17 +84,24 @@ export const AppShell = () => {
<div className="shell-body">
<aside className="shell-nav" aria-label="Primary navigation">
{NAV_ITEMS.map((item) => (
<NavLink
key={item.to}
to={item.to}
className={({ isActive }) => (isActive ? "nav-item nav-item-active" : "nav-item")}
end={item.to === "/"}
>
<Icon name={item.icon} size="sm" />
{item.label}
</NavLink>
))}
{NAV_ITEMS.map((item) => {
const isSessions = item.to === "/sessions";
const activeCount = sessions.filter((s) => s.status === "running").length;
return (
<NavLink
key={item.to}
to={item.to}
className={({ isActive }) => (isActive ? "nav-item nav-item-active" : "nav-item")}
end={item.to === "/"}
>
<Icon name={item.icon} size="sm" />
{item.label}
{isSessions && activeCount > 0 && (
<span className="nav-badge">{activeCount}</span>
)}
</NavLink>
);
})}
{sessions.length > 0 && (
<>