@licklist/design 0.78.5-dev.106 → 0.78.5-dev.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +3 -0
- package/bitbucket-pipelines.yml +13 -4
- package/dist/Maintenance/Maintenance.scss.js +1 -1
- package/dist/product-set/form/ProductsControl.d.ts +2 -1
- package/dist/product-set/form/ProductsControl.d.ts.map +1 -1
- package/dist/product-set/form/ProductsControl.js +0 -24
- package/dist/v2/components/ActionMenu/ActionMenu.scss.js +1 -1
- package/dist/v2/components/Badge/Badge.scss.js +1 -1
- package/dist/v2/components/Button/Button.scss.js +1 -1
- package/dist/v2/components/Button/GhostButton.scss.js +1 -1
- package/dist/v2/components/Checkbox/Checkbox.scss.js +1 -1
- package/dist/v2/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/v2/components/DataTable/DataTable.js +86 -2
- package/dist/v2/components/IconButton/IconButton.scss.js +1 -1
- package/dist/v2/components/Modal/DeleteModal.d.ts.map +1 -1
- package/dist/v2/components/Modal/DeleteModal.js +13 -11
- package/dist/v2/components/Modal/DeleteModal.scss.js +1 -1
- package/dist/v2/components/NPSScore/NPSScore.scss.js +1 -1
- package/dist/v2/components/NewTabs/NewTabs.scss.js +1 -1
- package/dist/v2/components/Select/Select.scss.js +1 -1
- package/dist/v2/components/StatusBadge/StatusBadge.scss.js +1 -1
- package/dist/v2/components/StepIndicator/StepIndicator.scss.js +1 -1
- package/dist/v2/components/Tabs/Tabs.scss.js +1 -1
- package/dist/v2/components/Toggle/Toggle.d.ts.map +1 -1
- package/dist/v2/components/Toggle/Toggle.js +8 -5
- package/dist/v2/components/Tooltip/Tooltip.scss.js +1 -1
- package/dist/v2/components/UserAvatar/UserAvatar.scss.js +1 -1
- package/dist/v2/components/UserPanel/UserPanel.scss.js +1 -1
- package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.scss.js +1 -1
- package/dist/v2/components/ZoneCard/ZoneCard.scss.js +1 -1
- package/dist/v2/dashboard-analytics/chart/Chart.scss.js +1 -1
- package/dist/v2/dashboard-analytics/metric-card/MetricCard.scss.js +1 -1
- package/dist/v2/dashboard-analytics/venue-card/VenueCard.scss.js +1 -1
- package/dist/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.scss.js +1 -1
- package/dist/v2/icons/index.js +1 -16
- package/dist/v2/index.d.ts +0 -4
- package/dist/v2/index.d.ts.map +1 -1
- package/dist/v2/navigation/DashboardLayout/AdminSidebar.scss.js +1 -1
- package/dist/v2/navigation/DashboardLayout/DashboardLayout.scss.js +1 -1
- package/dist/v2/navigation/DashboardLayout/ProviderSidebar.scss.js +1 -1
- package/dist/v2/navigation/DashboardLayout/TopNavigation.scss.js +1 -1
- package/dist/v2/pages/Settings/SettingsTabs.scss.js +1 -1
- package/dist/v2/pages/Settings/components/SidebarCustomisation.js +0 -3
- package/dist/v2/pages/Settings/components/SidebarCustomisation.scss.js +1 -1
- package/dist/v2/pages/Settings/components/SidebarNavItem.js +0 -3
- package/dist/v2/pages/auth/AuthLayout/AuthLayout.scss.js +1 -1
- package/dist/v2/styles/form/NewInput.scss.js +1 -1
- package/package.json +6 -6
- package/rollup.config.js +16 -2
- package/src/iframe/payment/payment-status-page/PaymentStatusPage.tsx +1 -1
- package/src/product-set/form/ProductsControl.tsx +2 -1
- package/src/v2/components/DataTable/DataTable.tsx +23 -1
- package/src/v2/components/Modal/DeleteModal.tsx +12 -20
- package/src/v2/components/Toggle/Toggle.tsx +6 -5
- package/src/v2/index.ts +0 -73
- package/dist/v2/shadcn/components/ui/accordion.d.ts +0 -8
- package/dist/v2/shadcn/components/ui/accordion.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/alert-dialog.d.ts +0 -21
- package/dist/v2/shadcn/components/ui/alert-dialog.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/alert.d.ts +0 -9
- package/dist/v2/shadcn/components/ui/alert.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts +0 -4
- package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/avatar.d.ts +0 -7
- package/dist/v2/shadcn/components/ui/avatar.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/badge.d.ts +0 -10
- package/dist/v2/shadcn/components/ui/badge.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/breadcrumb.d.ts +0 -20
- package/dist/v2/shadcn/components/ui/breadcrumb.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/button.d.ts +0 -14
- package/dist/v2/shadcn/components/ui/button.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/calendar.d.ts +0 -9
- package/dist/v2/shadcn/components/ui/calendar.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/card.d.ts +0 -9
- package/dist/v2/shadcn/components/ui/card.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/carousel.d.ts +0 -19
- package/dist/v2/shadcn/components/ui/carousel.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/checkbox.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/checkbox.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/checkbox.js +0 -115
- package/dist/v2/shadcn/components/ui/checkbox.scss.js +0 -6
- package/dist/v2/shadcn/components/ui/collapsible.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/collapsible.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/command.d.ts +0 -83
- package/dist/v2/shadcn/components/ui/command.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/context-menu.d.ts +0 -28
- package/dist/v2/shadcn/components/ui/context-menu.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/dialog.d.ts +0 -20
- package/dist/v2/shadcn/components/ui/dialog.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/dialog.js +0 -169
- package/dist/v2/shadcn/components/ui/drawer.d.ts +0 -23
- package/dist/v2/shadcn/components/ui/drawer.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts +0 -28
- package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/form.d.ts +0 -24
- package/dist/v2/shadcn/components/ui/form.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/hover-card.d.ts +0 -7
- package/dist/v2/shadcn/components/ui/hover-card.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/input-otp.d.ts +0 -35
- package/dist/v2/shadcn/components/ui/input-otp.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/input.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/input.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/label.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/label.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/menubar.d.ts +0 -34
- package/dist/v2/shadcn/components/ui/menubar.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/navigation-menu.d.ts +0 -13
- package/dist/v2/shadcn/components/ui/navigation-menu.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/pagination.d.ts +0 -29
- package/dist/v2/shadcn/components/ui/pagination.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/popover.d.ts +0 -7
- package/dist/v2/shadcn/components/ui/popover.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/progress.d.ts +0 -5
- package/dist/v2/shadcn/components/ui/progress.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/radio-card.d.ts +0 -12
- package/dist/v2/shadcn/components/ui/radio-card.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/radio-group.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/radio-group.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/scroll-area.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/scroll-area.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/select.d.ts +0 -14
- package/dist/v2/shadcn/components/ui/select.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/separator.d.ts +0 -5
- package/dist/v2/shadcn/components/ui/separator.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/sheet.d.ts +0 -26
- package/dist/v2/shadcn/components/ui/sheet.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/sidebar.d.ts +0 -67
- package/dist/v2/shadcn/components/ui/sidebar.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/skeleton.d.ts +0 -3
- package/dist/v2/shadcn/components/ui/skeleton.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/slider.d.ts +0 -5
- package/dist/v2/shadcn/components/ui/slider.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/switch.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/switch.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/switch.js +0 -115
- package/dist/v2/shadcn/components/ui/switch.scss.js +0 -6
- package/dist/v2/shadcn/components/ui/table-pagination.d.ts +0 -11
- package/dist/v2/shadcn/components/ui/table-pagination.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/table.d.ts +0 -11
- package/dist/v2/shadcn/components/ui/table.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/tabs.d.ts +0 -8
- package/dist/v2/shadcn/components/ui/tabs.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/textarea.d.ts +0 -6
- package/dist/v2/shadcn/components/ui/textarea.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/toast.d.ts +0 -16
- package/dist/v2/shadcn/components/ui/toast.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/toaster.d.ts +0 -2
- package/dist/v2/shadcn/components/ui/toaster.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/toggle-group.d.ts +0 -13
- package/dist/v2/shadcn/components/ui/toggle-group.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/toggle.d.ts +0 -13
- package/dist/v2/shadcn/components/ui/toggle.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/tooltip.d.ts +0 -8
- package/dist/v2/shadcn/components/ui/tooltip.d.ts.map +0 -1
- package/dist/v2/shadcn/components/ui/use-toast.d.ts +0 -3
- package/dist/v2/shadcn/components/ui/use-toast.d.ts.map +0 -1
- package/dist/v2/shadcn/hooks/use-mobile.d.ts +0 -2
- package/dist/v2/shadcn/hooks/use-mobile.d.ts.map +0 -1
- package/dist/v2/shadcn/hooks/use-toast.d.ts +0 -45
- package/dist/v2/shadcn/hooks/use-toast.d.ts.map +0 -1
- package/dist/v2/shadcn/index.d.ts +0 -20
- package/dist/v2/shadcn/index.d.ts.map +0 -1
- package/dist/v2/shadcn/lib/utils.d.ts +0 -3
- package/dist/v2/shadcn/lib/utils.d.ts.map +0 -1
- package/dist/v2/shadcn/lib/utils.js +0 -11
- package/dist/v2/shadcn/styles/globals.css +0 -112
- package/src/v2/shadcn/_reference/AccountManagerCard.tsx +0 -45
- package/src/v2/shadcn/_reference/AffiliatesTable.tsx +0 -178
- package/src/v2/shadcn/_reference/AuditArchive.tsx +0 -165
- package/src/v2/shadcn/_reference/AuditContent.tsx +0 -270
- package/src/v2/shadcn/_reference/AutomationsGeneralSettings.tsx +0 -251
- package/src/v2/shadcn/_reference/AvatarUpload.tsx +0 -150
- package/src/v2/shadcn/_reference/BookingsSummaryCard.tsx +0 -268
- package/src/v2/shadcn/_reference/CodeCleanUpAudit.tsx +0 -274
- package/src/v2/shadcn/_reference/CompaniesTable.tsx +0 -387
- package/src/v2/shadcn/_reference/ComponentAudit.tsx +0 -239
- package/src/v2/shadcn/_reference/ConfigureSettingsCard.tsx +0 -95
- package/src/v2/shadcn/_reference/CustomerCard.tsx +0 -155
- package/src/v2/shadcn/_reference/DashboardCards.tsx +0 -50
- package/src/v2/shadcn/_reference/DashboardFooter.tsx +0 -18
- package/src/v2/shadcn/_reference/DiarySettings.tsx +0 -187
- package/src/v2/shadcn/_reference/DiaryView.tsx +0 -998
- package/src/v2/shadcn/_reference/EmptyState.tsx +0 -76
- package/src/v2/shadcn/_reference/EntityInfoCard.tsx +0 -48
- package/src/v2/shadcn/_reference/ExistingUserAssignments.tsx +0 -131
- package/src/v2/shadcn/_reference/FeatureToggle.tsx +0 -72
- package/src/v2/shadcn/_reference/FlowCard.tsx +0 -170
- package/src/v2/shadcn/_reference/FlowsContent.tsx +0 -688
- package/src/v2/shadcn/_reference/FlowsGeneralSettings.tsx +0 -27
- package/src/v2/shadcn/_reference/GeneralSettings.tsx +0 -33
- package/src/v2/shadcn/_reference/InventoryGeneralSettings.tsx +0 -82
- package/src/v2/shadcn/_reference/LanguageSelector.tsx +0 -97
- package/src/v2/shadcn/_reference/LoadingScreen.tsx +0 -25
- package/src/v2/shadcn/_reference/LoadingSpinner.tsx +0 -41
- package/src/v2/shadcn/_reference/ManagedClientsList.tsx +0 -121
- package/src/v2/shadcn/_reference/NPSScore.tsx +0 -379
- package/src/v2/shadcn/_reference/NPSSummaryCard.tsx +0 -181
- package/src/v2/shadcn/_reference/NotificationBanner.tsx +0 -129
- package/src/v2/shadcn/_reference/NotificationPanel.tsx +0 -208
- package/src/v2/shadcn/_reference/OnlineUsersCard.tsx +0 -73
- package/src/v2/shadcn/_reference/ProtectedRoute.tsx +0 -39
- package/src/v2/shadcn/_reference/ProvidersTable.tsx +0 -353
- package/src/v2/shadcn/_reference/QuickAddPanel.tsx +0 -1057
- package/src/v2/shadcn/_reference/QuickFilters.tsx +0 -112
- package/src/v2/shadcn/_reference/ScheduleView.tsx +0 -410
- package/src/v2/shadcn/_reference/ScrollToTop.tsx +0 -14
- package/src/v2/shadcn/_reference/SecondaryNav.tsx +0 -50
- package/src/v2/shadcn/_reference/SecuritySettings.tsx +0 -258
- package/src/v2/shadcn/_reference/SessionDetailView.tsx +0 -294
- package/src/v2/shadcn/_reference/Sidebar.tsx +0 -14
- package/src/v2/shadcn/_reference/SidebarAwareLayout.tsx +0 -30
- package/src/v2/shadcn/_reference/SidebarLabelCustomization.tsx +0 -285
- package/src/v2/shadcn/_reference/SimulationBanner.tsx +0 -57
- package/src/v2/shadcn/_reference/SortControls.tsx +0 -65
- package/src/v2/shadcn/_reference/StatusBadge.tsx +0 -49
- package/src/v2/shadcn/_reference/StyleGuideContent.tsx +0 -331
- package/src/v2/shadcn/_reference/TableActionMenu.tsx +0 -126
- package/src/v2/shadcn/_reference/ThemeProvider.tsx +0 -119
- package/src/v2/shadcn/_reference/ThemeSettings.tsx +0 -73
- package/src/v2/shadcn/_reference/TopNavigation.tsx +0 -332
- package/src/v2/shadcn/_reference/UserActivityHistory.tsx +0 -209
- package/src/v2/shadcn/_reference/UserLanguageSettings.tsx +0 -94
- package/src/v2/shadcn/_reference/UserPanel.tsx +0 -472
- package/src/v2/shadcn/_reference/UsersTable.tsx +0 -1023
- package/src/v2/shadcn/_reference/WaiverForm.tsx +0 -301
- package/src/v2/shadcn/_reference/WaiversGeneralSettings.tsx +0 -46
- package/src/v2/shadcn/_reference/WaiversTable.tsx +0 -290
- package/src/v2/shadcn/_reference/WaiversTemplatesSettings.tsx +0 -416
- package/src/v2/shadcn/_reference/ai/AIChatPanel.tsx +0 -313
- package/src/v2/shadcn/_reference/ai/AIChatSearchBar.tsx +0 -36
- package/src/v2/shadcn/_reference/ai/ChatInteractiveBlock.tsx +0 -298
- package/src/v2/shadcn/_reference/ai/ChatMessageContent.tsx +0 -40
- package/src/v2/shadcn/_reference/ai/parseInteractiveBlocks.ts +0 -142
- package/src/v2/shadcn/_reference/auth/AuthLayout.tsx +0 -55
- package/src/v2/shadcn/_reference/auth/CreatePasswordForm.tsx +0 -285
- package/src/v2/shadcn/_reference/auth/CreatePasswordPanel.tsx +0 -20
- package/src/v2/shadcn/_reference/auth/LoginFooter.tsx +0 -14
- package/src/v2/shadcn/_reference/auth/LoginForm.tsx +0 -205
- package/src/v2/shadcn/_reference/auth/LoginPanel.tsx +0 -41
- package/src/v2/shadcn/_reference/auth/ResetPasswordForm.tsx +0 -102
- package/src/v2/shadcn/_reference/auth/ResetPasswordPanel.tsx +0 -20
- package/src/v2/shadcn/_reference/auth/VerifyEmailForm.tsx +0 -95
- package/src/v2/shadcn/_reference/auth/VerifyEmailPanel.tsx +0 -20
- package/src/v2/shadcn/_reference/email/EmailAttachment.tsx +0 -119
- package/src/v2/shadcn/_reference/email/EmailAutomation.tsx +0 -92
- package/src/v2/shadcn/_reference/email/EmailPlaceholders.tsx +0 -64
- package/src/v2/shadcn/_reference/email/UnlayerEmailEditor.tsx +0 -41
- package/src/v2/shadcn/_reference/email/emailTemplateData.ts +0 -53
- package/src/v2/shadcn/_reference/emptyStateIcons.tsx +0 -103
- package/src/v2/shadcn/_reference/games/MazeGame.tsx +0 -394
- package/src/v2/shadcn/_reference/games/RunnerGame.tsx +0 -497
- package/src/v2/shadcn/_reference/logos/BookedLogoFull.tsx +0 -36
- package/src/v2/shadcn/_reference/logos/BookedLogoMark.tsx +0 -31
- package/src/v2/shadcn/_reference/logos/BookedLogoNew.tsx +0 -36
- package/src/v2/shadcn/_reference/pricing/DynamicPricingRulesEditor.tsx +0 -401
- package/src/v2/shadcn/_reference/pricing/DynamicPricingTierCard.tsx +0 -77
- package/src/v2/shadcn/_reference/pricing/DynamicPricingTiersList.tsx +0 -218
- package/src/v2/shadcn/_reference/pricing/PricingCalendar.tsx +0 -810
- package/src/v2/shadcn/_reference/pricing/PricingPeriodCard.tsx +0 -152
- package/src/v2/shadcn/_reference/pricing/PricingPeriodForm.tsx +0 -377
- package/src/v2/shadcn/_reference/pricing/PricingPeriodsList.tsx +0 -213
- package/src/v2/shadcn/_reference/pricing/getRuleSummary.ts +0 -39
- package/src/v2/shadcn/_reference/products/AvailabilityRulesSection.tsx +0 -184
- package/src/v2/shadcn/_reference/products/AvailabilitySection.tsx +0 -677
- package/src/v2/shadcn/_reference/products/BookingTypeConfigOptions.tsx +0 -40
- package/src/v2/shadcn/_reference/products/CapacityPeriodsSection.tsx +0 -238
- package/src/v2/shadcn/_reference/products/DynamicPricingTiersSection.tsx +0 -131
- package/src/v2/shadcn/_reference/products/GiftCardOrdersTab.tsx +0 -192
- package/src/v2/shadcn/_reference/products/GiftCardSettings.tsx +0 -342
- package/src/v2/shadcn/_reference/products/PackageProductsSection.tsx +0 -322
- package/src/v2/shadcn/_reference/products/PricingSection.tsx +0 -173
- package/src/v2/shadcn/_reference/products/ProductTypeFields.tsx +0 -353
- package/src/v2/shadcn/_reference/products/ProductTypeIcon.tsx +0 -95
- package/src/v2/shadcn/_reference/products/VariablePricingSection.tsx +0 -140
- package/src/v2/shadcn/_reference/products/productTypeConfig.ts +0 -182
- package/src/v2/shadcn/_reference/shared/BackButton.tsx +0 -50
- package/src/v2/shadcn/_reference/shared/CancelConfirmationDialog.tsx +0 -18
- package/src/v2/shadcn/_reference/shared/ConfirmationDialog.tsx +0 -136
- package/src/v2/shadcn/_reference/shared/DeleteConfirmationDialog.tsx +0 -18
- package/src/v2/shadcn/_reference/shared/DeleteEntityPage.tsx +0 -221
- package/src/v2/shadcn/_reference/shared/SidebarIcons.tsx +0 -108
- package/src/v2/shadcn/_reference/shared/UnifiedSidebar.tsx +0 -722
- package/src/v2/shadcn/_reference/tables/BulkActionsBar.tsx +0 -68
- package/src/v2/shadcn/_reference/tables/DataTable.tsx +0 -221
- package/src/v2/shadcn/_reference/tables/TableControls.tsx +0 -94
- package/src/v2/shadcn/_reference/tables/index.ts +0 -3
- package/src/v2/shadcn/_reference/tables/types.ts +0 -79
- package/src/v2/shadcn/_reference/zones/LegacyZoneSettings.tsx +0 -299
- package/src/v2/shadcn/components/ui/accordion.stories.tsx +0 -63
- package/src/v2/shadcn/components/ui/accordion.tsx +0 -52
- package/src/v2/shadcn/components/ui/alert-dialog.stories.tsx +0 -44
- package/src/v2/shadcn/components/ui/alert-dialog.tsx +0 -104
- package/src/v2/shadcn/components/ui/alert.stories.tsx +0 -44
- package/src/v2/shadcn/components/ui/alert.tsx +0 -43
- package/src/v2/shadcn/components/ui/aspect-ratio.stories.tsx +0 -46
- package/src/v2/shadcn/components/ui/aspect-ratio.tsx +0 -5
- package/src/v2/shadcn/components/ui/avatar.stories.tsx +0 -39
- package/src/v2/shadcn/components/ui/avatar.tsx +0 -38
- package/src/v2/shadcn/components/ui/badge.stories.tsx +0 -17
- package/src/v2/shadcn/components/ui/badge.tsx +0 -30
- package/src/v2/shadcn/components/ui/breadcrumb.stories.tsx +0 -91
- package/src/v2/shadcn/components/ui/breadcrumb.tsx +0 -90
- package/src/v2/shadcn/components/ui/button.stories.tsx +0 -20
- package/src/v2/shadcn/components/ui/button.tsx +0 -60
- package/src/v2/shadcn/components/ui/calendar.stories.tsx +0 -61
- package/src/v2/shadcn/components/ui/calendar.tsx +0 -54
- package/src/v2/shadcn/components/ui/card.stories.tsx +0 -37
- package/src/v2/shadcn/components/ui/card.tsx +0 -43
- package/src/v2/shadcn/components/ui/carousel.stories.tsx +0 -92
- package/src/v2/shadcn/components/ui/carousel.tsx +0 -224
- package/src/v2/shadcn/components/ui/checkbox.scss +0 -38
- package/src/v2/shadcn/components/ui/checkbox.stories.tsx +0 -23
- package/src/v2/shadcn/components/ui/checkbox.tsx +0 -24
- package/src/v2/shadcn/components/ui/collapsible.stories.tsx +0 -59
- package/src/v2/shadcn/components/ui/collapsible.tsx +0 -9
- package/src/v2/shadcn/components/ui/command.stories.tsx +0 -70
- package/src/v2/shadcn/components/ui/command.tsx +0 -132
- package/src/v2/shadcn/components/ui/context-menu.stories.tsx +0 -72
- package/src/v2/shadcn/components/ui/context-menu.tsx +0 -178
- package/src/v2/shadcn/components/ui/dialog.stories.tsx +0 -67
- package/src/v2/shadcn/components/ui/dialog.tsx +0 -95
- package/src/v2/shadcn/components/ui/drawer.stories.tsx +0 -50
- package/src/v2/shadcn/components/ui/drawer.tsx +0 -87
- package/src/v2/shadcn/components/ui/dropdown-menu.stories.tsx +0 -73
- package/src/v2/shadcn/components/ui/dropdown-menu.tsx +0 -179
- package/src/v2/shadcn/components/ui/form.stories.tsx +0 -105
- package/src/v2/shadcn/components/ui/form.tsx +0 -129
- package/src/v2/shadcn/components/ui/hover-card.stories.tsx +0 -35
- package/src/v2/shadcn/components/ui/hover-card.tsx +0 -27
- package/src/v2/shadcn/components/ui/input-otp.stories.tsx +0 -72
- package/src/v2/shadcn/components/ui/input-otp.tsx +0 -61
- package/src/v2/shadcn/components/ui/input.stories.tsx +0 -16
- package/src/v2/shadcn/components/ui/input.tsx +0 -25
- package/src/v2/shadcn/components/ui/label.stories.tsx +0 -13
- package/src/v2/shadcn/components/ui/label.tsx +0 -17
- package/src/v2/shadcn/components/ui/menubar.stories.tsx +0 -86
- package/src/v2/shadcn/components/ui/menubar.tsx +0 -207
- package/src/v2/shadcn/components/ui/navigation-menu.stories.tsx +0 -68
- package/src/v2/shadcn/components/ui/navigation-menu.tsx +0 -120
- package/src/v2/shadcn/components/ui/pagination.stories.tsx +0 -78
- package/src/v2/shadcn/components/ui/pagination.tsx +0 -81
- package/src/v2/shadcn/components/ui/popover.stories.tsx +0 -44
- package/src/v2/shadcn/components/ui/popover.tsx +0 -29
- package/src/v2/shadcn/components/ui/progress.stories.tsx +0 -17
- package/src/v2/shadcn/components/ui/progress.tsx +0 -23
- package/src/v2/shadcn/components/ui/radio-card.stories.tsx +0 -68
- package/src/v2/shadcn/components/ui/radio-card.tsx +0 -52
- package/src/v2/shadcn/components/ui/radio-group.stories.tsx +0 -77
- package/src/v2/shadcn/components/ui/radio-group.tsx +0 -35
- package/src/v2/shadcn/components/ui/scroll-area.stories.tsx +0 -56
- package/src/v2/shadcn/components/ui/scroll-area.tsx +0 -38
- package/src/v2/shadcn/components/ui/select.stories.tsx +0 -60
- package/src/v2/shadcn/components/ui/select.tsx +0 -148
- package/src/v2/shadcn/components/ui/separator.stories.tsx +0 -30
- package/src/v2/shadcn/components/ui/separator.tsx +0 -20
- package/src/v2/shadcn/components/ui/sheet.stories.tsx +0 -115
- package/src/v2/shadcn/components/ui/sheet.tsx +0 -107
- package/src/v2/shadcn/components/ui/sidebar.stories.tsx +0 -167
- package/src/v2/shadcn/components/ui/sidebar.tsx +0 -637
- package/src/v2/shadcn/components/ui/skeleton.stories.tsx +0 -36
- package/src/v2/shadcn/components/ui/skeleton.tsx +0 -7
- package/src/v2/shadcn/components/ui/slider.stories.tsx +0 -16
- package/src/v2/shadcn/components/ui/slider.tsx +0 -23
- package/src/v2/shadcn/components/ui/switch.scss +0 -63
- package/src/v2/shadcn/components/ui/switch.stories.tsx +0 -23
- package/src/v2/shadcn/components/ui/switch.tsx +0 -24
- package/src/v2/shadcn/components/ui/table-pagination.stories.tsx +0 -81
- package/src/v2/shadcn/components/ui/table-pagination.tsx +0 -61
- package/src/v2/shadcn/components/ui/table.stories.tsx +0 -40
- package/src/v2/shadcn/components/ui/table.tsx +0 -72
- package/src/v2/shadcn/components/ui/tabs.stories.tsx +0 -85
- package/src/v2/shadcn/components/ui/tabs.tsx +0 -53
- package/src/v2/shadcn/components/ui/textarea.stories.tsx +0 -15
- package/src/v2/shadcn/components/ui/textarea.tsx +0 -21
- package/src/v2/shadcn/components/ui/toast.stories.tsx +0 -77
- package/src/v2/shadcn/components/ui/toast.tsx +0 -111
- package/src/v2/shadcn/components/ui/toaster.stories.tsx +0 -46
- package/src/v2/shadcn/components/ui/toaster.tsx +0 -24
- package/src/v2/shadcn/components/ui/toggle-group.stories.tsx +0 -95
- package/src/v2/shadcn/components/ui/toggle-group.tsx +0 -49
- package/src/v2/shadcn/components/ui/toggle.stories.tsx +0 -18
- package/src/v2/shadcn/components/ui/toggle.tsx +0 -37
- package/src/v2/shadcn/components/ui/tooltip.stories.tsx +0 -57
- package/src/v2/shadcn/components/ui/tooltip.tsx +0 -28
- package/src/v2/shadcn/components/ui/use-toast.ts +0 -3
- package/src/v2/shadcn/hooks/use-mobile.tsx +0 -19
- package/src/v2/shadcn/hooks/use-toast.ts +0 -184
- package/src/v2/shadcn/index.ts +0 -76
- package/src/v2/shadcn/lib/utils.ts +0 -6
- package/src/v2/shadcn/styles/globals.css +0 -112
|
@@ -1,677 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import { Button } from '../ui/button';
|
|
3
|
-
import { Input } from '../ui/input';
|
|
4
|
-
import { Label } from '../ui/label';
|
|
5
|
-
import { RadioGroup, RadioGroupItem } from '../ui/radio-group';
|
|
6
|
-
import { Switch } from '../ui/switch';
|
|
7
|
-
import { IconPlus, IconCross } from '../../../icons';
|
|
8
|
-
import { supabase } from '@/integrations/supabase/client';
|
|
9
|
-
|
|
10
|
-
interface OpeningHours {
|
|
11
|
-
day_of_week: number;
|
|
12
|
-
is_open: boolean;
|
|
13
|
-
open_time: string;
|
|
14
|
-
close_time: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Database uses 0 = Sunday, 1 = Monday, etc. (JavaScript Date.getDay() convention)
|
|
18
|
-
const DAYS_OF_WEEK = [
|
|
19
|
-
{ value: 1, label: 'Monday', short: 'Mon' },
|
|
20
|
-
{ value: 2, label: 'Tuesday', short: 'Tue' },
|
|
21
|
-
{ value: 3, label: 'Wednesday', short: 'Wed' },
|
|
22
|
-
{ value: 4, label: 'Thursday', short: 'Thu' },
|
|
23
|
-
{ value: 5, label: 'Friday', short: 'Fri' },
|
|
24
|
-
{ value: 6, label: 'Saturday', short: 'Sat' },
|
|
25
|
-
{ value: 0, label: 'Sunday', short: 'Sun' },
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
const INCREMENT_OPTIONS = [
|
|
29
|
-
{ value: 5, label: '5 min' },
|
|
30
|
-
{ value: 10, label: '10 min' },
|
|
31
|
-
{ value: 15, label: '15 min' },
|
|
32
|
-
{ value: 20, label: '20 min' },
|
|
33
|
-
{ value: 30, label: '30 min' },
|
|
34
|
-
{ value: 45, label: '45 min' },
|
|
35
|
-
{ value: 60, label: '1 hour' },
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
// Default opening time if no provider opening hours available
|
|
39
|
-
const DEFAULT_OPENING_TIME = '09:00';
|
|
40
|
-
|
|
41
|
-
export interface DayAvailability {
|
|
42
|
-
enabled: boolean;
|
|
43
|
-
times: string[]; // For fixed sessions
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface AvailabilityData {
|
|
47
|
-
availability_type: 'fixed_sessions' | 'incremental' | '';
|
|
48
|
-
is_daily_availability: boolean;
|
|
49
|
-
increment_minutes: number;
|
|
50
|
-
// For daily mode (same times every day)
|
|
51
|
-
daily_times: string[];
|
|
52
|
-
// For per-day mode
|
|
53
|
-
day_availability: Record<number, DayAvailability>;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
interface AvailabilitySectionProps {
|
|
57
|
-
values: Record<string, any>;
|
|
58
|
-
onChange: (field: string, value: any) => void;
|
|
59
|
-
providerId?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Helper function to convert time string to minutes from midnight
|
|
63
|
-
const timeToMinutes = (time: string): number => {
|
|
64
|
-
const [hours, minutes] = time.split(':').map(Number);
|
|
65
|
-
return hours * 60 + minutes;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// Helper function to add minutes to a time string (HH:MM format)
|
|
69
|
-
const addMinutesToTime = (time: string, minutesToAdd: number): string => {
|
|
70
|
-
const [hours, minutes] = time.split(':').map(Number);
|
|
71
|
-
const totalMinutes = hours * 60 + minutes + minutesToAdd;
|
|
72
|
-
const newHours = Math.floor(totalMinutes / 60) % 24;
|
|
73
|
-
const newMinutes = totalMinutes % 60;
|
|
74
|
-
return `${String(newHours).padStart(2, '0')}:${String(newMinutes).padStart(2, '0')}`;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// Get duration in minutes from timing fields
|
|
78
|
-
const getDurationMinutes = (values: Record<string, any>): number => {
|
|
79
|
-
// Prefer persisted duration (minutes) when available
|
|
80
|
-
if (typeof values.duration === 'number' && Number.isFinite(values.duration) && values.duration > 0) {
|
|
81
|
-
return values.duration;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const timingType = values.timing_type;
|
|
85
|
-
|
|
86
|
-
if (timingType === 'session_based') {
|
|
87
|
-
const hours = values.session_duration_hours || 0;
|
|
88
|
-
const minutes = values.session_duration_minutes || 0;
|
|
89
|
-
return hours * 60 + minutes;
|
|
90
|
-
} else if (timingType === 'timed_per_person') {
|
|
91
|
-
const hours = values.time_per_person_hours || 0;
|
|
92
|
-
const minutes = values.time_per_person_minutes || 0;
|
|
93
|
-
return hours * 60 + minutes;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Default to 1 hour if no duration set
|
|
97
|
-
return 60;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// Format duration for display
|
|
101
|
-
const formatDuration = (minutes: number): string => {
|
|
102
|
-
if (minutes < 60) {
|
|
103
|
-
return `${minutes} min`;
|
|
104
|
-
}
|
|
105
|
-
const hours = Math.floor(minutes / 60);
|
|
106
|
-
const mins = minutes % 60;
|
|
107
|
-
if (mins === 0) {
|
|
108
|
-
return `${hours} hour${hours > 1 ? 's' : ''}`;
|
|
109
|
-
}
|
|
110
|
-
return `${hours}h ${mins}m`;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
// Format time for display (remove seconds if present)
|
|
114
|
-
const formatTimeForDisplay = (time: string): string => {
|
|
115
|
-
if (!time) return DEFAULT_OPENING_TIME;
|
|
116
|
-
// Handle HH:MM:SS format from database
|
|
117
|
-
return time.substring(0, 5);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const AvailabilitySection: React.FC<AvailabilitySectionProps> = ({
|
|
121
|
-
values,
|
|
122
|
-
onChange,
|
|
123
|
-
providerId,
|
|
124
|
-
}) => {
|
|
125
|
-
const [openingHours, setOpeningHours] = useState<OpeningHours[]>([]);
|
|
126
|
-
const [loadingHours, setLoadingHours] = useState(false);
|
|
127
|
-
|
|
128
|
-
// Fetch provider opening hours
|
|
129
|
-
useEffect(() => {
|
|
130
|
-
const fetchOpeningHours = async () => {
|
|
131
|
-
if (!providerId) return;
|
|
132
|
-
|
|
133
|
-
setLoadingHours(true);
|
|
134
|
-
try {
|
|
135
|
-
const { data, error } = await supabase
|
|
136
|
-
.from('provider_opening_hours')
|
|
137
|
-
.select('day_of_week, is_open, open_time, close_time')
|
|
138
|
-
.eq('provider_id', providerId)
|
|
139
|
-
.order('day_of_week');
|
|
140
|
-
|
|
141
|
-
if (error) {
|
|
142
|
-
console.error('Error fetching opening hours:', error);
|
|
143
|
-
} else if (data) {
|
|
144
|
-
setOpeningHours(data);
|
|
145
|
-
}
|
|
146
|
-
} catch (err) {
|
|
147
|
-
console.error('Error fetching opening hours:', err);
|
|
148
|
-
} finally {
|
|
149
|
-
setLoadingHours(false);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
fetchOpeningHours();
|
|
154
|
-
}, [providerId]);
|
|
155
|
-
|
|
156
|
-
// Get opening hours for a specific day
|
|
157
|
-
const getOpeningHoursForDay = (dayValue: number): OpeningHours | undefined => {
|
|
158
|
-
return openingHours.find(h => h.day_of_week === dayValue);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
// Check if venue is open on a specific day
|
|
162
|
-
const isVenueOpenOnDay = (dayValue: number): boolean => {
|
|
163
|
-
const hours = getOpeningHoursForDay(dayValue);
|
|
164
|
-
// If no hours data, assume open (fallback)
|
|
165
|
-
if (!hours) return true;
|
|
166
|
-
return hours.is_open;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// Get default first session time for a day (venue opening time)
|
|
170
|
-
const getDefaultOpeningTimeForDay = (dayValue: number): string => {
|
|
171
|
-
const hours = getOpeningHoursForDay(dayValue);
|
|
172
|
-
if (hours?.open_time) {
|
|
173
|
-
return formatTimeForDisplay(hours.open_time);
|
|
174
|
-
}
|
|
175
|
-
return DEFAULT_OPENING_TIME;
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
// Get earliest opening time across all open days (for daily mode)
|
|
179
|
-
const getEarliestOpeningTime = (): string => {
|
|
180
|
-
const openDays = openingHours.filter(h => h.is_open);
|
|
181
|
-
if (openDays.length === 0) return DEFAULT_OPENING_TIME;
|
|
182
|
-
|
|
183
|
-
const times = openDays.map(h => formatTimeForDisplay(h.open_time));
|
|
184
|
-
return times.sort()[0] || DEFAULT_OPENING_TIME;
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
// Get latest closing time across all open days (for daily mode validation)
|
|
188
|
-
const getLatestClosingTime = (): string | null => {
|
|
189
|
-
const openDays = openingHours.filter(h => h.is_open);
|
|
190
|
-
if (openDays.length === 0) return null;
|
|
191
|
-
|
|
192
|
-
const times = openDays.map(h => formatTimeForDisplay(h.close_time));
|
|
193
|
-
// Sort descending to get latest
|
|
194
|
-
return times.sort().reverse()[0] || null;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// Check if a session exceeds closing time for daily mode - returns affected days info
|
|
198
|
-
const getSessionIssuesDaily = (startTime: string): {
|
|
199
|
-
exceedsClosing: boolean;
|
|
200
|
-
startsAfterClose: boolean;
|
|
201
|
-
beforeOpening: boolean;
|
|
202
|
-
affectedDays: { day: string; issue: 'before_open' | 'after_close' | 'starts_after_close'; time: string }[];
|
|
203
|
-
} => {
|
|
204
|
-
const startMinutes = timeToMinutes(startTime);
|
|
205
|
-
const sessionEndTime = addMinutesToTime(startTime, durationMinutes);
|
|
206
|
-
const sessionEndMinutes = timeToMinutes(sessionEndTime);
|
|
207
|
-
|
|
208
|
-
const affectedDays: { day: string; issue: 'before_open' | 'after_close' | 'starts_after_close'; time: string }[] = [];
|
|
209
|
-
|
|
210
|
-
// Check each open day
|
|
211
|
-
const openDays = openingHours.filter(h => h.is_open);
|
|
212
|
-
|
|
213
|
-
for (const hours of openDays) {
|
|
214
|
-
const dayInfo = DAYS_OF_WEEK.find(d => d.value === hours.day_of_week);
|
|
215
|
-
if (!dayInfo) continue;
|
|
216
|
-
|
|
217
|
-
const openTime = formatTimeForDisplay(hours.open_time);
|
|
218
|
-
const closeTime = formatTimeForDisplay(hours.close_time);
|
|
219
|
-
const openMinutes = timeToMinutes(openTime);
|
|
220
|
-
const closeMinutes = timeToMinutes(closeTime);
|
|
221
|
-
|
|
222
|
-
// Check if session starts before opening
|
|
223
|
-
if (startMinutes < openMinutes) {
|
|
224
|
-
affectedDays.push({ day: dayInfo.short, issue: 'before_open', time: openTime });
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Check if session starts after closing (completely outside hours)
|
|
228
|
-
if (startMinutes >= closeMinutes) {
|
|
229
|
-
affectedDays.push({ day: dayInfo.short, issue: 'starts_after_close', time: closeTime });
|
|
230
|
-
}
|
|
231
|
-
// Check if session ends after closing (but starts within hours)
|
|
232
|
-
else if (sessionEndMinutes > closeMinutes && !(sessionEndMinutes < startMinutes)) {
|
|
233
|
-
affectedDays.push({ day: dayInfo.short, issue: 'after_close', time: closeTime });
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const beforeOpeningDays = affectedDays.filter(d => d.issue === 'before_open');
|
|
238
|
-
const startsAfterCloseDays = affectedDays.filter(d => d.issue === 'starts_after_close');
|
|
239
|
-
const exceedsClosingDays = affectedDays.filter(d => d.issue === 'after_close');
|
|
240
|
-
|
|
241
|
-
return {
|
|
242
|
-
exceedsClosing: exceedsClosingDays.length > 0,
|
|
243
|
-
startsAfterClose: startsAfterCloseDays.length > 0,
|
|
244
|
-
beforeOpening: beforeOpeningDays.length > 0,
|
|
245
|
-
affectedDays
|
|
246
|
-
};
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
// Check if a session exceeds closing time for a specific day
|
|
250
|
-
const getSessionIssuesForDay = (startTime: string, dayValue: number): {
|
|
251
|
-
exceedsClosing: boolean;
|
|
252
|
-
startsAfterClose: boolean;
|
|
253
|
-
beforeOpening: boolean;
|
|
254
|
-
openTime: string;
|
|
255
|
-
closeTime: string;
|
|
256
|
-
} => {
|
|
257
|
-
const hours = getOpeningHoursForDay(dayValue);
|
|
258
|
-
if (!hours || !hours.is_open) {
|
|
259
|
-
return { exceedsClosing: false, startsAfterClose: false, beforeOpening: false, openTime: '', closeTime: '' };
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const openTime = formatTimeForDisplay(hours.open_time);
|
|
263
|
-
const closeTime = formatTimeForDisplay(hours.close_time);
|
|
264
|
-
const startMinutes = timeToMinutes(startTime);
|
|
265
|
-
const openMinutes = timeToMinutes(openTime);
|
|
266
|
-
const closeMinutes = timeToMinutes(closeTime);
|
|
267
|
-
|
|
268
|
-
const sessionEndTime = addMinutesToTime(startTime, durationMinutes);
|
|
269
|
-
const sessionEndMinutes = timeToMinutes(sessionEndTime);
|
|
270
|
-
|
|
271
|
-
// Session starts before opening
|
|
272
|
-
const beforeOpening = startMinutes < openMinutes;
|
|
273
|
-
|
|
274
|
-
// Session starts after closing (completely outside hours)
|
|
275
|
-
const startsAfterClose = startMinutes >= closeMinutes;
|
|
276
|
-
|
|
277
|
-
// Session ends after closing (but starts within hours) - handle overnight
|
|
278
|
-
const exceedsClosing = !startsAfterClose && sessionEndMinutes > closeMinutes && !(sessionEndMinutes < startMinutes);
|
|
279
|
-
|
|
280
|
-
return { exceedsClosing, startsAfterClose, beforeOpening, openTime, closeTime };
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const availabilityType = values.availability_type || '';
|
|
285
|
-
const isDaily = values.is_daily_availability !== false; // Default to true
|
|
286
|
-
const incrementMinutes = values.increment_minutes || 15;
|
|
287
|
-
const dailyTimes: string[] = values.daily_times || [];
|
|
288
|
-
const dayAvailability: Record<number, DayAvailability> = values.day_availability ||
|
|
289
|
-
DAYS_OF_WEEK.reduce((acc, day) => ({
|
|
290
|
-
...acc,
|
|
291
|
-
[day.value]: { enabled: isVenueOpenOnDay(day.value), times: [] }
|
|
292
|
-
}), {});
|
|
293
|
-
|
|
294
|
-
// Get duration from timing settings
|
|
295
|
-
const durationMinutes = getDurationMinutes(values);
|
|
296
|
-
|
|
297
|
-
const handleAvailabilityTypeChange = (type: string) => {
|
|
298
|
-
onChange('availability_type', type);
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
const handleDailyToggle = (checked: boolean) => {
|
|
302
|
-
onChange('is_daily_availability', checked);
|
|
303
|
-
|
|
304
|
-
// When switching to per-day mode, initialize day availability based on opening hours
|
|
305
|
-
if (!checked) {
|
|
306
|
-
const initialDayAvailability = DAYS_OF_WEEK.reduce((acc, day) => ({
|
|
307
|
-
...acc,
|
|
308
|
-
[day.value]: {
|
|
309
|
-
enabled: isVenueOpenOnDay(day.value),
|
|
310
|
-
times: []
|
|
311
|
-
}
|
|
312
|
-
}), {});
|
|
313
|
-
onChange('day_availability', initialDayAvailability);
|
|
314
|
-
}
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
const handleIncrementChange = (value: number) => {
|
|
318
|
-
onChange('increment_minutes', value);
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
// Calculate next session time based on last time + duration
|
|
322
|
-
const getNextSessionTime = (existingTimes: string[], dayValue?: number): string => {
|
|
323
|
-
if (existingTimes.length === 0) {
|
|
324
|
-
// First session defaults to opening time
|
|
325
|
-
if (dayValue !== undefined) {
|
|
326
|
-
return getDefaultOpeningTimeForDay(dayValue);
|
|
327
|
-
}
|
|
328
|
-
return getEarliestOpeningTime();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Get the last time and add duration
|
|
332
|
-
const lastTime = existingTimes[existingTimes.length - 1];
|
|
333
|
-
return addMinutesToTime(lastTime, durationMinutes);
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
// Daily times management
|
|
337
|
-
const addDailyTime = () => {
|
|
338
|
-
const nextTime = getNextSessionTime(dailyTimes);
|
|
339
|
-
const newTimes = [...dailyTimes, nextTime];
|
|
340
|
-
onChange('daily_times', newTimes);
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
const updateDailyTime = (index: number, time: string) => {
|
|
344
|
-
const newTimes = [...dailyTimes];
|
|
345
|
-
newTimes[index] = time;
|
|
346
|
-
onChange('daily_times', newTimes);
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
const removeDailyTime = (index: number) => {
|
|
350
|
-
const newTimes = dailyTimes.filter((_, i) => i !== index);
|
|
351
|
-
onChange('daily_times', newTimes);
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
// Per-day times management
|
|
355
|
-
const toggleDayEnabled = (dayValue: number) => {
|
|
356
|
-
// Prevent enabling if venue is closed
|
|
357
|
-
if (!isVenueOpenOnDay(dayValue) && !dayAvailability[dayValue]?.enabled) {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
const newDayAvailability = {
|
|
362
|
-
...dayAvailability,
|
|
363
|
-
[dayValue]: {
|
|
364
|
-
...dayAvailability[dayValue],
|
|
365
|
-
enabled: !dayAvailability[dayValue]?.enabled
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
onChange('day_availability', newDayAvailability);
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
const addDayTime = (dayValue: number) => {
|
|
372
|
-
const currentTimes = dayAvailability[dayValue]?.times || [];
|
|
373
|
-
const nextTime = getNextSessionTime(currentTimes, dayValue);
|
|
374
|
-
const newDayAvailability = {
|
|
375
|
-
...dayAvailability,
|
|
376
|
-
[dayValue]: {
|
|
377
|
-
...dayAvailability[dayValue],
|
|
378
|
-
times: [...currentTimes, nextTime]
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
|
-
onChange('day_availability', newDayAvailability);
|
|
382
|
-
};
|
|
383
|
-
|
|
384
|
-
const updateDayTime = (dayValue: number, index: number, time: string) => {
|
|
385
|
-
const currentTimes = dayAvailability[dayValue]?.times || [];
|
|
386
|
-
const newTimes = [...currentTimes];
|
|
387
|
-
newTimes[index] = time;
|
|
388
|
-
const newDayAvailability = {
|
|
389
|
-
...dayAvailability,
|
|
390
|
-
[dayValue]: {
|
|
391
|
-
...dayAvailability[dayValue],
|
|
392
|
-
times: newTimes
|
|
393
|
-
}
|
|
394
|
-
};
|
|
395
|
-
onChange('day_availability', newDayAvailability);
|
|
396
|
-
};
|
|
397
|
-
|
|
398
|
-
const removeDayTime = (dayValue: number, index: number) => {
|
|
399
|
-
const currentTimes = dayAvailability[dayValue]?.times || [];
|
|
400
|
-
const newDayAvailability = {
|
|
401
|
-
...dayAvailability,
|
|
402
|
-
[dayValue]: {
|
|
403
|
-
...dayAvailability[dayValue],
|
|
404
|
-
times: currentTimes.filter((_, i) => i !== index)
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
onChange('day_availability', newDayAvailability);
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
return (
|
|
411
|
-
<div className="flex flex-col gap-4 pt-4 border-t border-border-primary">
|
|
412
|
-
<h2 className="text-label-primary text-xl font-semibold">Availability</h2>
|
|
413
|
-
|
|
414
|
-
{/* Availability Type Selection */}
|
|
415
|
-
<RadioGroup
|
|
416
|
-
value={availabilityType}
|
|
417
|
-
onValueChange={handleAvailabilityTypeChange}
|
|
418
|
-
className="flex gap-4"
|
|
419
|
-
>
|
|
420
|
-
<label className={`flex items-center gap-2 px-4 py-2 rounded-lg border cursor-pointer transition-colors ${
|
|
421
|
-
availabilityType === 'fixed_sessions'
|
|
422
|
-
? 'border-border-selected bg-surface-action-soft'
|
|
423
|
-
: 'border-border-primary hover:border-border-hover'
|
|
424
|
-
}`}>
|
|
425
|
-
<RadioGroupItem value="fixed_sessions" id="avail-fixed" />
|
|
426
|
-
<span className="text-label-primary">Fixed Sessions</span>
|
|
427
|
-
</label>
|
|
428
|
-
<label className={`flex items-center gap-2 px-4 py-2 rounded-lg border cursor-pointer transition-colors ${
|
|
429
|
-
availabilityType === 'incremental'
|
|
430
|
-
? 'border-border-selected bg-surface-action-soft'
|
|
431
|
-
: 'border-border-primary hover:border-border-hover'
|
|
432
|
-
}`}>
|
|
433
|
-
<RadioGroupItem value="incremental" id="avail-incremental" />
|
|
434
|
-
<span className="text-label-primary">Incremental</span>
|
|
435
|
-
</label>
|
|
436
|
-
</RadioGroup>
|
|
437
|
-
|
|
438
|
-
{/* Show options only when a type is selected */}
|
|
439
|
-
{availabilityType && (
|
|
440
|
-
<>
|
|
441
|
-
{/* Daily Toggle */}
|
|
442
|
-
<div className="flex items-center justify-between py-2">
|
|
443
|
-
<div className="flex flex-col">
|
|
444
|
-
<Label className="text-label-primary">Same times every day</Label>
|
|
445
|
-
<span className="text-label-tertiary text-sm">
|
|
446
|
-
{isDaily ? 'Times apply to all open days' : 'Configure times per day'}
|
|
447
|
-
</span>
|
|
448
|
-
</div>
|
|
449
|
-
<Switch
|
|
450
|
-
checked={isDaily}
|
|
451
|
-
onCheckedChange={handleDailyToggle}
|
|
452
|
-
/>
|
|
453
|
-
</div>
|
|
454
|
-
|
|
455
|
-
{/* Incremental: Show increment selector */}
|
|
456
|
-
{availabilityType === 'incremental' && (
|
|
457
|
-
<div className="flex flex-col gap-2">
|
|
458
|
-
<Label>Time Increment</Label>
|
|
459
|
-
<div className="flex flex-wrap gap-2">
|
|
460
|
-
{INCREMENT_OPTIONS.map((option) => (
|
|
461
|
-
<button
|
|
462
|
-
key={option.value}
|
|
463
|
-
type="button"
|
|
464
|
-
onClick={() => handleIncrementChange(option.value)}
|
|
465
|
-
className={`px-3 py-1.5 rounded-md text-sm transition-colors ${
|
|
466
|
-
incrementMinutes === option.value
|
|
467
|
-
? 'bg-surface-action-soft border border-border-selected text-label-primary'
|
|
468
|
-
: 'bg-surface-secondary border border-border-primary text-label-secondary hover:border-border-hover'
|
|
469
|
-
}`}
|
|
470
|
-
>
|
|
471
|
-
{option.label}
|
|
472
|
-
</button>
|
|
473
|
-
))}
|
|
474
|
-
</div>
|
|
475
|
-
<p className="text-label-tertiary text-sm mt-1">
|
|
476
|
-
Customers can book every {incrementMinutes} minutes during available hours
|
|
477
|
-
</p>
|
|
478
|
-
</div>
|
|
479
|
-
)}
|
|
480
|
-
|
|
481
|
-
{/* Fixed Sessions: Show time inputs */}
|
|
482
|
-
{availabilityType === 'fixed_sessions' && isDaily && (
|
|
483
|
-
<div className="flex flex-col gap-3">
|
|
484
|
-
<div className="flex items-center justify-between">
|
|
485
|
-
<Label>Session Times</Label>
|
|
486
|
-
{durationMinutes > 0 && (
|
|
487
|
-
<span className="text-label-tertiary text-sm">
|
|
488
|
-
Session duration: {formatDuration(durationMinutes)}
|
|
489
|
-
</span>
|
|
490
|
-
)}
|
|
491
|
-
</div>
|
|
492
|
-
<div className="flex flex-col gap-2">
|
|
493
|
-
{dailyTimes.map((time, index) => {
|
|
494
|
-
const issues = getSessionIssuesDaily(time);
|
|
495
|
-
const hasWarning = issues.exceedsClosing || issues.startsAfterClose || issues.beforeOpening;
|
|
496
|
-
|
|
497
|
-
// Group affected days by issue type
|
|
498
|
-
const beforeOpenDays = issues.affectedDays.filter(d => d.issue === 'before_open');
|
|
499
|
-
const startsAfterCloseDays = issues.affectedDays.filter(d => d.issue === 'starts_after_close');
|
|
500
|
-
const endsAfterCloseDays = issues.affectedDays.filter(d => d.issue === 'after_close');
|
|
501
|
-
|
|
502
|
-
return (
|
|
503
|
-
<div key={index} className="flex flex-col gap-1">
|
|
504
|
-
<div className="flex items-center gap-2">
|
|
505
|
-
<Input
|
|
506
|
-
type="time"
|
|
507
|
-
value={time}
|
|
508
|
-
onChange={(e) => updateDailyTime(index, e.target.value)}
|
|
509
|
-
className={`w-32 ${hasWarning ? 'border-border-status-error' : ''}`}
|
|
510
|
-
/>
|
|
511
|
-
<span className={`text-sm ${hasWarning ? 'text-label-status-error' : 'text-label-tertiary'}`}>
|
|
512
|
-
→ ends {addMinutesToTime(time, durationMinutes)}
|
|
513
|
-
</span>
|
|
514
|
-
<button
|
|
515
|
-
type="button"
|
|
516
|
-
onClick={() => removeDailyTime(index)}
|
|
517
|
-
className="p-1.5 text-label-tertiary hover:text-label-danger transition-colors ml-auto"
|
|
518
|
-
>
|
|
519
|
-
<IconCross className="w-4 h-4 fill-current" />
|
|
520
|
-
</button>
|
|
521
|
-
</div>
|
|
522
|
-
{hasWarning && (
|
|
523
|
-
<div className="bg-surface-status-error border border-border-status-error rounded-md px-2 py-1.5 mt-1">
|
|
524
|
-
{startsAfterCloseDays.length > 0 && (
|
|
525
|
-
<span className="text-label-status-error text-xs block">
|
|
526
|
-
⚠ Session starts after venue closes
|
|
527
|
-
</span>
|
|
528
|
-
)}
|
|
529
|
-
{endsAfterCloseDays.length > 0 && (
|
|
530
|
-
<span className="text-label-status-error text-xs block">
|
|
531
|
-
⚠ Session ends after venue closes
|
|
532
|
-
</span>
|
|
533
|
-
)}
|
|
534
|
-
{beforeOpenDays.length > 0 && (
|
|
535
|
-
<span className="text-label-status-error text-xs block">
|
|
536
|
-
⚠ Session starts before venue opens
|
|
537
|
-
</span>
|
|
538
|
-
)}
|
|
539
|
-
</div>
|
|
540
|
-
)}
|
|
541
|
-
</div>
|
|
542
|
-
);
|
|
543
|
-
})}
|
|
544
|
-
<Button
|
|
545
|
-
type="button"
|
|
546
|
-
variant="outline"
|
|
547
|
-
onClick={addDailyTime}
|
|
548
|
-
className="w-fit"
|
|
549
|
-
withIcon
|
|
550
|
-
>
|
|
551
|
-
<IconPlus className="w-4 h-4 fill-fill-secondary" />
|
|
552
|
-
Add Session
|
|
553
|
-
</Button>
|
|
554
|
-
</div>
|
|
555
|
-
</div>
|
|
556
|
-
)}
|
|
557
|
-
|
|
558
|
-
{/* Per-day configuration */}
|
|
559
|
-
{!isDaily && (
|
|
560
|
-
<div className="flex flex-col gap-4">
|
|
561
|
-
{durationMinutes > 0 && availabilityType === 'fixed_sessions' && (
|
|
562
|
-
<p className="text-label-tertiary text-sm">
|
|
563
|
-
Session duration: {formatDuration(durationMinutes)}
|
|
564
|
-
</p>
|
|
565
|
-
)}
|
|
566
|
-
{DAYS_OF_WEEK.map((day) => {
|
|
567
|
-
const dayData = dayAvailability[day.value] || { enabled: true, times: [] };
|
|
568
|
-
const venueOpen = isVenueOpenOnDay(day.value);
|
|
569
|
-
const hours = getOpeningHoursForDay(day.value);
|
|
570
|
-
|
|
571
|
-
return (
|
|
572
|
-
<div
|
|
573
|
-
key={day.value}
|
|
574
|
-
className={`flex flex-col gap-2 p-3 rounded-lg ${
|
|
575
|
-
venueOpen ? 'bg-surface-secondary' : 'bg-surface-tertiary opacity-60'
|
|
576
|
-
}`}
|
|
577
|
-
>
|
|
578
|
-
<div className="flex items-center justify-between">
|
|
579
|
-
<div className="flex items-center gap-3">
|
|
580
|
-
<Switch
|
|
581
|
-
checked={dayData.enabled && venueOpen}
|
|
582
|
-
onCheckedChange={() => toggleDayEnabled(day.value)}
|
|
583
|
-
disabled={!venueOpen}
|
|
584
|
-
/>
|
|
585
|
-
<div className="flex flex-col">
|
|
586
|
-
<span className={`text-sm font-medium ${
|
|
587
|
-
dayData.enabled && venueOpen ? 'text-label-primary' : 'text-label-tertiary'
|
|
588
|
-
}`}>
|
|
589
|
-
{day.label}
|
|
590
|
-
</span>
|
|
591
|
-
{!venueOpen && (
|
|
592
|
-
<span className="text-xs text-label-tertiary">Venue closed</span>
|
|
593
|
-
)}
|
|
594
|
-
{venueOpen && hours && (
|
|
595
|
-
<span className="text-xs text-label-tertiary">
|
|
596
|
-
Open {formatTimeForDisplay(hours.open_time)} - {formatTimeForDisplay(hours.close_time)}
|
|
597
|
-
</span>
|
|
598
|
-
)}
|
|
599
|
-
</div>
|
|
600
|
-
</div>
|
|
601
|
-
</div>
|
|
602
|
-
|
|
603
|
-
{dayData.enabled && venueOpen && availabilityType === 'fixed_sessions' && (
|
|
604
|
-
<div className="flex flex-col gap-2 pl-10">
|
|
605
|
-
<div className="flex flex-wrap items-center gap-2">
|
|
606
|
-
{dayData.times.map((time, index) => {
|
|
607
|
-
const issues = getSessionIssuesForDay(time, day.value);
|
|
608
|
-
const hasWarning = issues.exceedsClosing || issues.startsAfterClose || issues.beforeOpening;
|
|
609
|
-
|
|
610
|
-
// Build appropriate warning message
|
|
611
|
-
let warningText = '';
|
|
612
|
-
if (issues.startsAfterClose) {
|
|
613
|
-
warningText = '⚠ Starts after close';
|
|
614
|
-
} else if (issues.exceedsClosing) {
|
|
615
|
-
warningText = '⚠ Ends after close';
|
|
616
|
-
} else if (issues.beforeOpening) {
|
|
617
|
-
warningText = '⚠ Starts before open';
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
return (
|
|
621
|
-
<div key={index} className="flex flex-col gap-0.5">
|
|
622
|
-
<div className={`flex items-center gap-1 rounded px-2 py-1 ${
|
|
623
|
-
hasWarning ? 'bg-surface-status-error/20 border border-border-status-error' : 'bg-surface-primary'
|
|
624
|
-
}`}>
|
|
625
|
-
<Input
|
|
626
|
-
type="time"
|
|
627
|
-
value={time}
|
|
628
|
-
onChange={(e) => updateDayTime(day.value, index, e.target.value)}
|
|
629
|
-
className="w-28 h-7 text-sm border-0 bg-transparent p-0"
|
|
630
|
-
/>
|
|
631
|
-
<button
|
|
632
|
-
type="button"
|
|
633
|
-
onClick={() => removeDayTime(day.value, index)}
|
|
634
|
-
className="p-0.5 text-label-tertiary hover:text-label-danger transition-colors"
|
|
635
|
-
>
|
|
636
|
-
<IconCross className="w-3 h-3 fill-current" />
|
|
637
|
-
</button>
|
|
638
|
-
</div>
|
|
639
|
-
{hasWarning && (
|
|
640
|
-
<div className="bg-surface-status-error border border-border-status-error rounded px-1.5 py-0.5 mt-0.5">
|
|
641
|
-
<span className="text-label-status-error text-[10px]">
|
|
642
|
-
{warningText}
|
|
643
|
-
</span>
|
|
644
|
-
</div>
|
|
645
|
-
)}
|
|
646
|
-
</div>
|
|
647
|
-
);
|
|
648
|
-
})}
|
|
649
|
-
<button
|
|
650
|
-
type="button"
|
|
651
|
-
onClick={() => addDayTime(day.value)}
|
|
652
|
-
className="flex items-center gap-1 px-2 py-1 text-sm text-label-action hover:underline"
|
|
653
|
-
>
|
|
654
|
-
<IconPlus className="w-3 h-3 fill-fill-action" />
|
|
655
|
-
Add
|
|
656
|
-
</button>
|
|
657
|
-
</div>
|
|
658
|
-
</div>
|
|
659
|
-
)}
|
|
660
|
-
|
|
661
|
-
{dayData.enabled && venueOpen && availabilityType === 'incremental' && (
|
|
662
|
-
<p className="text-label-tertiary text-sm pl-10">
|
|
663
|
-
Available every {incrementMinutes} minutes
|
|
664
|
-
</p>
|
|
665
|
-
)}
|
|
666
|
-
</div>
|
|
667
|
-
);
|
|
668
|
-
})}
|
|
669
|
-
</div>
|
|
670
|
-
)}
|
|
671
|
-
</>
|
|
672
|
-
)}
|
|
673
|
-
</div>
|
|
674
|
-
);
|
|
675
|
-
};
|
|
676
|
-
|
|
677
|
-
export default AvailabilitySection;
|