"use client"; import { memo } from "react"; import Link from "@/components/routing/app-link"; import { IconBrandGitlab, IconCheck, IconClock, IconGitMerge, IconX } from "@tabler/icons-react"; import { Button } from "@kandev/ui/button"; import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip"; import { useTaskMRs } from "@/hooks/domains/gitlab/use-task-mr"; import { useAppStore } from "@/components/state-provider"; import type { TaskMR } from "@/lib/types/gitlab"; /** * Icon + colour for an MR's combined state. Mirrors github's pr-task-icon * priority order so a merged MR reads the same as a merged PR: terminal * states first, then pipeline failures / changes-requested, then ready-to- * merge, then awaiting-something, then pipeline-running. */ function MRStatusIcon({ mr }: { mr: TaskMR }) { if (mr.state === "merged") return ; if (mr.state === "closed") return ; if (mr.pipeline_state === "failure") return ; if (mr.approval_state === "approved" && mr.pipeline_state === "success" && !mr.draft) { return ; } if (mr.approval_state === "pending") return ; if (mr.pipeline_state === "pending") return ; return null; } function statusTextColor(mr: TaskMR): string { if (mr.state === "merged") return "text-purple-500"; if (mr.state === "closed") return "text-muted-foreground"; if (mr.pipeline_state === "failure") return "text-red-500"; if (mr.approval_state === "approved") return "text-emerald-400"; if (mr.approval_state === "pending") return "text-sky-400"; return "text-muted-foreground"; } function MRSingleButton({ mr }: { mr: TaskMR }) { const tooltip = `${mr.project_path} !${mr.mr_iid} — ${mr.mr_title}`; return ( {tooltip} ); } function MRMultiButton({ mrs }: { mrs: TaskMR[] }) { // 2+ MRs collapse into a single GitLab icon with a count. Detail panel // / dropdown for fan-out lands with phase 4. const failed = mrs.filter((m) => m.pipeline_state === "failure").length; const merged = mrs.filter((m) => m.state === "merged").length; const open = mrs.filter((m) => m.state === "open" || m.state === "opened").length; return ( {open > 0 &&
{open} open
} {failed > 0 &&
{failed} failing
} {merged > 0 &&
{merged} merged
}
); } export const MRTopbarButton = memo(function MRTopbarButton() { const activeTaskId = useAppStore((s) => s.tasks.activeTaskId); const mrs = useTaskMRs(activeTaskId); if (mrs.length === 0) return null; if (mrs.length === 1) return ; return ; });