@licklist/design 0.78.5-dev.107 → 0.78.5-dev.108

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.
Files changed (414) hide show
  1. package/bitbucket-pipelines.yml +4 -13
  2. package/dist/Maintenance/Maintenance.scss.js +1 -1
  3. package/dist/index.js +2 -0
  4. package/dist/product-set/form/ProductsControl.d.ts +1 -2
  5. package/dist/product-set/form/ProductsControl.d.ts.map +1 -1
  6. package/dist/product-set/form/ProductsControl.js +24 -0
  7. package/dist/v2/components/ActionMenu/ActionMenu.scss.js +1 -1
  8. package/dist/v2/components/Badge/Badge.scss.js +1 -1
  9. package/dist/v2/components/Button/Button.scss.js +1 -1
  10. package/dist/v2/components/Button/GhostButton.scss.js +1 -1
  11. package/dist/v2/components/Checkbox/Checkbox.scss.js +1 -1
  12. package/dist/v2/components/DataTable/DataTable.d.ts.map +1 -1
  13. package/dist/v2/components/DataTable/DataTable.js +2 -86
  14. package/dist/v2/components/IconButton/IconButton.scss.js +1 -1
  15. package/dist/v2/components/Modal/DeleteModal.d.ts.map +1 -1
  16. package/dist/v2/components/Modal/DeleteModal.js +11 -13
  17. package/dist/v2/components/Modal/DeleteModal.scss.js +1 -1
  18. package/dist/v2/components/NPSScore/NPSScore.scss.js +1 -1
  19. package/dist/v2/components/NewTabs/NewTabs.scss.js +1 -1
  20. package/dist/v2/components/PeriodCard/PeriodCard.d.ts +66 -0
  21. package/dist/v2/components/PeriodCard/PeriodCard.d.ts.map +1 -0
  22. package/dist/v2/components/PeriodCard/PeriodCard.js +351 -0
  23. package/dist/v2/components/PeriodCard/PeriodCard.scss.js +6 -0
  24. package/dist/v2/components/PeriodCard/index.d.ts +3 -0
  25. package/dist/v2/components/PeriodCard/index.d.ts.map +1 -0
  26. package/dist/v2/components/ReorderRow/ReorderRow.d.ts +24 -0
  27. package/dist/v2/components/ReorderRow/ReorderRow.d.ts.map +1 -0
  28. package/dist/v2/components/ReorderRow/ReorderRow.js +109 -0
  29. package/dist/v2/components/ReorderRow/ReorderRow.scss.js +6 -0
  30. package/dist/v2/components/ReorderRow/index.d.ts +3 -0
  31. package/dist/v2/components/ReorderRow/index.d.ts.map +1 -0
  32. package/dist/v2/components/Select/Select.scss.js +1 -1
  33. package/dist/v2/components/StatusBadge/StatusBadge.scss.js +1 -1
  34. package/dist/v2/components/StepIndicator/StepIndicator.scss.js +1 -1
  35. package/dist/v2/components/Tabs/Tabs.scss.js +1 -1
  36. package/dist/v2/components/Toggle/Toggle.d.ts.map +1 -1
  37. package/dist/v2/components/Toggle/Toggle.js +5 -8
  38. package/dist/v2/components/Tooltip/Tooltip.scss.js +1 -1
  39. package/dist/v2/components/UserAvatar/UserAvatar.scss.js +1 -1
  40. package/dist/v2/components/UserPanel/UserPanel.scss.js +1 -1
  41. package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.scss.js +1 -1
  42. package/dist/v2/components/ZoneCard/ZoneCard.scss.js +1 -1
  43. package/dist/v2/components/index.d.ts +4 -0
  44. package/dist/v2/components/index.d.ts.map +1 -1
  45. package/dist/v2/dashboard-analytics/chart/Chart.scss.js +1 -1
  46. package/dist/v2/dashboard-analytics/metric-card/MetricCard.scss.js +1 -1
  47. package/dist/v2/dashboard-analytics/venue-card/VenueCard.scss.js +1 -1
  48. package/dist/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.scss.js +1 -1
  49. package/dist/v2/icons/index.js +16 -1
  50. package/dist/v2/index.d.ts +8 -0
  51. package/dist/v2/index.d.ts.map +1 -1
  52. package/dist/v2/navigation/DashboardLayout/AdminSidebar.scss.js +1 -1
  53. package/dist/v2/navigation/DashboardLayout/DashboardLayout.scss.js +1 -1
  54. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.scss.js +1 -1
  55. package/dist/v2/navigation/DashboardLayout/TopNavigation.scss.js +1 -1
  56. package/dist/v2/pages/Settings/SettingsTabs.scss.js +1 -1
  57. package/dist/v2/pages/Settings/components/SidebarCustomisation.js +5 -0
  58. package/dist/v2/pages/Settings/components/SidebarCustomisation.scss.js +1 -1
  59. package/dist/v2/pages/Settings/components/SidebarNavItem.js +5 -0
  60. package/dist/v2/pages/auth/AuthLayout/AuthLayout.scss.js +1 -1
  61. package/dist/v2/shadcn/components/ui/accordion.d.ts +8 -0
  62. package/dist/v2/shadcn/components/ui/accordion.d.ts.map +1 -0
  63. package/dist/v2/shadcn/components/ui/alert-dialog.d.ts +21 -0
  64. package/dist/v2/shadcn/components/ui/alert-dialog.d.ts.map +1 -0
  65. package/dist/v2/shadcn/components/ui/alert.d.ts +9 -0
  66. package/dist/v2/shadcn/components/ui/alert.d.ts.map +1 -0
  67. package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts +4 -0
  68. package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts.map +1 -0
  69. package/dist/v2/shadcn/components/ui/avatar.d.ts +7 -0
  70. package/dist/v2/shadcn/components/ui/avatar.d.ts.map +1 -0
  71. package/dist/v2/shadcn/components/ui/badge.d.ts +10 -0
  72. package/dist/v2/shadcn/components/ui/badge.d.ts.map +1 -0
  73. package/dist/v2/shadcn/components/ui/breadcrumb.d.ts +20 -0
  74. package/dist/v2/shadcn/components/ui/breadcrumb.d.ts.map +1 -0
  75. package/dist/v2/shadcn/components/ui/button.d.ts +14 -0
  76. package/dist/v2/shadcn/components/ui/button.d.ts.map +1 -0
  77. package/dist/v2/shadcn/components/ui/calendar.d.ts +9 -0
  78. package/dist/v2/shadcn/components/ui/calendar.d.ts.map +1 -0
  79. package/dist/v2/shadcn/components/ui/card.d.ts +9 -0
  80. package/dist/v2/shadcn/components/ui/card.d.ts.map +1 -0
  81. package/dist/v2/shadcn/components/ui/carousel.d.ts +19 -0
  82. package/dist/v2/shadcn/components/ui/carousel.d.ts.map +1 -0
  83. package/dist/v2/shadcn/components/ui/checkbox.d.ts +6 -0
  84. package/dist/v2/shadcn/components/ui/checkbox.d.ts.map +1 -0
  85. package/dist/v2/shadcn/components/ui/checkbox.js +115 -0
  86. package/dist/v2/shadcn/components/ui/checkbox.scss.js +6 -0
  87. package/dist/v2/shadcn/components/ui/collapsible.d.ts +6 -0
  88. package/dist/v2/shadcn/components/ui/collapsible.d.ts.map +1 -0
  89. package/dist/v2/shadcn/components/ui/command.d.ts +83 -0
  90. package/dist/v2/shadcn/components/ui/command.d.ts.map +1 -0
  91. package/dist/v2/shadcn/components/ui/context-menu.d.ts +28 -0
  92. package/dist/v2/shadcn/components/ui/context-menu.d.ts.map +1 -0
  93. package/dist/v2/shadcn/components/ui/dialog.d.ts +20 -0
  94. package/dist/v2/shadcn/components/ui/dialog.d.ts.map +1 -0
  95. package/dist/v2/shadcn/components/ui/dialog.js +169 -0
  96. package/dist/v2/shadcn/components/ui/drawer.d.ts +23 -0
  97. package/dist/v2/shadcn/components/ui/drawer.d.ts.map +1 -0
  98. package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts +28 -0
  99. package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts.map +1 -0
  100. package/dist/v2/shadcn/components/ui/form.d.ts +24 -0
  101. package/dist/v2/shadcn/components/ui/form.d.ts.map +1 -0
  102. package/dist/v2/shadcn/components/ui/hover-card.d.ts +7 -0
  103. package/dist/v2/shadcn/components/ui/hover-card.d.ts.map +1 -0
  104. package/dist/v2/shadcn/components/ui/input-otp.d.ts +35 -0
  105. package/dist/v2/shadcn/components/ui/input-otp.d.ts.map +1 -0
  106. package/dist/v2/shadcn/components/ui/input.d.ts +6 -0
  107. package/dist/v2/shadcn/components/ui/input.d.ts.map +1 -0
  108. package/dist/v2/shadcn/components/ui/label.d.ts +6 -0
  109. package/dist/v2/shadcn/components/ui/label.d.ts.map +1 -0
  110. package/dist/v2/shadcn/components/ui/menubar.d.ts +34 -0
  111. package/dist/v2/shadcn/components/ui/menubar.d.ts.map +1 -0
  112. package/dist/v2/shadcn/components/ui/navigation-menu.d.ts +13 -0
  113. package/dist/v2/shadcn/components/ui/navigation-menu.d.ts.map +1 -0
  114. package/dist/v2/shadcn/components/ui/pagination.d.ts +29 -0
  115. package/dist/v2/shadcn/components/ui/pagination.d.ts.map +1 -0
  116. package/dist/v2/shadcn/components/ui/popover.d.ts +7 -0
  117. package/dist/v2/shadcn/components/ui/popover.d.ts.map +1 -0
  118. package/dist/v2/shadcn/components/ui/progress.d.ts +5 -0
  119. package/dist/v2/shadcn/components/ui/progress.d.ts.map +1 -0
  120. package/dist/v2/shadcn/components/ui/radio-card.d.ts +12 -0
  121. package/dist/v2/shadcn/components/ui/radio-card.d.ts.map +1 -0
  122. package/dist/v2/shadcn/components/ui/radio-group.d.ts +6 -0
  123. package/dist/v2/shadcn/components/ui/radio-group.d.ts.map +1 -0
  124. package/dist/v2/shadcn/components/ui/scroll-area.d.ts +6 -0
  125. package/dist/v2/shadcn/components/ui/scroll-area.d.ts.map +1 -0
  126. package/dist/v2/shadcn/components/ui/select.d.ts +14 -0
  127. package/dist/v2/shadcn/components/ui/select.d.ts.map +1 -0
  128. package/dist/v2/shadcn/components/ui/separator.d.ts +5 -0
  129. package/dist/v2/shadcn/components/ui/separator.d.ts.map +1 -0
  130. package/dist/v2/shadcn/components/ui/sheet.d.ts +26 -0
  131. package/dist/v2/shadcn/components/ui/sheet.d.ts.map +1 -0
  132. package/dist/v2/shadcn/components/ui/sidebar.d.ts +67 -0
  133. package/dist/v2/shadcn/components/ui/sidebar.d.ts.map +1 -0
  134. package/dist/v2/shadcn/components/ui/skeleton.d.ts +3 -0
  135. package/dist/v2/shadcn/components/ui/skeleton.d.ts.map +1 -0
  136. package/dist/v2/shadcn/components/ui/slider.d.ts +5 -0
  137. package/dist/v2/shadcn/components/ui/slider.d.ts.map +1 -0
  138. package/dist/v2/shadcn/components/ui/switch.d.ts +6 -0
  139. package/dist/v2/shadcn/components/ui/switch.d.ts.map +1 -0
  140. package/dist/v2/shadcn/components/ui/switch.js +115 -0
  141. package/dist/v2/shadcn/components/ui/switch.scss.js +6 -0
  142. package/dist/v2/shadcn/components/ui/table-pagination.d.ts +11 -0
  143. package/dist/v2/shadcn/components/ui/table-pagination.d.ts.map +1 -0
  144. package/dist/v2/shadcn/components/ui/table.d.ts +11 -0
  145. package/dist/v2/shadcn/components/ui/table.d.ts.map +1 -0
  146. package/dist/v2/shadcn/components/ui/tabs.d.ts +8 -0
  147. package/dist/v2/shadcn/components/ui/tabs.d.ts.map +1 -0
  148. package/dist/v2/shadcn/components/ui/textarea.d.ts +6 -0
  149. package/dist/v2/shadcn/components/ui/textarea.d.ts.map +1 -0
  150. package/dist/v2/shadcn/components/ui/toast.d.ts +16 -0
  151. package/dist/v2/shadcn/components/ui/toast.d.ts.map +1 -0
  152. package/dist/v2/shadcn/components/ui/toaster.d.ts +2 -0
  153. package/dist/v2/shadcn/components/ui/toaster.d.ts.map +1 -0
  154. package/dist/v2/shadcn/components/ui/toggle-group.d.ts +13 -0
  155. package/dist/v2/shadcn/components/ui/toggle-group.d.ts.map +1 -0
  156. package/dist/v2/shadcn/components/ui/toggle.d.ts +13 -0
  157. package/dist/v2/shadcn/components/ui/toggle.d.ts.map +1 -0
  158. package/dist/v2/shadcn/components/ui/tooltip.d.ts +8 -0
  159. package/dist/v2/shadcn/components/ui/tooltip.d.ts.map +1 -0
  160. package/dist/v2/shadcn/components/ui/use-toast.d.ts +3 -0
  161. package/dist/v2/shadcn/components/ui/use-toast.d.ts.map +1 -0
  162. package/dist/v2/shadcn/hooks/use-mobile.d.ts +2 -0
  163. package/dist/v2/shadcn/hooks/use-mobile.d.ts.map +1 -0
  164. package/dist/v2/shadcn/hooks/use-toast.d.ts +45 -0
  165. package/dist/v2/shadcn/hooks/use-toast.d.ts.map +1 -0
  166. package/dist/v2/shadcn/index.d.ts +20 -0
  167. package/dist/v2/shadcn/index.d.ts.map +1 -0
  168. package/dist/v2/shadcn/lib/utils.d.ts +3 -0
  169. package/dist/v2/shadcn/lib/utils.d.ts.map +1 -0
  170. package/dist/v2/shadcn/lib/utils.js +11 -0
  171. package/dist/v2/shadcn/styles/globals.css +112 -0
  172. package/dist/v2/styles/form/NewInput.scss.js +1 -1
  173. package/package.json +6 -6
  174. package/rollup.config.js +2 -16
  175. package/src/iframe/payment/payment-status-page/PaymentStatusPage.tsx +1 -1
  176. package/src/product-set/form/ProductsControl.tsx +1 -2
  177. package/src/v2/components/DataTable/DataTable.tsx +1 -23
  178. package/src/v2/components/Modal/DeleteModal.tsx +20 -12
  179. package/src/v2/components/PeriodCard/PeriodCard.scss +157 -0
  180. package/src/v2/components/PeriodCard/PeriodCard.stories.tsx +245 -0
  181. package/src/v2/components/PeriodCard/PeriodCard.tsx +350 -0
  182. package/src/v2/components/PeriodCard/index.ts +8 -0
  183. package/src/v2/components/ReorderRow/ReorderRow.scss +68 -0
  184. package/src/v2/components/ReorderRow/ReorderRow.stories.tsx +124 -0
  185. package/src/v2/components/ReorderRow/ReorderRow.tsx +88 -0
  186. package/src/v2/components/ReorderRow/index.ts +2 -0
  187. package/src/v2/components/Toggle/Toggle.tsx +5 -6
  188. package/src/v2/components/index.ts +6 -0
  189. package/src/v2/index.ts +82 -0
  190. package/src/v2/shadcn/_reference/AccountManagerCard.tsx +45 -0
  191. package/src/v2/shadcn/_reference/AffiliatesTable.tsx +178 -0
  192. package/src/v2/shadcn/_reference/AuditArchive.tsx +165 -0
  193. package/src/v2/shadcn/_reference/AuditContent.tsx +270 -0
  194. package/src/v2/shadcn/_reference/AutomationsGeneralSettings.tsx +251 -0
  195. package/src/v2/shadcn/_reference/AvatarUpload.tsx +150 -0
  196. package/src/v2/shadcn/_reference/BookingsSummaryCard.tsx +268 -0
  197. package/src/v2/shadcn/_reference/CodeCleanUpAudit.tsx +274 -0
  198. package/src/v2/shadcn/_reference/CompaniesTable.tsx +387 -0
  199. package/src/v2/shadcn/_reference/ComponentAudit.tsx +239 -0
  200. package/src/v2/shadcn/_reference/ConfigureSettingsCard.tsx +95 -0
  201. package/src/v2/shadcn/_reference/CustomerCard.tsx +155 -0
  202. package/src/v2/shadcn/_reference/DashboardCards.tsx +50 -0
  203. package/src/v2/shadcn/_reference/DashboardFooter.tsx +18 -0
  204. package/src/v2/shadcn/_reference/DiarySettings.tsx +187 -0
  205. package/src/v2/shadcn/_reference/DiaryView.tsx +998 -0
  206. package/src/v2/shadcn/_reference/EmptyState.tsx +76 -0
  207. package/src/v2/shadcn/_reference/EntityInfoCard.tsx +48 -0
  208. package/src/v2/shadcn/_reference/ExistingUserAssignments.tsx +131 -0
  209. package/src/v2/shadcn/_reference/FeatureToggle.tsx +72 -0
  210. package/src/v2/shadcn/_reference/FlowCard.tsx +170 -0
  211. package/src/v2/shadcn/_reference/FlowsContent.tsx +688 -0
  212. package/src/v2/shadcn/_reference/FlowsGeneralSettings.tsx +27 -0
  213. package/src/v2/shadcn/_reference/GeneralSettings.tsx +33 -0
  214. package/src/v2/shadcn/_reference/InventoryGeneralSettings.tsx +82 -0
  215. package/src/v2/shadcn/_reference/LanguageSelector.tsx +97 -0
  216. package/src/v2/shadcn/_reference/LoadingScreen.tsx +25 -0
  217. package/src/v2/shadcn/_reference/LoadingSpinner.tsx +41 -0
  218. package/src/v2/shadcn/_reference/ManagedClientsList.tsx +121 -0
  219. package/src/v2/shadcn/_reference/NPSScore.tsx +379 -0
  220. package/src/v2/shadcn/_reference/NPSSummaryCard.tsx +181 -0
  221. package/src/v2/shadcn/_reference/NotificationBanner.tsx +129 -0
  222. package/src/v2/shadcn/_reference/NotificationPanel.tsx +208 -0
  223. package/src/v2/shadcn/_reference/OnlineUsersCard.tsx +73 -0
  224. package/src/v2/shadcn/_reference/ProtectedRoute.tsx +39 -0
  225. package/src/v2/shadcn/_reference/ProvidersTable.tsx +353 -0
  226. package/src/v2/shadcn/_reference/QuickAddPanel.tsx +1057 -0
  227. package/src/v2/shadcn/_reference/QuickFilters.tsx +112 -0
  228. package/src/v2/shadcn/_reference/ScheduleView.tsx +410 -0
  229. package/src/v2/shadcn/_reference/ScrollToTop.tsx +14 -0
  230. package/src/v2/shadcn/_reference/SecondaryNav.tsx +50 -0
  231. package/src/v2/shadcn/_reference/SecuritySettings.tsx +258 -0
  232. package/src/v2/shadcn/_reference/SessionDetailView.tsx +294 -0
  233. package/src/v2/shadcn/_reference/Sidebar.tsx +14 -0
  234. package/src/v2/shadcn/_reference/SidebarAwareLayout.tsx +30 -0
  235. package/src/v2/shadcn/_reference/SidebarLabelCustomization.tsx +285 -0
  236. package/src/v2/shadcn/_reference/SimulationBanner.tsx +57 -0
  237. package/src/v2/shadcn/_reference/SortControls.tsx +65 -0
  238. package/src/v2/shadcn/_reference/StatusBadge.tsx +49 -0
  239. package/src/v2/shadcn/_reference/StyleGuideContent.tsx +331 -0
  240. package/src/v2/shadcn/_reference/TableActionMenu.tsx +126 -0
  241. package/src/v2/shadcn/_reference/ThemeProvider.tsx +119 -0
  242. package/src/v2/shadcn/_reference/ThemeSettings.tsx +73 -0
  243. package/src/v2/shadcn/_reference/TopNavigation.tsx +332 -0
  244. package/src/v2/shadcn/_reference/UserActivityHistory.tsx +209 -0
  245. package/src/v2/shadcn/_reference/UserLanguageSettings.tsx +94 -0
  246. package/src/v2/shadcn/_reference/UserPanel.tsx +472 -0
  247. package/src/v2/shadcn/_reference/UsersTable.tsx +1023 -0
  248. package/src/v2/shadcn/_reference/WaiverForm.tsx +301 -0
  249. package/src/v2/shadcn/_reference/WaiversGeneralSettings.tsx +46 -0
  250. package/src/v2/shadcn/_reference/WaiversTable.tsx +290 -0
  251. package/src/v2/shadcn/_reference/WaiversTemplatesSettings.tsx +416 -0
  252. package/src/v2/shadcn/_reference/ai/AIChatPanel.tsx +313 -0
  253. package/src/v2/shadcn/_reference/ai/AIChatSearchBar.tsx +36 -0
  254. package/src/v2/shadcn/_reference/ai/ChatInteractiveBlock.tsx +298 -0
  255. package/src/v2/shadcn/_reference/ai/ChatMessageContent.tsx +40 -0
  256. package/src/v2/shadcn/_reference/ai/parseInteractiveBlocks.ts +142 -0
  257. package/src/v2/shadcn/_reference/auth/AuthLayout.tsx +55 -0
  258. package/src/v2/shadcn/_reference/auth/CreatePasswordForm.tsx +285 -0
  259. package/src/v2/shadcn/_reference/auth/CreatePasswordPanel.tsx +20 -0
  260. package/src/v2/shadcn/_reference/auth/LoginFooter.tsx +14 -0
  261. package/src/v2/shadcn/_reference/auth/LoginForm.tsx +205 -0
  262. package/src/v2/shadcn/_reference/auth/LoginPanel.tsx +41 -0
  263. package/src/v2/shadcn/_reference/auth/ResetPasswordForm.tsx +102 -0
  264. package/src/v2/shadcn/_reference/auth/ResetPasswordPanel.tsx +20 -0
  265. package/src/v2/shadcn/_reference/auth/VerifyEmailForm.tsx +95 -0
  266. package/src/v2/shadcn/_reference/auth/VerifyEmailPanel.tsx +20 -0
  267. package/src/v2/shadcn/_reference/email/EmailAttachment.tsx +119 -0
  268. package/src/v2/shadcn/_reference/email/EmailAutomation.tsx +92 -0
  269. package/src/v2/shadcn/_reference/email/EmailPlaceholders.tsx +64 -0
  270. package/src/v2/shadcn/_reference/email/UnlayerEmailEditor.tsx +41 -0
  271. package/src/v2/shadcn/_reference/email/emailTemplateData.ts +53 -0
  272. package/src/v2/shadcn/_reference/emptyStateIcons.tsx +103 -0
  273. package/src/v2/shadcn/_reference/games/MazeGame.tsx +394 -0
  274. package/src/v2/shadcn/_reference/games/RunnerGame.tsx +497 -0
  275. package/src/v2/shadcn/_reference/logos/BookedLogoFull.tsx +36 -0
  276. package/src/v2/shadcn/_reference/logos/BookedLogoMark.tsx +31 -0
  277. package/src/v2/shadcn/_reference/logos/BookedLogoNew.tsx +36 -0
  278. package/src/v2/shadcn/_reference/pricing/DynamicPricingRulesEditor.tsx +401 -0
  279. package/src/v2/shadcn/_reference/pricing/DynamicPricingTierCard.tsx +77 -0
  280. package/src/v2/shadcn/_reference/pricing/DynamicPricingTiersList.tsx +218 -0
  281. package/src/v2/shadcn/_reference/pricing/PricingCalendar.tsx +810 -0
  282. package/src/v2/shadcn/_reference/pricing/PricingPeriodCard.tsx +152 -0
  283. package/src/v2/shadcn/_reference/pricing/PricingPeriodForm.tsx +377 -0
  284. package/src/v2/shadcn/_reference/pricing/PricingPeriodsList.tsx +213 -0
  285. package/src/v2/shadcn/_reference/pricing/getRuleSummary.ts +39 -0
  286. package/src/v2/shadcn/_reference/products/AvailabilityRulesSection.tsx +184 -0
  287. package/src/v2/shadcn/_reference/products/AvailabilitySection.tsx +677 -0
  288. package/src/v2/shadcn/_reference/products/BookingTypeConfigOptions.tsx +40 -0
  289. package/src/v2/shadcn/_reference/products/CapacityPeriodsSection.tsx +238 -0
  290. package/src/v2/shadcn/_reference/products/DynamicPricingTiersSection.tsx +131 -0
  291. package/src/v2/shadcn/_reference/products/GiftCardOrdersTab.tsx +192 -0
  292. package/src/v2/shadcn/_reference/products/GiftCardSettings.tsx +342 -0
  293. package/src/v2/shadcn/_reference/products/PackageProductsSection.tsx +322 -0
  294. package/src/v2/shadcn/_reference/products/PricingSection.tsx +173 -0
  295. package/src/v2/shadcn/_reference/products/ProductTypeFields.tsx +353 -0
  296. package/src/v2/shadcn/_reference/products/ProductTypeIcon.tsx +95 -0
  297. package/src/v2/shadcn/_reference/products/VariablePricingSection.tsx +140 -0
  298. package/src/v2/shadcn/_reference/products/productTypeConfig.ts +182 -0
  299. package/src/v2/shadcn/_reference/shared/BackButton.tsx +50 -0
  300. package/src/v2/shadcn/_reference/shared/CancelConfirmationDialog.tsx +18 -0
  301. package/src/v2/shadcn/_reference/shared/ConfirmationDialog.tsx +136 -0
  302. package/src/v2/shadcn/_reference/shared/DeleteConfirmationDialog.tsx +18 -0
  303. package/src/v2/shadcn/_reference/shared/DeleteEntityPage.tsx +221 -0
  304. package/src/v2/shadcn/_reference/shared/SidebarIcons.tsx +108 -0
  305. package/src/v2/shadcn/_reference/shared/UnifiedSidebar.tsx +722 -0
  306. package/src/v2/shadcn/_reference/tables/BulkActionsBar.tsx +68 -0
  307. package/src/v2/shadcn/_reference/tables/DataTable.tsx +221 -0
  308. package/src/v2/shadcn/_reference/tables/TableControls.tsx +94 -0
  309. package/src/v2/shadcn/_reference/tables/index.ts +3 -0
  310. package/src/v2/shadcn/_reference/tables/types.ts +79 -0
  311. package/src/v2/shadcn/_reference/zones/LegacyZoneSettings.tsx +299 -0
  312. package/src/v2/shadcn/components/ui/accordion.stories.tsx +63 -0
  313. package/src/v2/shadcn/components/ui/accordion.tsx +52 -0
  314. package/src/v2/shadcn/components/ui/alert-dialog.stories.tsx +44 -0
  315. package/src/v2/shadcn/components/ui/alert-dialog.tsx +104 -0
  316. package/src/v2/shadcn/components/ui/alert.stories.tsx +44 -0
  317. package/src/v2/shadcn/components/ui/alert.tsx +43 -0
  318. package/src/v2/shadcn/components/ui/aspect-ratio.stories.tsx +46 -0
  319. package/src/v2/shadcn/components/ui/aspect-ratio.tsx +5 -0
  320. package/src/v2/shadcn/components/ui/avatar.stories.tsx +39 -0
  321. package/src/v2/shadcn/components/ui/avatar.tsx +38 -0
  322. package/src/v2/shadcn/components/ui/badge.stories.tsx +17 -0
  323. package/src/v2/shadcn/components/ui/badge.tsx +30 -0
  324. package/src/v2/shadcn/components/ui/breadcrumb.stories.tsx +91 -0
  325. package/src/v2/shadcn/components/ui/breadcrumb.tsx +90 -0
  326. package/src/v2/shadcn/components/ui/button.stories.tsx +20 -0
  327. package/src/v2/shadcn/components/ui/button.tsx +60 -0
  328. package/src/v2/shadcn/components/ui/calendar.stories.tsx +61 -0
  329. package/src/v2/shadcn/components/ui/calendar.tsx +54 -0
  330. package/src/v2/shadcn/components/ui/card.stories.tsx +37 -0
  331. package/src/v2/shadcn/components/ui/card.tsx +43 -0
  332. package/src/v2/shadcn/components/ui/carousel.stories.tsx +92 -0
  333. package/src/v2/shadcn/components/ui/carousel.tsx +224 -0
  334. package/src/v2/shadcn/components/ui/checkbox.scss +38 -0
  335. package/src/v2/shadcn/components/ui/checkbox.stories.tsx +23 -0
  336. package/src/v2/shadcn/components/ui/checkbox.tsx +24 -0
  337. package/src/v2/shadcn/components/ui/collapsible.stories.tsx +59 -0
  338. package/src/v2/shadcn/components/ui/collapsible.tsx +9 -0
  339. package/src/v2/shadcn/components/ui/command.stories.tsx +70 -0
  340. package/src/v2/shadcn/components/ui/command.tsx +132 -0
  341. package/src/v2/shadcn/components/ui/context-menu.stories.tsx +72 -0
  342. package/src/v2/shadcn/components/ui/context-menu.tsx +178 -0
  343. package/src/v2/shadcn/components/ui/dialog.stories.tsx +67 -0
  344. package/src/v2/shadcn/components/ui/dialog.tsx +95 -0
  345. package/src/v2/shadcn/components/ui/drawer.stories.tsx +50 -0
  346. package/src/v2/shadcn/components/ui/drawer.tsx +87 -0
  347. package/src/v2/shadcn/components/ui/dropdown-menu.stories.tsx +73 -0
  348. package/src/v2/shadcn/components/ui/dropdown-menu.tsx +179 -0
  349. package/src/v2/shadcn/components/ui/form.stories.tsx +105 -0
  350. package/src/v2/shadcn/components/ui/form.tsx +129 -0
  351. package/src/v2/shadcn/components/ui/hover-card.stories.tsx +35 -0
  352. package/src/v2/shadcn/components/ui/hover-card.tsx +27 -0
  353. package/src/v2/shadcn/components/ui/input-otp.stories.tsx +72 -0
  354. package/src/v2/shadcn/components/ui/input-otp.tsx +61 -0
  355. package/src/v2/shadcn/components/ui/input.stories.tsx +16 -0
  356. package/src/v2/shadcn/components/ui/input.tsx +25 -0
  357. package/src/v2/shadcn/components/ui/label.stories.tsx +13 -0
  358. package/src/v2/shadcn/components/ui/label.tsx +17 -0
  359. package/src/v2/shadcn/components/ui/menubar.stories.tsx +86 -0
  360. package/src/v2/shadcn/components/ui/menubar.tsx +207 -0
  361. package/src/v2/shadcn/components/ui/navigation-menu.stories.tsx +68 -0
  362. package/src/v2/shadcn/components/ui/navigation-menu.tsx +120 -0
  363. package/src/v2/shadcn/components/ui/pagination.stories.tsx +78 -0
  364. package/src/v2/shadcn/components/ui/pagination.tsx +81 -0
  365. package/src/v2/shadcn/components/ui/popover.stories.tsx +44 -0
  366. package/src/v2/shadcn/components/ui/popover.tsx +29 -0
  367. package/src/v2/shadcn/components/ui/progress.stories.tsx +17 -0
  368. package/src/v2/shadcn/components/ui/progress.tsx +23 -0
  369. package/src/v2/shadcn/components/ui/radio-card.stories.tsx +68 -0
  370. package/src/v2/shadcn/components/ui/radio-card.tsx +52 -0
  371. package/src/v2/shadcn/components/ui/radio-group.stories.tsx +77 -0
  372. package/src/v2/shadcn/components/ui/radio-group.tsx +35 -0
  373. package/src/v2/shadcn/components/ui/scroll-area.stories.tsx +56 -0
  374. package/src/v2/shadcn/components/ui/scroll-area.tsx +38 -0
  375. package/src/v2/shadcn/components/ui/select.stories.tsx +60 -0
  376. package/src/v2/shadcn/components/ui/select.tsx +148 -0
  377. package/src/v2/shadcn/components/ui/separator.stories.tsx +30 -0
  378. package/src/v2/shadcn/components/ui/separator.tsx +20 -0
  379. package/src/v2/shadcn/components/ui/sheet.stories.tsx +115 -0
  380. package/src/v2/shadcn/components/ui/sheet.tsx +107 -0
  381. package/src/v2/shadcn/components/ui/sidebar.stories.tsx +167 -0
  382. package/src/v2/shadcn/components/ui/sidebar.tsx +637 -0
  383. package/src/v2/shadcn/components/ui/skeleton.stories.tsx +36 -0
  384. package/src/v2/shadcn/components/ui/skeleton.tsx +7 -0
  385. package/src/v2/shadcn/components/ui/slider.stories.tsx +16 -0
  386. package/src/v2/shadcn/components/ui/slider.tsx +23 -0
  387. package/src/v2/shadcn/components/ui/switch.scss +63 -0
  388. package/src/v2/shadcn/components/ui/switch.stories.tsx +23 -0
  389. package/src/v2/shadcn/components/ui/switch.tsx +24 -0
  390. package/src/v2/shadcn/components/ui/table-pagination.stories.tsx +81 -0
  391. package/src/v2/shadcn/components/ui/table-pagination.tsx +61 -0
  392. package/src/v2/shadcn/components/ui/table.stories.tsx +40 -0
  393. package/src/v2/shadcn/components/ui/table.tsx +72 -0
  394. package/src/v2/shadcn/components/ui/tabs.stories.tsx +85 -0
  395. package/src/v2/shadcn/components/ui/tabs.tsx +53 -0
  396. package/src/v2/shadcn/components/ui/textarea.stories.tsx +15 -0
  397. package/src/v2/shadcn/components/ui/textarea.tsx +21 -0
  398. package/src/v2/shadcn/components/ui/toast.stories.tsx +77 -0
  399. package/src/v2/shadcn/components/ui/toast.tsx +111 -0
  400. package/src/v2/shadcn/components/ui/toaster.stories.tsx +46 -0
  401. package/src/v2/shadcn/components/ui/toaster.tsx +24 -0
  402. package/src/v2/shadcn/components/ui/toggle-group.stories.tsx +95 -0
  403. package/src/v2/shadcn/components/ui/toggle-group.tsx +49 -0
  404. package/src/v2/shadcn/components/ui/toggle.stories.tsx +18 -0
  405. package/src/v2/shadcn/components/ui/toggle.tsx +37 -0
  406. package/src/v2/shadcn/components/ui/tooltip.stories.tsx +57 -0
  407. package/src/v2/shadcn/components/ui/tooltip.tsx +28 -0
  408. package/src/v2/shadcn/components/ui/use-toast.ts +3 -0
  409. package/src/v2/shadcn/hooks/use-mobile.tsx +19 -0
  410. package/src/v2/shadcn/hooks/use-toast.ts +184 -0
  411. package/src/v2/shadcn/index.ts +76 -0
  412. package/src/v2/shadcn/lib/utils.ts +6 -0
  413. package/src/v2/shadcn/styles/globals.css +112 -0
  414. package/.vscode/settings.json +0 -3
@@ -0,0 +1,313 @@
1
+ import React, { useState, useRef, useEffect } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { ScrollArea } from '../ui/scroll-area';
4
+ import { IconCross, IconNew, IconArrowUp } from '../../../icons';
5
+ import { ChatMessageContent } from './ChatMessageContent';
6
+ import { supabase } from '@/integrations/supabase/client';
7
+ import { useAIChatPanel } from '@/contexts/AIChatPanelContext';
8
+ import { useUser } from '@/contexts/UserContext';
9
+ import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
10
+
11
+ interface AIChatPanelProps {
12
+ isOpen: boolean;
13
+ onClose: () => void;
14
+ }
15
+
16
+ export const AIChatPanel: React.FC<AIChatPanelProps> = ({ isOpen, onClose }) => {
17
+ const [inputValue, setInputValue] = useState('');
18
+ const { messages, isLoading, sendMessage, addBotMessage, clearMessages, consumePendingMessage } = useAIChatPanel();
19
+ const messagesEndRef = useRef<HTMLDivElement>(null);
20
+ const inputRef = useRef<HTMLInputElement>(null);
21
+ const panelRef = useRef<HTMLDivElement>(null);
22
+ const scrollYRef = useRef(0);
23
+ const navigate = useNavigate();
24
+ const { profile } = useUser();
25
+ const hasSentPending = useRef(false);
26
+
27
+ // Send pending message from search bar when panel opens
28
+ useEffect(() => {
29
+ if (isOpen && !hasSentPending.current) {
30
+ const pending = consumePendingMessage();
31
+ if (pending) {
32
+ sendMessage(pending);
33
+ }
34
+ hasSentPending.current = true;
35
+ }
36
+ if (!isOpen) {
37
+ hasSentPending.current = false;
38
+ }
39
+ }, [isOpen, consumePendingMessage, sendMessage]);
40
+
41
+ useEffect(() => {
42
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
43
+ }, [messages]);
44
+
45
+ useEffect(() => {
46
+ if (isOpen) {
47
+ // Capture current scroll position and lock body in place
48
+ // This prevents iOS from scrolling the layout viewport when keyboard opens
49
+ scrollYRef.current = window.scrollY;
50
+ document.body.style.position = 'fixed';
51
+ document.body.style.top = `-${scrollYRef.current}px`;
52
+ document.body.style.left = '0';
53
+ document.body.style.right = '0';
54
+ document.body.style.overflow = 'hidden';
55
+ setTimeout(() => inputRef.current?.focus(), 300);
56
+ } else {
57
+ // Restore body and scroll position
58
+ document.body.style.position = '';
59
+ document.body.style.top = '';
60
+ document.body.style.left = '';
61
+ document.body.style.right = '';
62
+ document.body.style.overflow = '';
63
+ window.scrollTo(0, scrollYRef.current);
64
+ }
65
+ return () => {
66
+ document.body.style.position = '';
67
+ document.body.style.top = '';
68
+ document.body.style.left = '';
69
+ document.body.style.right = '';
70
+ document.body.style.overflow = '';
71
+ };
72
+ }, [isOpen]);
73
+
74
+ // Prevent any touch-driven scrolling from leaking to the background
75
+ useEffect(() => {
76
+ if (!isOpen) return;
77
+
78
+ const preventScroll = (e: TouchEvent) => {
79
+ // Allow scrolling inside the ScrollArea, block everything else
80
+ const target = e.target as HTMLElement;
81
+ const scrollArea = panelRef.current?.querySelector('[data-radix-scroll-area-viewport]');
82
+ if (scrollArea && scrollArea.contains(target)) return;
83
+ e.preventDefault();
84
+ };
85
+
86
+ document.addEventListener('touchmove', preventScroll, { passive: false });
87
+ return () => document.removeEventListener('touchmove', preventScroll);
88
+ }, [isOpen]);
89
+
90
+ if (!isOpen) return null;
91
+
92
+ const handleSubmit = (e: React.FormEvent) => {
93
+ e.preventDefault();
94
+ if (!inputValue.trim() || isLoading) return;
95
+ sendMessage(inputValue.trim());
96
+ setInputValue('');
97
+ // Re-focus input after submission so user can keep typing
98
+ setTimeout(() => inputRef.current?.focus(), 0);
99
+ };
100
+
101
+ const handleClose = () => {
102
+ onClose();
103
+ };
104
+
105
+ const handleNewChat = () => {
106
+ clearMessages();
107
+ };
108
+
109
+ const handleInteractiveSelect = (value: string) => {
110
+ sendMessage(value);
111
+ };
112
+
113
+ const handleNavigate = (path: string) => {
114
+ onClose();
115
+ navigate(path);
116
+ };
117
+
118
+ const handleInteractiveAction = async (action: string, data?: Record<string, any>) => {
119
+ if (action === 'cancel') {
120
+ sendMessage('Cancel this action.');
121
+ return;
122
+ }
123
+ if (action === 'edit') {
124
+ sendMessage('I want to edit the details.');
125
+ return;
126
+ }
127
+ if (action === 'create_user' && data) {
128
+ // Show a short user action message
129
+ sendMessage(`Create ${data.firstName} ${data.lastName}`);
130
+ try {
131
+ const { data: sessionData } = await supabase.auth.getSession();
132
+ if (!sessionData.session) {
133
+ addBotMessage('❌ Not authenticated. Please log in first.');
134
+ return;
135
+ }
136
+
137
+ const providers: any[] = [];
138
+ if (data.providerId) {
139
+ providers.push({ id: data.providerId, type: 'provider', role: data.role, companyId: data.companyId });
140
+ }
141
+ if (data.companyId) {
142
+ providers.push({ id: data.companyId, type: 'company', role: data.role });
143
+ }
144
+
145
+ const response = await fetch(`${import.meta.env.VITE_SUPABASE_URL}/functions/v1/create-admin-user`, {
146
+ method: 'POST',
147
+ headers: {
148
+ Authorization: `Bearer ${sessionData.session.access_token}`,
149
+ 'Content-Type': 'application/json',
150
+ },
151
+ body: JSON.stringify({
152
+ firstName: data.firstName,
153
+ lastName: data.lastName,
154
+ email: data.email,
155
+ role: data.role,
156
+ providers: providers.length > 0 ? providers : undefined,
157
+ }),
158
+ });
159
+
160
+ const result = await response.json();
161
+ if (!response.ok) throw new Error(result.error || 'Failed to create user');
162
+
163
+ const roleName = (data.role || '').replace(/_/g, ' ');
164
+ addBotMessage(`✅ **${data.firstName} ${data.lastName}** has been created as **${roleName}**. Their temporary password has been generated.`);
165
+ } catch (err: any) {
166
+ addBotMessage(`❌ Failed to create user: ${err.message}`);
167
+ }
168
+ return;
169
+ }
170
+ // Default: send the action as a message
171
+ sendMessage(action);
172
+ };
173
+
174
+ return (
175
+ <>
176
+ {/* Overlay */}
177
+ <div
178
+ className="fixed inset-0 z-40 animate-fade-in touch-none"
179
+ style={{ backgroundColor: 'var(--overlay-curtain)' }}
180
+ onClick={handleClose}
181
+ onTouchMove={(e) => e.preventDefault()}
182
+ />
183
+
184
+ {/* Panel — uses inset-0 so it always fills the available viewport,
185
+ even when the mobile keyboard shrinks the visual viewport */}
186
+ <div
187
+ ref={panelRef}
188
+ className="fixed inset-0 sm:left-auto sm:w-[420px] bg-surface-primary shadow-xl z-50 animate-slide-in-right flex flex-col overscroll-none"
189
+ onClick={(e) => e.stopPropagation()}
190
+ >
191
+ {/* Header */}
192
+ <div className="flex items-center justify-between p-4 border-b border-border-primary flex-shrink-0">
193
+ <div className="flex items-center gap-2">
194
+ <div className="bkit-icon-glow"><IconNew size={32} /></div>
195
+ <h2 className="text-lg font-semibold text-label-primary">Brad Bot</h2>
196
+ </div>
197
+ <div className="flex items-center gap-1">
198
+ {messages.length > 0 && (
199
+ <button
200
+ onClick={handleNewChat}
201
+ className="text-xs font-medium text-label-secondary hover:text-label-primary transition-colors px-2 py-1.5 rounded-lg hover:bg-surface-primary-hover"
202
+ >
203
+ Clear
204
+ </button>
205
+ )}
206
+ <button
207
+ onClick={handleClose}
208
+ className="p-2 rounded-lg hover:bg-surface-primary-hover transition-colors flex items-center justify-center"
209
+ aria-label="Close assistant"
210
+ >
211
+ <IconCross className="w-5 h-5 text-label-secondary" />
212
+ </button>
213
+ </div>
214
+ </div>
215
+
216
+ {/* Messages */}
217
+ <ScrollArea className="flex-1 min-h-0">
218
+ <div className="p-4 space-y-3">
219
+ {messages.length === 0 && (
220
+ <div className="flex flex-col items-center justify-center py-16 text-center">
221
+ <div className="mb-4 opacity-50 text-fill-secondary"><IconNew size={48} /></div>
222
+ <h3 className="text-sm font-semibold text-label-primary mb-1">Brad Bot</h3>
223
+ <p className="text-xs text-label-secondary max-w-[260px]">
224
+ Search, query data, or make changes across your dashboard.
225
+ </p>
226
+ </div>
227
+ )}
228
+ {messages.map((msg) => (
229
+ <div
230
+ key={msg.id}
231
+ className={`flex flex-col ${msg.role === 'user' ? 'items-end' : 'items-start'}`}
232
+ >
233
+ {/* Identity row */}
234
+ <div className={`flex items-center gap-1.5 mb-1 ${msg.role === 'user' ? 'flex-row-reverse' : ''}`}>
235
+ {msg.role === 'user' ? (
236
+ <>
237
+ <Avatar className="h-5 w-5">
238
+ {profile?.avatarUrl && <AvatarImage src={profile.avatarUrl} alt={profile.fullName} />}
239
+ <AvatarFallback className="text-[10px] bg-surface-tertiary text-label-secondary">
240
+ {profile?.initials || '?'}
241
+ </AvatarFallback>
242
+ </Avatar>
243
+ <span className="text-xs font-semibold text-label-secondary">{profile?.firstName || 'You'}</span>
244
+ </>
245
+ ) : (
246
+ <>
247
+ <div className="text-fill-secondary"><IconNew size={16} /></div>
248
+ <span className="text-xs font-semibold text-label-secondary">Brad Bot</span>
249
+ </>
250
+ )}
251
+ </div>
252
+ <div className={`max-w-[90%] rounded-lg px-4 py-2.5 text-sm ${
253
+ msg.role === 'user'
254
+ ? 'bg-surface-primary border border-border-primary text-label-primary'
255
+ : 'bg-surface-tertiary text-label-primary'
256
+ }`}>
257
+ {msg.role === 'assistant' ? (
258
+ <ChatMessageContent
259
+ content={msg.content}
260
+ onSelect={handleInteractiveSelect}
261
+ onAction={handleInteractiveAction}
262
+ onNavigate={handleNavigate}
263
+ disabled={isLoading}
264
+ />
265
+ ) : (
266
+ <div className="whitespace-pre-wrap">{msg.content}</div>
267
+ )}
268
+ </div>
269
+ </div>
270
+ ))}
271
+ {isLoading && messages[messages.length - 1]?.role === 'user' && (
272
+ <div className="flex justify-start">
273
+ <div className="bg-surface-tertiary rounded-lg px-4 py-2.5">
274
+ <div className="flex items-center gap-1.5 mb-1">
275
+ <div className="bkit-icon-glow"><IconNew size={16} /></div>
276
+ <span className="text-xs font-semibold text-label-secondary">Brad Bot</span>
277
+ </div>
278
+ <div className="flex gap-1.5">
279
+ <span className="w-2 h-2 rounded-full bkit-thinking-dot" />
280
+ <span className="w-2 h-2 rounded-full bkit-thinking-dot [animation-delay:0.2s]" />
281
+ <span className="w-2 h-2 rounded-full bkit-thinking-dot [animation-delay:0.4s]" />
282
+ </div>
283
+ </div>
284
+ </div>
285
+ )}
286
+ <div ref={messagesEndRef} />
287
+ </div>
288
+ </ScrollArea>
289
+
290
+ {/* Input */}
291
+ <div className="border-t border-border-primary p-4 pb-[max(1rem,env(safe-area-inset-bottom))] flex-shrink-0">
292
+ <form onSubmit={handleSubmit} className="flex items-center gap-2">
293
+ <input
294
+ ref={inputRef}
295
+ type="text"
296
+ value={inputValue}
297
+ onChange={(e) => setInputValue(e.target.value)}
298
+ className="flex-1 h-10 rounded-lg border border-border-primary bg-surface-primary px-3 text-base text-label-primary focus:outline-none focus:border-border-selected"
299
+ placeholder="Ask Brad Bot anything..."
300
+ />
301
+ <button
302
+ type="submit"
303
+ className="h-10 w-10 flex-shrink-0 flex items-center justify-center rounded-lg bg-fill-action transition-opacity"
304
+ aria-label="Send message"
305
+ >
306
+ <IconArrowUp size={24} className="[&_path]:!fill-white" />
307
+ </button>
308
+ </form>
309
+ </div>
310
+ </div>
311
+ </>
312
+ );
313
+ };
@@ -0,0 +1,36 @@
1
+ import React, { useState, useRef } from 'react';
2
+ import { IconNew } from '../../../icons';
3
+ import { useAIChatPanel } from '@/contexts/AIChatPanelContext';
4
+
5
+ const AIChatSearchBar: React.FC = () => {
6
+ const [inputValue, setInputValue] = useState('');
7
+ const inputRef = useRef<HTMLInputElement>(null);
8
+ const { openPanelWithMessage } = useAIChatPanel();
9
+
10
+ const handleSubmit = (e: React.FormEvent) => {
11
+ e.preventDefault();
12
+ if (!inputValue.trim()) return;
13
+ openPanelWithMessage(inputValue.trim());
14
+ setInputValue('');
15
+ };
16
+
17
+ return (
18
+ <div className="w-full pt-6">
19
+ <div className="w-full rounded-xl border border-border-primary bg-surface-secondary">
20
+ <form onSubmit={handleSubmit} className="flex items-center gap-3 p-3">
21
+ <div className="w-8 h-8 flex-shrink-0 bkit-icon-glow"><IconNew size={32} /></div>
22
+ <input
23
+ ref={inputRef}
24
+ type="text"
25
+ value={inputValue}
26
+ onChange={(e) => setInputValue(e.target.value)}
27
+ className="flex-1 bg-transparent text-[16px] text-label-primary focus:outline-none"
28
+ placeholder="Ask Brad Bot anything..."
29
+ />
30
+ </form>
31
+ </div>
32
+ </div>
33
+ );
34
+ };
35
+
36
+ export default AIChatSearchBar;
@@ -0,0 +1,298 @@
1
+ import React, { useState } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { format } from 'date-fns';
4
+ import { Button } from '../ui/button';
5
+ import { Calendar } from '../ui/calendar';
6
+ import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
7
+ import type {
8
+ InteractiveBlock,
9
+ RadioSelectBlock,
10
+ UserCardBlock,
11
+ ActionButtonsBlock,
12
+ QuickActionsBlock,
13
+ EntityCardBlock,
14
+ } from './parseInteractiveBlocks';
15
+
16
+ interface ChatInteractiveBlockProps {
17
+ block: InteractiveBlock;
18
+ onSelect?: (value: string) => void;
19
+ onAction?: (action: string, data?: Record<string, any>) => void;
20
+ onNavigate?: (path: string) => void;
21
+ disabled?: boolean;
22
+ }
23
+
24
+ const RadioSelect: React.FC<{
25
+ block: RadioSelectBlock;
26
+ onSelect?: (value: string) => void;
27
+ disabled?: boolean;
28
+ }> = ({ block, onSelect, disabled }) => {
29
+ const [selected, setSelected] = useState<string | null>(null);
30
+
31
+ const handleSelect = (value: string) => {
32
+ if (disabled || selected) return;
33
+ setSelected(value);
34
+ onSelect?.(value);
35
+ };
36
+
37
+ return (
38
+ <div className="flex flex-col gap-1.5 mt-2">
39
+ {block.options.map((opt) => (
40
+ <button
41
+ key={opt.value}
42
+ onClick={() => handleSelect(opt.value)}
43
+ disabled={disabled || !!selected}
44
+ className={`flex flex-col items-start gap-0.5 px-3 py-2 rounded-lg border text-left transition-colors ${
45
+ selected === opt.value
46
+ ? 'border-border-selected bg-surface-action-soft'
47
+ : selected
48
+ ? 'border-border-primary bg-surface-secondary opacity-50'
49
+ : 'border-border-primary bg-surface-secondary hover:bg-surface-primary-hover'
50
+ } ${disabled || selected ? 'cursor-default' : 'cursor-pointer'}`}
51
+ >
52
+ <span className="text-sm font-medium text-label-primary">{opt.label}</span>
53
+ {opt.description && (
54
+ <span className="text-xs text-label-secondary">{opt.description}</span>
55
+ )}
56
+ </button>
57
+ ))}
58
+ </div>
59
+ );
60
+ };
61
+
62
+ const UserCard: React.FC<{ block: UserCardBlock }> = ({ block }) => {
63
+ const initials = `${block.firstName.charAt(0)}${block.lastName.charAt(0)}`.toUpperCase();
64
+ const roleName = (block.roleLabel || block.role || '').replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
65
+ const assignmentName = block.providerName || block.companyName;
66
+
67
+ return (
68
+ <div className="flex items-start gap-3 p-3 bg-surface-primary border border-border-primary rounded-lg mt-2 min-w-[320px]">
69
+ <div className="w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 bg-surface-tertiary border border-border-primary">
70
+ <span className="text-label-secondary font-bold text-sm">{initials}</span>
71
+ </div>
72
+ <div className="flex flex-col gap-1 flex-1 min-w-0">
73
+ <span className="text-label-primary font-medium text-sm">{block.firstName} {block.lastName}</span>
74
+ <span className="text-label-secondary text-xs truncate">{block.email}</span>
75
+ <div className="flex flex-wrap items-center gap-1.5 mt-0.5">
76
+ {roleName && (
77
+ <div className="flex justify-center items-center gap-2 bg-surface-tertiary px-2 py-1 rounded-lg w-fit">
78
+ <span className="text-label-secondary text-[10px] leading-3 font-mono font-semibold whitespace-nowrap">
79
+ {roleName}
80
+ </span>
81
+ </div>
82
+ )}
83
+ {assignmentName && (
84
+ <div className="flex justify-center items-center gap-2 bg-surface-tertiary px-2 py-1 rounded-lg w-fit">
85
+ <span className="text-label-secondary text-[10px] leading-3 font-mono font-semibold whitespace-nowrap">
86
+ {assignmentName}
87
+ </span>
88
+ </div>
89
+ )}
90
+ </div>
91
+ </div>
92
+ </div>
93
+ );
94
+ };
95
+
96
+ const ActionButtons: React.FC<{
97
+ block: ActionButtonsBlock;
98
+ onAction?: (action: string, data?: Record<string, any>) => void;
99
+ disabled?: boolean;
100
+ }> = ({ block, onAction, disabled }) => {
101
+ const [clicked, setClicked] = useState<string | null>(null);
102
+
103
+ const handleClick = (btn: typeof block.buttons[0]) => {
104
+ if (disabled || clicked) return;
105
+ setClicked(btn.action);
106
+ onAction?.(btn.action, btn.data);
107
+ };
108
+
109
+ const variantMap: Record<string, any> = {
110
+ primary: 'default',
111
+ ghost: 'ghost',
112
+ cancel: 'cancel',
113
+ destructive: 'destructive',
114
+ };
115
+
116
+ return (
117
+ <div className="flex flex-col gap-1.5 mt-2">
118
+ {block.buttons.map((btn) => (
119
+ <Button
120
+ key={btn.action}
121
+ variant={variantMap[btn.variant] || 'default'}
122
+ size="sm"
123
+ onClick={() => handleClick(btn)}
124
+ disabled={disabled || !!clicked}
125
+ className={`w-full ${btn.variant === 'ghost' ? 'bg-surface-primary' : ''} ${clicked && clicked !== btn.action ? 'opacity-50' : ''}`}
126
+ >
127
+ {clicked === btn.action ? 'Processing...' : btn.label}
128
+ </Button>
129
+ ))}
130
+ </div>
131
+ );
132
+ };
133
+
134
+ const QuickActions: React.FC<{
135
+ block: QuickActionsBlock;
136
+ onSelect?: (value: string) => void;
137
+ disabled?: boolean;
138
+ }> = ({ block, onSelect, disabled }) => {
139
+ const [clicked, setClicked] = useState<string | null>(null);
140
+ const [datePickerAction, setDatePickerAction] = useState<string | null>(null);
141
+ const [selectedDate, setSelectedDate] = useState<Date>();
142
+
143
+ const handleClick = (action: typeof block.actions[0]) => {
144
+ if (disabled || clicked) return;
145
+
146
+ if (action.type === 'date-picker') {
147
+ setDatePickerAction(action.action);
148
+ return;
149
+ }
150
+
151
+ setClicked(action.action);
152
+ onSelect?.(action.action);
153
+ };
154
+
155
+ const handleDateSelect = (date: Date | undefined) => {
156
+ if (!date || !datePickerAction) return;
157
+ setSelectedDate(date);
158
+ const formatted = format(date, 'do MMMM yyyy');
159
+ setClicked(datePickerAction);
160
+ setDatePickerAction(null);
161
+ onSelect?.(`Show bookings for ${formatted}`);
162
+ };
163
+
164
+ return (
165
+ <div className="flex flex-col gap-1.5 mt-2">
166
+ {block.actions.map((action) => (
167
+ action.type === 'date-picker' ? (
168
+ <Popover key={action.action} open={datePickerAction === action.action} onOpenChange={(open) => !open && setDatePickerAction(null)}>
169
+ <PopoverTrigger asChild>
170
+ <button
171
+ onClick={() => handleClick(action)}
172
+ disabled={disabled || !!clicked}
173
+ className={`flex items-center gap-2 px-3 py-2.5 rounded-lg border text-left transition-colors ${
174
+ clicked === action.action
175
+ ? 'border-border-selected bg-surface-action-soft'
176
+ : clicked
177
+ ? 'border-border-primary bg-surface-secondary opacity-50'
178
+ : 'border-border-primary bg-surface-secondary hover:bg-surface-primary-hover'
179
+ } ${disabled || clicked ? 'cursor-default' : 'cursor-pointer'}`}
180
+ >
181
+ <span className="text-sm font-medium text-label-primary">{action.label}</span>
182
+ </button>
183
+ </PopoverTrigger>
184
+ <PopoverContent className="w-auto p-0" align="start" side="top">
185
+ <Calendar
186
+ mode="single"
187
+ selected={selectedDate}
188
+ onSelect={handleDateSelect}
189
+ className="p-3 pointer-events-auto"
190
+ />
191
+ </PopoverContent>
192
+ </Popover>
193
+ ) : (
194
+ <button
195
+ key={action.action}
196
+ onClick={() => handleClick(action)}
197
+ disabled={disabled || !!clicked}
198
+ className={`flex items-center gap-2 px-3 py-2.5 rounded-lg border text-left transition-colors ${
199
+ clicked === action.action
200
+ ? 'border-border-selected bg-surface-action-soft'
201
+ : clicked
202
+ ? 'border-border-primary bg-surface-secondary opacity-50'
203
+ : 'border-border-primary bg-surface-secondary hover:bg-surface-primary-hover'
204
+ } ${disabled || clicked ? 'cursor-default' : 'cursor-pointer'}`}
205
+ >
206
+ <span className="text-sm font-medium text-label-primary">{action.label}</span>
207
+ </button>
208
+ )
209
+ ))}
210
+ </div>
211
+ );
212
+ };
213
+
214
+ const EntityCards: React.FC<{
215
+ block: EntityCardBlock;
216
+ onNavigate?: (path: string) => void;
217
+ }> = ({ block, onNavigate }) => {
218
+ const getEntityPath = (item: typeof block.items[0]): string | null => {
219
+ const providerPrefix = item.providerType === 'promoter' ? 'promoter' : 'venue';
220
+
221
+ switch (item.entityType) {
222
+ case 'customer':
223
+ if (item.providerId) return `/${providerPrefix}/${item.providerId}/customers/${item.id}`;
224
+ return `/admin/customers/${item.id}`;
225
+ case 'user':
226
+ if (item.providerId) return `/${providerPrefix}/${item.providerId}/users/${item.id}`;
227
+ return `/admin/users/${item.id}`;
228
+ case 'provider':
229
+ return `/admin/providers/${item.id}`;
230
+ case 'company':
231
+ return `/admin/companies/${item.id}`;
232
+ default:
233
+ return null;
234
+ }
235
+ };
236
+
237
+ const getInitials = (name: string): string => {
238
+ return name
239
+ .split(' ')
240
+ .map((w) => w.charAt(0))
241
+ .slice(0, 2)
242
+ .join('')
243
+ .toUpperCase();
244
+ };
245
+
246
+ return (
247
+ <div className="flex flex-col gap-1.5 mt-2">
248
+ {block.items.map((item) => {
249
+ const path = getEntityPath(item);
250
+ return (
251
+ <button
252
+ key={item.id}
253
+ onClick={() => path && onNavigate?.(path)}
254
+ className="flex items-center gap-3 p-3 bg-surface-secondary border border-border-primary rounded-lg text-left transition-colors hover:bg-surface-primary-hover cursor-pointer"
255
+ >
256
+ <div className="w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 bg-surface-tertiary border border-border-primary">
257
+ <span className="text-label-secondary font-semibold text-xs">{getInitials(item.name)}</span>
258
+ </div>
259
+ <div className="flex flex-col gap-0.5 flex-1 min-w-0">
260
+ <span className="text-sm font-medium text-label-primary">{item.name}</span>
261
+ {item.subtitle && (
262
+ <span className="text-xs text-label-secondary truncate">{item.subtitle}</span>
263
+ )}
264
+ </div>
265
+ {item.badge && (
266
+ <span className="text-xs font-medium text-label-secondary bg-surface-tertiary px-2 py-0.5 rounded flex-shrink-0">
267
+ {item.badge}
268
+ </span>
269
+ )}
270
+ </button>
271
+ );
272
+ })}
273
+ </div>
274
+ );
275
+ };
276
+
277
+ export const ChatInteractiveBlock: React.FC<ChatInteractiveBlockProps> = ({
278
+ block,
279
+ onSelect,
280
+ onAction,
281
+ onNavigate,
282
+ disabled,
283
+ }) => {
284
+ switch (block.type) {
285
+ case 'radio-select':
286
+ return <RadioSelect block={block} onSelect={onSelect} disabled={disabled} />;
287
+ case 'user-card':
288
+ return <UserCard block={block} />;
289
+ case 'action-buttons':
290
+ return <ActionButtons block={block} onAction={onAction} disabled={disabled} />;
291
+ case 'quick-actions':
292
+ return <QuickActions block={block} onSelect={onSelect} disabled={disabled} />;
293
+ case 'entity-card':
294
+ return <EntityCards block={block} onNavigate={onNavigate} />;
295
+ default:
296
+ return null;
297
+ }
298
+ };
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import { parseMessageContent } from './parseInteractiveBlocks';
3
+ import { ChatInteractiveBlock } from './ChatInteractiveBlock';
4
+
5
+ interface ChatMessageContentProps {
6
+ content: string;
7
+ onSelect?: (value: string) => void;
8
+ onAction?: (action: string, data?: Record<string, any>) => void;
9
+ onNavigate?: (path: string) => void;
10
+ disabled?: boolean;
11
+ }
12
+
13
+ export const ChatMessageContent: React.FC<ChatMessageContentProps> = ({
14
+ content,
15
+ onSelect,
16
+ onAction,
17
+ onNavigate,
18
+ disabled,
19
+ }) => {
20
+ const segments = parseMessageContent(content);
21
+
22
+ return (
23
+ <>
24
+ {segments.map((seg, i) =>
25
+ seg.kind === 'text' ? (
26
+ <div key={i} className="whitespace-pre-wrap">{seg.content}</div>
27
+ ) : (
28
+ <ChatInteractiveBlock
29
+ key={i}
30
+ block={seg.block}
31
+ onSelect={onSelect}
32
+ onAction={onAction}
33
+ onNavigate={onNavigate}
34
+ disabled={disabled}
35
+ />
36
+ )
37
+ )}
38
+ </>
39
+ );
40
+ };