feat(bookings): dashboard cancellation and waitlist promotion

- POST /v1/catalog/bookings/{id}/cancel lets businesses cancel
  tenant-owned bookings; two-step confirm in the detail modal
- Shared PromoteWaitlist helper promotes earliest waitlisted bookings
  when a class seat frees, on both dashboard and customer cancel paths;
  promoted customers get a confirmation email, waitlist ledger marked
  resolved
- waitlisted status surfaced in bookings UI: stats card, filter, warning
  badge, demo seed, CS+EN strings
- BookingRecord gains created_at for fair ordering; GetBookingByID and
  ResolveWaitlistEntry added to the repository surface

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-18 11:21:46 +02:00
1 parent 0405106587
commit 668a54ae1d
15 files changed
+563 -5

No files matched your search

@@ -287,6 +287,22 @@ export interface paths {
patch?: never;
trace?: never;
};
"/v1/catalog/bookings/{bookingID}/cancel": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
post: operations["cancelDashboardBooking"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/v1/catalog/class-sessions": {
parameters: {
query?: never;
@@ -2030,6 +2046,40 @@ export interface operations {
};
};
};
cancelDashboardBooking: {
parameters: {
query?: never;
header?: never;
path: {
bookingID: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Booking cancelled; freed class seats promote the waitlist */
200: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Booking already cancelled */
400: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Booking not found */
404: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
listClassSessions: {
parameters: {
query?: never;