- Next.js 16 App Router site with the ANOUMA design system - Payload CMS (PostgreSQL) for offers, events, posts and page content - WebRTC video-call system with custom signaling server - SMTP email reminders and booking-request notifications - Customer accounts, calendar-based availability, and booking workflow
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { MonthCalendar, type CalendarMarker } from "./MonthCalendar";
|
|
import { BookingCard } from "./BookingCard";
|
|
import { resolveDisplayStatus } from "./BookingStatusBadge";
|
|
import type { BookingRequest } from "@/payload-types";
|
|
|
|
function dateKey(d: Date) {
|
|
return d.toISOString().slice(0, 10);
|
|
}
|
|
|
|
export function PersonalCalendar({ bookings }: { bookings: BookingRequest[] }) {
|
|
const [selectedDay, setSelectedDay] = useState<Date | null>(null);
|
|
|
|
const markers: CalendarMarker[] = bookings.map((b) => ({
|
|
date: new Date(b.date),
|
|
status: resolveDisplayStatus(b.status, b.date) as CalendarMarker["status"],
|
|
}));
|
|
|
|
const selectedBookings = selectedDay
|
|
? bookings.filter((b) => dateKey(new Date(b.date)) === dateKey(selectedDay))
|
|
: [];
|
|
|
|
return (
|
|
<div className="grid gap-8 lg:grid-cols-[minmax(0,360px)_1fr]">
|
|
<MonthCalendar markers={markers} onSelectDay={setSelectedDay} selectedDay={selectedDay} />
|
|
<div>
|
|
{selectedDay ? (
|
|
selectedBookings.length > 0 ? (
|
|
<div className="space-y-4">
|
|
{selectedBookings.map((b) => (
|
|
<BookingCard key={b.id} booking={b} />
|
|
))}
|
|
</div>
|
|
) : (
|
|
<p className="text-sm text-anouma-plum/70">An diesem Tag ist kein Termin von dir eingetragen.</p>
|
|
)
|
|
) : (
|
|
<p className="text-sm text-anouma-plum/70">Wähle einen Tag mit Markierung, um deine Termine zu sehen.</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|