import { useQuery } from "@tanstack/react-query"; import { useMemo } from "react"; import { useParams } from "react-router-dom"; import { AgentAvatarOverlay } from "../components/FloatingAvatar"; import { KanbanColumn } from "../components/KanbanColumn"; import { useAgentPresenceFromEvents } from "../hooks/useAgentPresence"; import { usePublicBoardSSE } from "../hooks/usePublicBoardSSE"; import { api } from "../lib/api"; const TASK_STATUSES = ["todo", "in_progress", "in_review", "done", "cancelled"] as const; const TASK_STATUS_LABELS: Record = { todo: "Todo", in_progress: "In Progress", in_review: "In Review", done: "Done", cancelled: "Cancelled", }; export function SharePage() { const { slug } = useParams<{ slug: string }>(); const { data: board, isLoading, isError, } = useQuery({ queryKey: ["share", slug], queryFn: () => api.share.getBoard(slug!), enabled: !!slug, refetchInterval: 60_000, }); const { events } = usePublicBoardSSE(slug); const avatars = useAgentPresenceFromEvents(events, board?.id); const columns = useMemo(() => { if (!board?.tasks) return []; return TASK_STATUSES.map((status) => ({ status, name: TASK_STATUS_LABELS[status], tasks: board.tasks.filter((t: any) => t.status === status), })); }, [board]); if (isLoading) { return (
VTIT Agent Coding
{[0, 1, 2, 3, 4].map((i) => (
{[0, 1].map((j) => (
))}
))}
); } if (isError || !board) { return (
VTIT Agent Coding
Board not found or not public
); } return (
{/* Minimal header */}
VTIT Agent Coding / {board.name}
Get Your Agent Team →
{board.description &&
{board.description}
} {/* Desktop: 5-column kanban */}
{columns.map((col) => ( {}} /> ))}
{/* Mobile: stacked columns */}
{columns.map((col) => (
{}} />
))}
{/* Footer */}
); }