"use client"; import { useCallback } from "react"; import { useRouter } from "@/lib/routing/client-router"; import { IconChecklist } from "@tabler/icons-react"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@kandev/ui/dropdown-menu"; import { Badge } from "@kandev/ui/badge"; import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip"; import { useAppStore } from "@/components/state-provider"; import { cn } from "@/lib/utils"; import { linkToTask } from "@/lib/links"; import { useTaskById } from "@/hooks/domains/kanban/use-task-by-id"; import type { KanbanState } from "@/lib/state/slices"; import { useTranslation } from "react-i18next"; export type TaskRowLink = { id: string; taskId: string; fallbackTitle: string; }; type TaskRowIndicatorProps = { tasks: TaskRowLink[] | undefined; testIdPrefix: string; emptyLabel?: string; }; function useTaskStepTitle(workflowStepId: string | undefined): string | null { return useAppStore((state) => { if (!workflowStepId) return null; const findIn = (steps: KanbanState["steps"]) => steps.find((step) => step.id === workflowStepId)?.title ?? null; const activeTitle = findIn(state.kanban.steps); if (activeTitle) return activeTitle; for (const snapshot of Object.values(state.kanbanMulti.snapshots)) { const title = findIn(snapshot.steps); if (title) return title; } return null; }); } function TaskTitle({ task }: { task: TaskRowLink }) { const taskData = useTaskById(task.taskId); const title = taskData?.title ?? task.fallbackTitle; return ( {title} ); } const buttonClass = cn( "inline-flex items-center gap-1.5 rounded px-1.5 py-0.5 text-xs", "hover:bg-muted/70 transition-colors cursor-pointer w-fit max-w-full", ); const iconClass = "h-3 w-3 shrink-0 text-muted-foreground"; function SingleTaskButton({ task, testIdPrefix, onNavigate, }: { task: TaskRowLink; testIdPrefix: string; onNavigate: (taskId: string) => void; }) { const taskData = useTaskById(task.taskId); const stepTitle = useTaskStepTitle(taskData?.workflowStepId); const title = taskData?.title ?? task.fallbackTitle; const { t } = useTranslation(); return ( onNavigate(task.taskId)} className={buttonClass} > {title} {t("github:taskLabelled", { title })} {stepTitle ? ( {t("github:stepLabelled", { stepTitle })} ) : null} ); } export function TaskRowIndicator({ tasks, testIdPrefix, emptyLabel }: TaskRowIndicatorProps) { const { t } = useTranslation(); const setActiveTask = useAppStore((state) => state.setActiveTask); const router = useRouter(); const navigate = useCallback( (taskId: string) => { setActiveTask(taskId); router.push(linkToTask(taskId)); }, [router, setActiveTask], ); if (!tasks || tasks.length === 0) { return emptyLabel ? ( {emptyLabel} ) : null; } if (tasks.length === 1) { return ; } return ( {t("github:tasks")} {tasks.length} {tasks.map((task) => ( navigate(task.taskId)} > ))} ); }