import { useEffect, useState } from "react"; import type { Task, Member, Step, Event, TaskLink } from "@/lib/api"; import CreateTaskModal from "@/components/CreateTaskModal"; import { updateTask, deleteTask, getMembers, getSteps, createStep, updateStep, deleteStep as _deleteStepApi, getEvents, sendEvent, getTaskLinks, createTaskLink, deleteTaskLink, searchTasks, } from "@/lib/api"; const STATUSES = [ { key: "backlog", label: "Backlog", color: "#737373" }, { key: "todo", label: "TODO", color: "#3b82f6" }, { key: "in_progress", label: "In Progress", color: "#f59e0b" }, { key: "in_review", label: "Review", color: "#a855f7" }, { key: "done", label: "Done", color: "#22c55e" }, ]; const PRIORITIES = [ { key: "low", label: "Low", color: "#737373" }, { key: "medium", label: "Medium", color: "#3b82f6" }, { key: "high", label: "High", color: "#f59e0b" }, { key: "critical", label: "Critical", color: "#ef4444" }, ]; const AUTHOR_ICON: Record = { human: "👤", agent: "🤖", system: "⚙️", }; interface Props { task: Task; projectId: string; projectSlug: string; onClose: () => void; onUpdated: (task: Task) => void; onDeleted: (taskId: string) => void; onOpenTask?: (taskId: string) => void; } export default function TaskModal({ task, projectId: _projectId, projectSlug: _projectSlug, onClose, onUpdated, onDeleted, onOpenTask }: Props) { const [title, setTitle] = useState(task.title); const [description, setDescription] = useState(task.description || ""); const [status, setStatus] = useState(task.status); const [priority, setPriority] = useState(task.priority); const [assigneeId, setAssigneeId] = useState(task.assignee_id || ""); const [members, setMembers] = useState([]); const [steps, setSteps] = useState(task.steps || []); const [links, setLinks] = useState([]); const [showAddLink, setShowAddLink] = useState(false); const [linkTargetId, setLinkTargetId] = useState(""); const [linkSearch, setLinkSearch] = useState(""); const [linkSearchResults, setLinkSearchResults] = useState([]); const [linkType, setLinkType] = useState("depends_on"); const [comments, setComments] = useState([]); const [_saving, setSaving] = useState(false); const [editingDesc, setEditingDesc] = useState(false); const [editingTitle, setEditingTitle] = useState(false); const [showCreateSubtask, setShowCreateSubtask] = useState(false); const [confirmDelete, setConfirmDelete] = useState(false); const [newStep, setNewStep] = useState(""); const [newComment, setNewComment] = useState(""); useEffect(() => { getMembers().then(setMembers).catch(() => {}); getSteps(task.id).then(setSteps).catch(() => {}); getTaskLinks(task.id).then(setLinks).catch(() => {}); getEvents({ task_id: task.id }).then(setComments).catch(() => {}); }, [task.id]); const save = async (patch: Partial) => { setSaving(true); try { const updated = await updateTask(task.id, patch); onUpdated(updated); } catch (e) { console.error(e); } finally { setSaving(false); } }; const handleDelete = async () => { try { await deleteTask(task.id); onDeleted(task.id); onClose(); } catch (e) { console.error(e); } }; const handleAddStep = async () => { if (!newStep.trim()) return; try { const step = await createStep(task.id, newStep.trim()); setSteps((prev) => [...prev, step]); setNewStep(""); } catch (e) { console.error(e); } }; const handleToggleStep = async (step: Step) => { try { const updated = await updateStep(task.id, step.id, { done: !step.done }); setSteps((prev) => prev.map((s) => (s.id === step.id ? updated : s))); } catch (e) { console.error(e); } }; const handleAddComment = async () => { if (!newComment.trim()) return; try { const event = await sendEvent({ type: "task_comment", task_id: task.id, payload: { content: newComment.trim() } }); setComments((prev) => [...prev, event]); setNewComment(""); } catch (e) { console.error(e); } }; return (
e.stopPropagation()} > {/* Header */}
{task.parent_key && task.parent_id ? ( / ) : null} {task.key}
{editingTitle ? ( setTitle(e.target.value)} onBlur={() => { setEditingTitle(false); if (title.trim() && title !== task.title) save({ title: title.trim() }); }} onKeyDown={(e) => { if (e.key === "Enter") (e.target as HTMLInputElement).blur(); if (e.key === "Escape") { setTitle(task.title); setEditingTitle(false); } }} className="w-full text-xl font-bold bg-transparent border-b border-[var(--accent)] outline-none pb-1" /> ) : (

setEditingTitle(true)} > {title}

)}
{/* Left: Description + Steps + Comments */}
{/* Description */}
Описание {!editingDesc && ( )}
{editingDesc ? (