From c427a8240f622e5e3c19f4e7f63d7583f6acd09a Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Thu, 12 Feb 2026 14:40:07 +0530 Subject: [PATCH] feat: add provisioning indicator for board lead in task panel and implement related tests --- frontend/src/app/boards/[boardId]/page.tsx | 13 +++ .../components/BoardApprovalsPanel.test.tsx | 90 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 frontend/src/components/BoardApprovalsPanel.test.tsx diff --git a/frontend/src/app/boards/[boardId]/page.tsx b/frontend/src/app/boards/[boardId]/page.tsx index 398b2a7c..3906c1b1 100644 --- a/frontend/src/app/boards/[boardId]/page.tsx +++ b/frontend/src/app/boards/[boardId]/page.tsx @@ -14,6 +14,7 @@ import { Plus, Pencil, Play, + RefreshCcw, Settings, ShieldCheck, X, @@ -1794,6 +1795,12 @@ export default function BoardDetailPage() { }); }, [agents, workingAgentIds]); + const boardLead = useMemo( + () => agents.find((agent) => agent.is_board_lead) ?? null, + [agents], + ); + const isBoardLeadProvisioning = boardLead?.status === "provisioning"; + const loadComments = useCallback( async (taskId: string) => { if (!isSignedIn || !boardId) return; @@ -2347,6 +2354,12 @@ export default function BoardDetailPage() {

Keep tasks moving through your workflow.

+ {isBoardLeadProvisioning ? ( +
+ + Provisioning board lead… +
+ ) : null}
diff --git a/frontend/src/components/BoardApprovalsPanel.test.tsx b/frontend/src/components/BoardApprovalsPanel.test.tsx new file mode 100644 index 00000000..d4cdab87 --- /dev/null +++ b/frontend/src/components/BoardApprovalsPanel.test.tsx @@ -0,0 +1,90 @@ +import React from "react"; +import { describe, expect, it, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +import type { ApprovalRead } from "@/api/generated/model"; +import { BoardApprovalsPanel } from "./BoardApprovalsPanel"; + +vi.mock("@/auth/clerk", () => ({ + useAuth: () => ({ isSignedIn: true }), +})); + +vi.mock("recharts", () => { + type BoxProps = React.PropsWithChildren<{ className?: string }>; + const Box = ({ children, className }: BoxProps) => ( +
{children}
+ ); + return { + ResponsiveContainer: Box, + Tooltip: Box, + Legend: Box, + PieChart: Box, + Pie: Box, + Cell: Box, + }; +}); + +const renderWithQueryClient = (ui: React.ReactNode) => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + mutations: { retry: false }, + }, + }); + return render( + {ui}, + ); +}; + +describe("BoardApprovalsPanel", () => { + it("renders nested linked-approval metadata and rubric scores", () => { + const approval = { + id: "approval-1", + board_id: "board-1", + action_type: "task.create", + confidence: 62, + status: "pending", + task_id: "task-1", + created_at: "2026-02-12T10:00:00Z", + resolved_at: null, + payload: { + linked_request: { + tasks: [ + { + title: "Launch onboarding checklist", + description: "Create and validate the v1 onboarding checklist.", + }, + ], + task_ids: ["task-1", "task-2"], + }, + decision: { reason: "Needs explicit sign-off before rollout." }, + analytics: { + rubric_scores: { + clarity: 25, + risk: 20, + dependencies: 15, + }, + }, + }, + task_ids: ["task-1", "task-2"], + rubric_scores: null, + } as ApprovalRead; + + renderWithQueryClient( + , + ); + + expect( + screen.getAllByText("Launch onboarding checklist").length, + ).toBeGreaterThan(0); + expect( + screen.getByText("Create and validate the v1 onboarding checklist."), + ).toBeInTheDocument(); + expect( + screen.getByText("Needs explicit sign-off before rollout."), + ).toBeInTheDocument(); + expect(screen.getByText(/rubric scores/i)).toBeInTheDocument(); + expect(screen.getByText("Clarity")).toBeInTheDocument(); + }); +});