"use client";
import { useId, useState, type KeyboardEvent } from "react";
import { IconGitPullRequest } from "@tabler/icons-react";
import { cn } from "@/lib/utils";
import { PRCIPopover } from "@/components/github/pr-ci-popover";
import { getPRStatusColor, pickDefaultPR } from "@/components/github/pr-task-icon";
import { usePRFeedbackBackgroundSync } from "@/hooks/domains/github/use-pr-ci-popover";
import type { TaskPR } from "@/lib/types/github";
/**
* Renders nothing — just keeps one PR's feedback cache warm while the popover
* is mounted, so switching tabs shows fresh data immediately. One instance per
* PR (keyed by id) so the hook count stays stable as the list changes.
*/
function PRFeedbackWarmer({ pr }: { pr: TaskPR }) {
usePRFeedbackBackgroundSync(pr);
return null;
}
function prTabDomId(uid: string, pr: TaskPR): string {
return `${uid}-pr-tab-${pr.repo}-${pr.pr_number}`;
}
function PRTab({
pr,
uid,
panelId,
active,
onSelect,
}: {
pr: TaskPR;
uid: string;
panelId: string;
active: boolean;
onSelect: (pr: TaskPR) => void;
}) {
return (
);
}
/**
* Multi-PR variant of the CI popover. A segmented header lists every PR linked
* to the task (one chip per PR, coloured by its status); the body reuses the
* single-PR PRCIPopover for whichever PR is selected. Defaults to the
* worst-status open PR so problems surface first.
*/
export function MultiPRCIPopover({
prs,
enabled,
onOpenDetailPanel,
}: {
prs: TaskPR[];
enabled: boolean;
onOpenDetailPanel?: (pr: TaskPR) => void;
}) {
// `overrideId` is only set when the user activates a tab. The displayed PR is
// derived: honour the override while it still exists, otherwise fall back to
// the worst-status PR. This keeps the selection valid as the list changes
// (PR closed, new PR opened, task switch) without a setState-in-effect.
const [overrideId, setOverrideId] = useState(null);
// useId-scoped DOM ids so two mounted popovers (chip + topbar) can't collide.
// The panel id is stable across tab switches so every tab's aria-controls
// always references an element that exists in the DOM.
const uid = useId();
const panelId = `${uid}-pr-ci-tabpanel`;
const selected = prs.find((p) => p.id === overrideId) ?? pickDefaultPR(prs);
if (!selected) return null;
// ArrowLeft/ArrowRight move selection (and focus) within the tablist,
// wrapping at the ends — selection follows focus, per the ARIA tabs pattern.
const onTablistKeyDown = (e: KeyboardEvent) => {
if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
e.preventDefault();
const idx = prs.findIndex((p) => p.id === selected.id);
const delta = e.key === "ArrowRight" ? 1 : -1;
const next = prs[(idx + delta + prs.length) % prs.length];
setOverrideId(next.id);
document.getElementById(prTabDomId(uid, next))?.focus();
};
return (