124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useTransition } from "react";
|
|
import { Trash2, Plus, Utensils } from "lucide-react";
|
|
import { toast } from "sonner";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
import { addMitbringsel, deleteMitbringsel } from "../actions";
|
|
|
|
type MitbringselItemDto = {
|
|
id: string;
|
|
userId: string;
|
|
content: string;
|
|
user: { firstName: string; lastName: string };
|
|
};
|
|
|
|
export function MitbringselList({
|
|
terminId,
|
|
items,
|
|
currentUserId,
|
|
isAdmin,
|
|
}: {
|
|
terminId: string;
|
|
items: MitbringselItemDto[];
|
|
currentUserId: string;
|
|
isAdmin: boolean;
|
|
}) {
|
|
const [content, setContent] = useState("");
|
|
const [isPending, startTransition] = useTransition();
|
|
|
|
const handleAdd = () => {
|
|
if (!content.trim()) return;
|
|
|
|
startTransition(async () => {
|
|
const res = await addMitbringsel({ terminId, content });
|
|
if (res.error) {
|
|
toast.error(res.error);
|
|
} else {
|
|
toast.success("Eintrag hinzugefügt.");
|
|
setContent("");
|
|
}
|
|
});
|
|
};
|
|
|
|
const handleDelete = (id: string) => {
|
|
startTransition(async () => {
|
|
const res = await deleteMitbringsel(id);
|
|
if (res.error) {
|
|
toast.error(res.error);
|
|
} else {
|
|
toast.success("Eintrag gelöscht.");
|
|
}
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col gap-3 rounded-lg bg-[var(--surface-2)] p-3">
|
|
<div className="mb-1 flex items-center gap-2 text-sm font-medium text-[var(--ink)]">
|
|
<Utensils className="h-4 w-4 text-[var(--ink-muted)] [stroke-width:1.7]" />
|
|
Mitbring-Liste
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-2 max-h-40 overflow-y-auto">
|
|
{items.length === 0 ? (
|
|
<p className="text-xs italic text-[var(--ink-faint)]">
|
|
Noch keine Einträge vorhanden.
|
|
</p>
|
|
) : (
|
|
items.map((item) => (
|
|
<div
|
|
key={item.id}
|
|
className="flex items-center justify-between gap-2 rounded-md border border-[var(--hairline-soft)] bg-[var(--surface)] p-2 text-sm text-[var(--ink)]"
|
|
>
|
|
<div className="flex flex-col">
|
|
<span className="text-xs font-medium text-[var(--accent-deep)]">
|
|
{item.user.firstName} {item.user.lastName}
|
|
</span>
|
|
<span>{item.content}</span>
|
|
</div>
|
|
{(isAdmin || item.userId === currentUserId) && (
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-6 w-6 shrink-0 text-[var(--ink-muted)] hover:bg-[var(--danger-soft)] hover:text-[var(--danger)]"
|
|
onClick={() => handleDelete(item.id)}
|
|
disabled={isPending}
|
|
>
|
|
<Trash2 className="h-4 w-4 [stroke-width:1.7]" />
|
|
</Button>
|
|
)}
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex gap-2 mt-1">
|
|
<Input
|
|
placeholder="Was bringst du mit?"
|
|
value={content}
|
|
onChange={(e) => setContent(e.target.value)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === "Enter") {
|
|
e.preventDefault();
|
|
handleAdd();
|
|
}
|
|
}}
|
|
disabled={isPending}
|
|
className="h-8 text-sm"
|
|
/>
|
|
<Button
|
|
size="sm"
|
|
className="h-8 shrink-0"
|
|
onClick={handleAdd}
|
|
disabled={!content.trim() || isPending}
|
|
>
|
|
<Plus className="mr-1 h-4 w-4 [stroke-width:1.7]" />
|
|
Hinzufügen
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|