'use client'; import { useCallback, useMemo, useState } from 'react'; import type { TaskState } from '@/lib/types/http'; import { TaskSwitcher } from './task-switcher'; import { Button } from '@kandev/ui/button'; import { IconPlus } from '@tabler/icons-react'; import { TaskCreateDialog } from '@/components/task-create-dialog'; import { useAppStore, useAppStoreApi } from '@/components/state-provider'; import { linkToSession } from '@/lib/links'; import { listTaskSessions } from '@/lib/http'; import { useTasks } from '@/hooks/use-tasks'; type TaskSessionSidebarProps = { workspaceId: string | null; boardId: string | null; }; export function TaskSessionSidebar({ workspaceId, boardId }: TaskSessionSidebarProps) { const activeTaskId = useAppStore((state) => state.tasks.activeTaskId); const activeSessionId = useAppStore((state) => state.tasks.activeSessionId); const sessionsById = useAppStore((state) => state.taskSessions.items); const { tasks } = useTasks(boardId); const columns = useAppStore((state) => state.kanban.columns); const workspaces = useAppStore((state) => state.workspaces.items); const repositoriesByWorkspace = useAppStore((state) => state.repositories.itemsByWorkspaceId); const setActiveTask = useAppStore((state) => state.setActiveTask); const setActiveSession = useAppStore((state) => state.setActiveSession); const setTaskSessionsForTask = useAppStore((state) => state.setTaskSessionsForTask); const setTaskSessionsLoading = useAppStore((state) => state.setTaskSessionsLoading); const selectedTaskId = useMemo(() => { if (activeSessionId) { return sessionsById[activeSessionId]?.task_id ?? activeTaskId; } return activeTaskId; }, [activeSessionId, activeTaskId, sessionsById]); const [taskDialogOpen, setTaskDialogOpen] = useState(false); const store = useAppStoreApi(); const workspaceName = useMemo(() => { if (!workspaceId) return 'Workspace'; return workspaces.find((workspace) => workspace.id === workspaceId)?.name ?? 'Workspace'; }, [workspaceId, workspaces]); const tasksWithRepositories = useMemo(() => { const repositories = workspaceId ? repositoriesByWorkspace[workspaceId] ?? [] : []; const repositoryPathsById = new Map(repositories.map((repo) => [repo.id, repo.local_path])); return tasks.map((task) => ({ id: task.id, title: task.title, state: task.state as TaskState | undefined, description: task.description, columnId: task.columnId, repositoryPath: task.repositoryId ? repositoryPathsById.get(task.repositoryId) : undefined, })); }, [repositoriesByWorkspace, tasks, workspaceId]); const updateUrl = useCallback((sessionId: string) => { if (typeof window === 'undefined') return; window.history.replaceState({}, '', linkToSession(sessionId)); }, []); const loadTaskSessionsForTask = useCallback( async (taskId: string) => { const state = store.getState(); if (state.taskSessionsByTask.loadedByTaskId[taskId]) { return state.taskSessionsByTask.itemsByTaskId[taskId] ?? []; } if (state.taskSessionsByTask.loadingByTaskId[taskId]) { return state.taskSessionsByTask.itemsByTaskId[taskId] ?? []; } setTaskSessionsLoading(taskId, true); try { const response = await listTaskSessions(taskId, { cache: 'no-store' }); setTaskSessionsForTask(taskId, response.sessions ?? []); return response.sessions ?? []; } catch (error) { console.error('Failed to load task sessions:', error); setTaskSessionsForTask(taskId, []); return []; } finally { setTaskSessionsLoading(taskId, false); } }, [setTaskSessionsForTask, setTaskSessionsLoading, store] ); const handleSelectTask = useCallback( async (taskId: string) => { const sessions = await loadTaskSessionsForTask(taskId); const sessionId = sessions[0]?.id ?? null; if (!sessionId) { setActiveTask(taskId); return; } setActiveSession(taskId, sessionId); updateUrl(sessionId); }, [loadTaskSessionsForTask, setActiveSession, setActiveTask, updateUrl] ); return ( <>