Add booking flow, business hours, and dark mode support

Features:
- Complete multi-step booking flow with service selection, date/time picker,
  auth (login/signup with email verification), payment, and confirmation
- Business hours settings page for defining when business is open
- TimeBlock purpose field (BUSINESS_HOURS, CLOSURE, UNAVAILABLE)
- Service resource assignment with prep/takedown time buffers
- Availability checking respects business hours and service buffers
- Customer registration via email verification code

UI/UX:
- Full dark mode support for all booking components
- Separate first/last name fields in signup form
- Back buttons on each wizard step
- Removed auto-redirect from confirmation page

API:
- Public endpoints for services, availability, business hours
- Customer verification and registration endpoints
- Tenant lookup from X-Business-Subdomain header

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-11 20:20:18 -05:00
parent 76c0d71aa0
commit 4a66246708
61 changed files with 6083 additions and 855 deletions

View File

@@ -48,6 +48,9 @@ export const useCurrentBusiness = () => {
initialSetupComplete: data.initial_setup_complete,
websitePages: data.website_pages || {},
customerDashboardContent: data.customer_dashboard_content || [],
// Booking page customization
serviceSelectionHeading: data.service_selection_heading || 'Choose your experience',
serviceSelectionSubheading: data.service_selection_subheading || 'Select a service to begin your booking.',
paymentsEnabled: data.payments_enabled ?? false,
// Platform-controlled permissions
canManageOAuthCredentials: data.can_manage_oauth_credentials || false,
@@ -118,6 +121,12 @@ export const useUpdateBusiness = () => {
if (updates.customerDashboardContent !== undefined) {
backendData.customer_dashboard_content = updates.customerDashboardContent;
}
if (updates.serviceSelectionHeading !== undefined) {
backendData.service_selection_heading = updates.serviceSelectionHeading;
}
if (updates.serviceSelectionSubheading !== undefined) {
backendData.service_selection_subheading = updates.serviceSelectionSubheading;
}
const { data } = await apiClient.patch('/business/current/update/', backendData);
return data;