feat: Erweiterte Filtermöglichkeiten für Buchungsverwaltung

- Neue Filter-Modi: Zukünftige (default), Alle, Datum
- Filter-Buttons mit visueller Hervorhebung des aktiven Filters
- Datumsauswahl nur sichtbar wenn Datum-Filter aktiv
- Default-Filter zeigt alle zukünftigen (nicht stornierten) Buchungen
- Angepasste Leermeldungen je nach aktivem Filter
This commit is contained in:
2025-10-09 08:50:25 +02:00
parent f0037226a9
commit a603232ed8

View File

@@ -3,6 +3,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { queryClient } from "@/client/rpc-client";
export function AdminBookings() {
const [filterMode, setFilterMode] = useState<"upcoming" | "all" | "date">("upcoming");
const [selectedDate, setSelectedDate] = useState(new Date().toISOString().split('T')[0]);
const [selectedPhoto, setSelectedPhoto] = useState<string>("");
const [showPhotoModal, setShowPhotoModal] = useState(false);
@@ -139,9 +140,23 @@ export function AdminBookings() {
return appointmentDate >= today;
};
const filteredBookings = bookings?.filter(booking =>
selectedDate ? booking.appointmentDate === selectedDate : true
).sort((a, b) => {
// Filter bookings based on selected filter mode
const filteredBookings = bookings?.filter(booking => {
if (filterMode === "upcoming") {
// Show all future bookings (not cancelled)
const bookingDate = new Date(booking.appointmentDate);
const today = new Date();
today.setHours(0, 0, 0, 0);
bookingDate.setHours(0, 0, 0, 0);
return bookingDate >= today && booking.status !== "cancelled";
} else if (filterMode === "date") {
// Show bookings for specific date
return booking.appointmentDate === selectedDate;
} else {
// Show all bookings
return true;
}
}).sort((a, b) => {
if (a.appointmentDate === b.appointmentDate) {
return a.appointmentTime.localeCompare(b.appointmentTime);
}
@@ -218,22 +233,54 @@ export function AdminBookings() {
</div>
</div>
{/* Date Filter */}
{/* Filter Section */}
<div className="bg-white rounded-lg shadow p-4 mb-6">
<div className="flex items-center space-x-4">
<label className="text-sm font-medium text-gray-700">Filter by date:</label>
<input
type="date"
value={selectedDate}
onChange={(e) => setSelectedDate(e.target.value)}
className="p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-pink-500 focus:border-pink-500"
/>
<button
onClick={() => setSelectedDate("")}
className="text-sm text-pink-600 hover:text-pink-800"
>
Show All
</button>
<div className="flex flex-col space-y-4">
<div className="flex items-center space-x-2">
<label className="text-sm font-medium text-gray-700">Filter:</label>
<button
onClick={() => setFilterMode("upcoming")}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
filterMode === "upcoming"
? "bg-pink-600 text-white"
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
}`}
>
Zukünftige
</button>
<button
onClick={() => setFilterMode("all")}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
filterMode === "all"
? "bg-pink-600 text-white"
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
}`}
>
Alle
</button>
<button
onClick={() => setFilterMode("date")}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
filterMode === "date"
? "bg-pink-600 text-white"
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
}`}
>
Datum
</button>
</div>
{filterMode === "date" && (
<div className="flex items-center space-x-4 pl-16">
<label className="text-sm font-medium text-gray-700">Wähle Datum:</label>
<input
type="date"
value={selectedDate}
onChange={(e) => setSelectedDate(e.target.value)}
className="p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-pink-500 focus:border-pink-500"
/>
</div>
)}
</div>
</div>
@@ -369,8 +416,10 @@ export function AdminBookings() {
{!filteredBookings?.length && (
<div className="text-center py-8 text-gray-500">
{selectedDate
{filterMode === "date"
? `Keine Buchungen für ${new Date(selectedDate).toLocaleDateString()} gefunden`
: filterMode === "upcoming"
? "Keine zukünftigen Buchungen verfügbar."
: "Keine Buchungen verfügbar."
}
</div>