'use client'; import { useMemo, useState } from 'react'; import { IconChevronRight } from '@tabler/icons-react'; import type { TaskState } from '@/lib/types/http'; import { Item, ItemActions, ItemContent, ItemDescription, ItemGroup, ItemTitle, } from '@kandev/ui/item'; import { truncateRepoPath } from '@/lib/utils'; import { TaskStateActions } from './task-state-actions'; type TaskSwitcherItem = { id: string; title: string; state?: TaskState; description?: string; columnId?: string; repositoryPath?: string; }; type TaskSwitcherProps = { tasks: TaskSwitcherItem[]; columns: Array<{ id: string; title: string }>; activeTaskId: string | null; selectedTaskId: string | null; onSelectTask: (taskId: string) => void; }; export function TaskSwitcher({ tasks, columns, activeTaskId, selectedTaskId, onSelectTask, }: TaskSwitcherProps) { const [collapsedColumnIds, setCollapsedColumnIds] = useState>(() => new Set()); const sortedTasks = useMemo(() => { return [...tasks].sort((a, b) => a.title.localeCompare(b.title)); }, [tasks]); const tasksByColumn = useMemo(() => { const grouped: Record = {}; for (const task of sortedTasks) { const key = task.columnId ?? 'unknown'; if (!grouped[key]) grouped[key] = []; grouped[key].push(task); } return grouped; }, [sortedTasks]); const columnsWithFallback = useMemo(() => { const seen = new Set(columns.map((column) => column.id)); const extra: Array<{ id: string; title: string }> = []; if (tasksByColumn.unknown?.length) { extra.push({ id: 'unknown', title: 'Other' }); } return [...columns, ...extra].filter((column) => { if (seen.has(column.id)) return true; seen.add(column.id); return true; }); }, [columns, tasksByColumn]); const handleToggleColumn = (columnId: string) => { setCollapsedColumnIds((prev) => { const next = new Set(prev); if (next.has(columnId)) next.delete(columnId); else next.add(columnId); return next; }); }; return (
Tasks {sortedTasks.length === 0 ? (
No tasks on this board.
) : (
{columnsWithFallback.map((column) => { const columnTasks = tasksByColumn[column.id] ?? []; if (columnTasks.length === 0) return null; const isColumnOpen = !collapsedColumnIds.has(column.id); return (
{isColumnOpen && (
{columnTasks.map((task) => { const isActive = task.id === activeTaskId; const isSelected = task.id === selectedTaskId || isActive; const repoLabel = task.repositoryPath ? truncateRepoPath(task.repositoryPath) : 'No repository'; return ( { event.preventDefault(); onSelectTask(task.id); }} onKeyDown={(event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); onSelectTask(task.id); } }} className="flex w-full items-center gap-2" > {task.title} {repoLabel} ); })}
)}
); })}
)}
); }