Files
kita-planer/src/app/dashboard/kalender/_components/pending-anfragen.tsx
T
2026-05-06 22:31:07 +02:00

104 lines
3.4 KiB
TypeScript

"use client";
import { useTransition } from "react";
import { format } from "date-fns";
import { de } from "date-fns/locale";
import { Check, X, Clock, CalendarIcon } from "lucide-react";
import { toast } from "sonner";
import { Termin, User } from "@prisma/client";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { approveTermin, rejectTermin } from "../actions";
type PendingTermin = Termin & {
createdBy: { firstName: string; lastName: string } | null;
};
export function PendingAnfragen({ termine }: { termine: PendingTermin[] }) {
if (termine.length === 0) {
return (
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center animate-in fade-in-50">
<CalendarIcon className="h-10 w-10 text-muted-foreground mb-4" />
<h3 className="text-lg font-semibold">Keine ausstehenden Anfragen</h3>
<p className="text-sm text-muted-foreground">
Es gibt aktuell keine Terminanfragen, die bestätigt werden müssen.
</p>
</div>
);
}
return (
<div className="flex flex-col gap-4">
{termine.map((termin) => (
<PendingTerminCard key={termin.id} termin={termin} />
))}
</div>
);
}
function PendingTerminCard({ termin }: { termin: PendingTermin }) {
const [isPending, startTransition] = useTransition();
const handleApprove = () => {
startTransition(async () => {
const res = await approveTermin(termin.id);
if (res.error) {
toast.error(res.error);
} else {
toast.success("Anfrage freigegeben.");
}
});
};
const handleReject = () => {
// In a real app, you might want to ask for a rejection reason in a prompt/modal.
startTransition(async () => {
const res = await rejectTermin(termin.id);
if (res.error) {
toast.error(res.error);
} else {
toast.success("Anfrage abgelehnt.");
}
});
};
return (
<Card>
<CardContent className="flex items-center justify-between p-4 sm:p-6">
<div className="flex flex-col gap-1">
<div className="font-semibold">{termin.title}</div>
<div className="text-sm text-muted-foreground flex items-center gap-1">
<Clock className="h-3.5 w-3.5" />
{format(termin.startDate, "PP", { locale: de })}
{!termin.allDay && `${format(termin.startDate, "p", { locale: de })}`}
</div>
<div className="text-sm font-medium text-primary mt-1">
Angefragt von: {termin.createdBy?.firstName} {termin.createdBy?.lastName}
</div>
</div>
<div className="flex flex-col sm:flex-row gap-2">
<Button
variant="outline"
className="text-destructive hover:bg-destructive hover:text-destructive-foreground border-destructive/20"
onClick={handleReject}
disabled={isPending}
>
<X className="h-4 w-4 sm:mr-2" />
<span className="hidden sm:inline">Ablehnen</span>
</Button>
<Button
className="bg-emerald-600 hover:bg-emerald-700 text-white"
onClick={handleApprove}
disabled={isPending}
>
<Check className="h-4 w-4 sm:mr-2" />
<span className="hidden sm:inline">Freigeben</span>
</Button>
</div>
</CardContent>
</Card>
);
}