'use client'; import { useEffect, useRef, useState, FormEvent } from 'react'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogClose, } from '@/components/ui/dialog'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import type { Repository, Task } from '@/lib/types/http'; import { getBackendConfig } from '@/lib/config'; import { createTask, listRepositories, listRepositoryBranches, updateTask } from '@/lib/http/client'; interface TaskCreateDialogProps { open: boolean; onOpenChange: (open: boolean) => void; workspaceId: string | null; boardId: string | null; defaultColumnId: string | null; columns: Array<{ id: string; title: string }>; editingTask?: { id: string; title: string; description?: string; columnId: string; state?: Task['state'] } | null; onSuccess?: (task: Task, mode: 'create' | 'edit') => void; initialValues?: { title: string; description?: string; repositoryId?: string; branch?: string; state?: Task['state']; }; submitLabel?: string; } export function TaskCreateDialog({ open, onOpenChange, workspaceId, boardId, defaultColumnId, columns, editingTask, onSuccess, initialValues, submitLabel = 'Create', }: TaskCreateDialogProps) { const isEditMode = submitLabel !== 'Create'; const [title, setTitle] = useState(initialValues?.title ?? ''); const [description, setDescription] = useState(initialValues?.description ?? ''); const [repositoryId, setRepositoryId] = useState(initialValues?.repositoryId ?? ''); const [branch, setBranch] = useState(initialValues?.branch ?? ''); const [taskState, setTaskState] = useState(initialValues?.state ?? 'CREATED'); const [startAgent, setStartAgent] = useState(false); const [repositories, setRepositories] = useState([]); const [repositoriesLoading, setRepositoriesLoading] = useState(false); const [branchesByRepo, setBranchesByRepo] = useState>({}); const [branchesLoading, setBranchesLoading] = useState(false); const descriptionRef = useRef(null); useEffect(() => { if (!open) return; setTitle(initialValues?.title ?? ''); setDescription(initialValues?.description ?? ''); setRepositoryId(initialValues?.repositoryId ?? ''); setBranch(initialValues?.branch ?? ''); setTaskState(initialValues?.state ?? editingTask?.state ?? 'CREATED'); setStartAgent(false); }, [ editingTask?.state, initialValues?.branch, initialValues?.description, initialValues?.repositoryId, initialValues?.state, initialValues?.title, open, ]); useEffect(() => { if (!open || !workspaceId) return; setRepositoriesLoading(true); listRepositories(getBackendConfig().apiBaseUrl, workspaceId) .then((response) => { setRepositories(response.repositories); if (editingTask?.description && !description) { setDescription(editingTask.description); } }) .catch(() => { setRepositories([]); }) .finally(() => { setRepositoriesLoading(false); }); }, [description, editingTask?.description, open, workspaceId]); useEffect(() => { if (!repositoryId) return; if (branchesByRepo[repositoryId]) return; setBranchesLoading(true); listRepositoryBranches(getBackendConfig().apiBaseUrl, repositoryId) .then((response) => { setBranchesByRepo((prev) => ({ ...prev, [repositoryId]: response.branches })); }) .catch(() => { setBranchesByRepo((prev) => ({ ...prev, [repositoryId]: [] })); }) .finally(() => { setBranchesLoading(false); }); }, [branchesByRepo, repositoryId]); useEffect(() => { const textarea = descriptionRef.current; if (!textarea) return; textarea.style.height = 'auto'; textarea.style.height = `${textarea.scrollHeight}px`; }, [description]); const handleSubmit = async (e: FormEvent) => { e.preventDefault(); const trimmedTitle = title.trim(); if (!trimmedTitle) return; if (isEditMode && editingTask) { try { const updatedTask = await updateTask(getBackendConfig().apiBaseUrl, editingTask.id, { title: trimmedTitle, description: description.trim(), state: taskState, }); onSuccess?.(updatedTask, 'edit'); } finally { setTitle(''); setDescription(''); setRepositoryId(''); setBranch(''); setTaskState('CREATED'); setStartAgent(false); onOpenChange(false); } return; } if (!workspaceId || !boardId) return; const columnId = editingTask?.columnId ?? defaultColumnId; if (!columnId) return; let targetColumnId = columnId; let targetState: Task['state'] | undefined = taskState ?? 'CREATED'; if (startAgent && !isEditMode) { const progressColumn = columns.find((column) => column.title.toLowerCase().includes('progress') ); targetColumnId = progressColumn?.id ?? columnId; targetState = 'IN_PROGRESS'; } const repository = repositories.find((repo) => repo.id === repositoryId); try { const task = await createTask(getBackendConfig().apiBaseUrl, { workspace_id: workspaceId, board_id: boardId, column_id: targetColumnId, title: trimmedTitle, description: description.trim(), repository_url: repository?.local_path ?? '', branch: branch || '', agent_type: startAgent ? 'default' : '', state: targetState, }); onSuccess?.(task, 'create'); } finally { setTitle(''); setDescription(''); setRepositoryId(''); setBranch(''); setTaskState('CREATED'); setStartAgent(false); onOpenChange(false); } }; const handleCancel = () => { setTitle(''); setDescription(''); setRepositoryId(''); setBranch(''); setTaskState('CREATED'); setStartAgent(false); onOpenChange(false); }; return ( {submitLabel === 'Create' ? 'Create Task' : 'Edit Task'}
setTitle(e.target.value)} />