mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 07:41:16 +00:00
feat(booking): stepped public booking flow with service/staff selection
The public booking page showed a capped flat preview of slots with no way to pick a service, day, or staff member. Replaces it with a stepped flow: pick service, optional staff preference, pick a day, pick a time. Backend: availability accepts serviceId/staffId/date filters (default response unchanged for the embed widget), a new public catalog endpoint exposes bookable services and active staff, and slots carry staffName. Slot generation and booking creation now honor tenant-wide and per-staff blocked days; appointment requests must fit inside a matching availability rule and reference tenant-owned, active staff and locations. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
09f780e7a6
commit
d9aa29dbcb
9 files changed
+940
-118
No files matched your search
@@ -607,6 +607,22 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/public/tenants/{tenantSlug}/catalog": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getPublicCatalog"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/public/widget.js": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1033,6 +1049,11 @@ export interface components {
|
||||
tenantSlug: string;
|
||||
timezone: string;
|
||||
};
|
||||
PublicCatalogResponse: {
|
||||
services: components["schemas"]["PublicService"][];
|
||||
staff: components["schemas"]["PublicStaff"][];
|
||||
tenantSlug: string;
|
||||
};
|
||||
PublicConfig: {
|
||||
/** Format: uri */
|
||||
apiUrl: string;
|
||||
@@ -1040,6 +1061,18 @@ export interface components {
|
||||
environment: string;
|
||||
neonAuthEnabled: boolean;
|
||||
};
|
||||
PublicService: {
|
||||
durationMinutes: number;
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
name: string;
|
||||
priceCents: number;
|
||||
};
|
||||
PublicStaff: {
|
||||
displayName: string;
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
};
|
||||
Service: {
|
||||
/** @description Blocked time after the appointment (0-480) */
|
||||
bufferAfterMinutes: number;
|
||||
@@ -1136,6 +1169,7 @@ export interface components {
|
||||
serviceId?: string | null;
|
||||
/** Format: uuid */
|
||||
staffId?: string | null;
|
||||
staffName?: string | null;
|
||||
/** Format: date-time */
|
||||
startsAt: string;
|
||||
};
|
||||
@@ -2674,7 +2708,14 @@ export interface operations {
|
||||
};
|
||||
getPublicAvailability: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
query?: {
|
||||
/** @description Return all slots for a single tenant-local day (YYYY-MM-DD) instead of the capped preview */
|
||||
date?: string;
|
||||
/** @description Restrict appointment slots to a single service */
|
||||
serviceId?: string;
|
||||
/** @description Restrict appointment slots to a single staff member */
|
||||
staffId?: string;
|
||||
};
|
||||
header?: never;
|
||||
path: {
|
||||
tenantSlug: string;
|
||||
@@ -2694,6 +2735,28 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
getPublicCatalog: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
tenantSlug: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Bookable services and active staff for a tenant booking page */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["PublicCatalogResponse"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
getWidgetScript: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
Reference in new issue
Block a user