"use client"; import { useState } from "react"; import { Task } from "@/types"; import { useUpdateTask } from "@/hooks/use-tasks"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Markdown } from "@/components/ui/markdown"; import { HelpTip } from "@/components/ui/help-tip"; import { CollapsibleSection } from "./collapsible-section"; import { Edit3, Eye, Check, X, ShieldAlert } from "lucide-react"; import { toast } from "sonner"; interface TaskDescriptionProps { task: Task; } export function TaskDescription({ task }: TaskDescriptionProps) { const updateTask = useUpdateTask(); const [isEditing, setIsEditing] = useState(false); const [localEditValue, setLocalEditValue] = useState(""); const [editMode, setEditMode] = useState<"write" | "preview">("write"); const [sectionOpen, setSectionOpen] = useState(true); // Display prop value when not editing, local value when editing const editValue = isEditing ? localEditValue : task.description; const setEditValue = (value: string) => setLocalEditValue(value); // Start editing - copy current prop value to local state const startEditing = () => { setLocalEditValue(task.description); setIsEditing(true); }; const handleCheckboxChange = async (newDescription: string) => { try { await updateTask.mutateAsync({ taskId: task.id, updates: { description: newDescription }, }); } catch { toast.error("Failed to update task"); } }; const handleSave = async () => { if (editValue === task.description) { setIsEditing(false); return; } try { await updateTask.mutateAsync({ taskId: task.id, updates: { description: editValue }, }); setIsEditing(false); setEditMode("write"); } catch { toast.error("Failed to update description"); } }; const handleCancel = () => { setEditValue(task.description); setIsEditing(false); setEditMode("write"); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Escape") { handleCancel(); } // Save with Cmd/Ctrl + Enter if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); handleSave(); } }; return ( <> setEditMode(v as "write" | "preview")} > Write Preview Save > ) : ( Edit ) } > {isEditing ? ( {editMode === "write" ? ( setEditValue(e.target.value)} onKeyDown={handleKeyDown} placeholder="Add a description..." className="min-h-[200px] font-mono text-sm" disabled={updateTask.isPending} autoFocus /> ) : ( {editValue ? ( {editValue} ) : ( Nothing to preview )} )} Markdown supported. Press Ctrl/Cmd + Enter to save, Escape to cancel. ) : task.description ? ( {task.description} ) : ( No description provided. Click to add one. )} {task.constraints ? ( Constraints > } className="border-amber-300 bg-amber-50/60 dark:border-amber-800 dark:bg-amber-950/20" > Architectural standard derived from the project conventions — read-only. Applies to every task in this project. {task.constraints} ) : null} > ); }
Nothing to preview
Markdown supported. Press Ctrl/Cmd + Enter to save, Escape to cancel.
No description provided. Click to add one.
Architectural standard derived from the project conventions — read-only. Applies to every task in this project.