Refine project and todo workflow

This commit is contained in:
michael committed 2026-09-02 11:23:34 +02:00
1 parent 3da436423f
commit 239be9f218
9 files changed
+487 -301

No files matched your search

+61 -35
View File
@@ -4,6 +4,7 @@ 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";
@@ -38,6 +39,7 @@ export function TodoPanel({ ticketId, todos, onChanged, showCreate = true, showT
const [description, setDescription] = useState("");
const [priority, setPriority] = useState<TodoPriority>("medium");
const [saving, setSaving] = useState(false);
const [createOpen, setCreateOpen] = useState(false);
const [editingId, setEditingId] = useState<string | null>(null);
const [editTitle, setEditTitle] = useState("");
const [editDescription, setEditDescription] = useState("");
@@ -57,6 +59,7 @@ export function TodoPanel({ ticketId, todos, onChanged, showCreate = true, showT
setTitle("");
setDescription("");
setPriority("medium");
setCreateOpen(false);
toast.success("ToDo angelegt");
await onChanged();
} catch (error) {
@@ -119,41 +122,64 @@ export function TodoPanel({ ticketId, todos, onChanged, showCreate = true, showT
return (
<div className="space-y-3">
{showCreate && ticketId ? (
<form className="grid gap-3 lg:grid-cols-[minmax(220px,1fr)_160px_auto] lg:items-end" onSubmit={submitTodo}>
<div className="space-y-2">
<label className="text-sm font-medium" htmlFor={`todo-title-${ticketId}`}>
Aufgabe
</label>
<Input id={`todo-title-${ticketId}`} value={title} onChange={(event) => setTitle(event.currentTarget.value)} required />
</div>
<div className="space-y-2">
<label className="text-sm font-medium" htmlFor={`todo-priority-${ticketId}`}>
Priorität
</label>
<select
id={`todo-priority-${ticketId}`}
className="h-9 w-full rounded-lg border border-input bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
value={priority}
onChange={(event) => setPriority(event.currentTarget.value as TodoPriority)}
>
{Object.entries(priorityLabels).map(([value, label]) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
</div>
<Button type="submit" disabled={saving}>
<Plus className="size-4" />
{saving ? "Speichert..." : "Anlegen"}
</Button>
<Textarea
className="min-h-16 lg:col-span-3"
placeholder="Details optional"
value={description}
onChange={(event) => setDescription(event.currentTarget.value)}
/>
</form>
<div className="flex justify-end">
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
<DialogTrigger asChild>
<Button type="button" size="sm">
<Plus className="size-4" />
ToDo anlegen
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>ToDo anlegen</DialogTitle>
<DialogDescription>Neue Aufgabe zu diesem Ticket oder Projekt erfassen.</DialogDescription>
</DialogHeader>
<form className="space-y-4" onSubmit={submitTodo}>
<div className="space-y-2">
<label className="text-sm font-medium" htmlFor={`todo-title-${ticketId}`}>
Aufgabe
</label>
<Input id={`todo-title-${ticketId}`} value={title} onChange={(event) => setTitle(event.currentTarget.value)} autoFocus required />
</div>
<div className="space-y-2">
<label className="text-sm font-medium" htmlFor={`todo-priority-${ticketId}`}>
Priorität
</label>
<select
id={`todo-priority-${ticketId}`}
className="h-9 w-full rounded-lg border border-input bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
value={priority}
onChange={(event) => setPriority(event.currentTarget.value as TodoPriority)}
>
{Object.entries(priorityLabels).map(([value, label]) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
</div>
<div className="space-y-2">
<label className="text-sm font-medium" htmlFor={`todo-description-${ticketId}`}>
Details
</label>
<Textarea
id={`todo-description-${ticketId}`}
className="min-h-24"
value={description}
onChange={(event) => setDescription(event.currentTarget.value)}
/>
</div>
<div className="flex justify-end">
<Button type="submit" disabled={saving}>
<Plus className="size-4" />
{saving ? "Speichert..." : "Anlegen"}
</Button>
</div>
</form>
</DialogContent>
</Dialog>
</div>
) : null}
<div className="space-y-2">