feat: Token-basierte Kunden-Statusseite

- Neue /booking/{token} Route für einheitliche Buchungsübersicht
- Vollständige Termin-Details mit Status-Badges (pending/confirmed/cancelled/completed)
- Integrierte Stornierungsfunktion mit Bestätigungsdialog
- Anzeige von Behandlungsdetails, Kundendaten und verbleibender Zeit
- Automatische Berechnung ob Stornierung noch möglich
- Responsive UI mit modernem Design

Server-Erweiterungen:
- BookingAccessToken statt CancellationToken (semantisch präziser)
- Erweiterte Rückgabe von getBookingByToken (Preis, Dauer, canCancel, hoursUntilAppointment)
- Token-Generierung bei Buchungserstellung (pending) und Bestätigung

E-Mail-Integration:
- Status-Links in pending-Mails
- 'Termin verwalten' statt 'Termin stornieren' in confirmed-Mails
- Einheitliches Branding (Pink/Orange statt Rot)

Aufgeräumt:
- Legacy cancellation-page.tsx entfernt
- /cancel/ Route entfernt (keine Rückwärtskompatibilität nötig)
- Backlog aktualisiert
This commit is contained in:
2025-10-01 13:14:27 +02:00
parent 8ee2a2b3b6
commit 85fcde0805
7 changed files with 445 additions and 288 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from "react";
import { useState } from "react";
import { useAuth } from "@/client/components/auth-provider";
import { LoginForm } from "@/client/components/login-form";
import { UserProfile } from "@/client/components/user-profile";
@@ -8,32 +8,19 @@ import { AdminBookings } from "@/client/components/admin-bookings";
import { AdminCalendar } from "@/client/components/admin-calendar";
import { InitialDataLoader } from "@/client/components/initial-data-loader";
import { AdminAvailability } from "@/client/components/admin-availability";
import CancellationPage from "@/client/components/cancellation-page";
import BookingStatusPage from "@/client/components/booking-status-page";
import LegalPage from "@/client/components/legal-page";
function App() {
const { user, isLoading, isOwner } = useAuth();
const [activeTab, setActiveTab] = useState<"booking" | "admin-treatments" | "admin-bookings" | "admin-calendar" | "admin-availability" | "profile" | "legal">("booking");
// Check for cancellation token in URL
useEffect(() => {
const path = window.location.pathname;
if (path.startsWith('/cancel/')) {
const token = path.split('/cancel/')[1];
if (token) {
// Set a special state to show cancellation page
setActiveTab("cancellation" as any);
return;
}
}
}, []);
// Handle cancellation page
// Handle booking status page
const path = window.location.pathname;
if (path.startsWith('/cancel/')) {
const token = path.split('/cancel/')[1];
if (path.startsWith('/booking/')) {
const token = path.split('/booking/')[1];
if (token) {
return <CancellationPage token={token} />;
return <BookingStatusPage token={token} />;
}
}