import { CheckCircle2, Circle, Pencil, Plus, Save, Trash2 } from "lucide-react"; import { FormEvent, useState } from "react"; import { toast } from "sonner"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { cn } from "@/lib/utils"; import { createTicketTodo, deleteTodo, updateTodo } from "../api"; import type { TicketTodo, TodoPriority, TodoStatus } from "../types"; const priorityLabels: Record = { low: "Niedrig", medium: "Normal", high: "Hoch", urgent: "Dringend" }; const priorityClasses: Record = { low: "border-sky-500/30 bg-sky-500/10 text-sky-300", medium: "border-muted-foreground/25 bg-muted/50 text-muted-foreground", high: "border-amber-500/30 bg-amber-500/10 text-amber-300", urgent: "border-red-500/30 bg-red-500/10 text-red-300" }; type TodoPanelProps = { ticketId?: string; todos: TicketTodo[]; onChanged: () => Promise | void; showCreate?: boolean; showTicketMeta?: boolean; onNavigate?: (to: string) => void; }; export function TodoPanel({ ticketId, todos, onChanged, showCreate = true, showTicketMeta = false, onNavigate }: TodoPanelProps) { const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [priority, setPriority] = useState("medium"); const [saving, setSaving] = useState(false); const [createOpen, setCreateOpen] = useState(false); const [editingId, setEditingId] = useState(null); const [editTitle, setEditTitle] = useState(""); const [editDescription, setEditDescription] = useState(""); const [editPriority, setEditPriority] = useState("medium"); const [busyId, setBusyId] = useState(null); async function submitTodo(event: FormEvent) { event.preventDefault(); if (!ticketId) { return; } setSaving(true); try { await createTicketTodo(ticketId, { title, description, priority }); setTitle(""); setDescription(""); setPriority("medium"); setCreateOpen(false); toast.success("ToDo angelegt"); await onChanged(); } catch (error) { toast.error("ToDo konnte nicht angelegt werden", { description: error instanceof Error ? error.message : "Unbekannter Fehler" }); } finally { setSaving(false); } } function startEdit(todo: TicketTodo) { setEditingId(todo.id); setEditTitle(todo.title); setEditDescription(todo.description); setEditPriority(todo.priority); } async function saveTodo(todo: TicketTodo, status: TodoStatus = todo.status) { setBusyId(todo.id); try { await updateTodo(todo.id, { title: editingId === todo.id ? editTitle : todo.title, description: editingId === todo.id ? editDescription : todo.description, priority: editingId === todo.id ? editPriority : todo.priority, status }); setEditingId(null); await onChanged(); } catch (error) { toast.error("ToDo konnte nicht gespeichert werden", { description: error instanceof Error ? error.message : "Unbekannter Fehler" }); } finally { setBusyId(null); } } async function removeTodo(todo: TicketTodo) { const confirmed = window.confirm(`ToDo "${todo.title}" wirklich löschen?`); if (!confirmed) { return; } setBusyId(todo.id); try { await deleteTodo(todo.id); toast.success("ToDo gelöscht"); await onChanged(); } catch (error) { toast.error("ToDo konnte nicht gelöscht werden", { description: error instanceof Error ? error.message : "Unbekannter Fehler" }); } finally { setBusyId(null); } } return (
{showCreate && ticketId ? (
ToDo anlegen Neue Aufgabe zu diesem Ticket oder Projekt erfassen.
setTitle(event.currentTarget.value)} autoFocus required />