@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.
Files changed (390) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/bitbucket-pipelines.yml +13 -4
  3. package/dist/Maintenance/Maintenance.scss.js +1 -1
  4. package/dist/product-set/form/ProductsControl.d.ts +2 -1
  5. package/dist/product-set/form/ProductsControl.d.ts.map +1 -1
  6. package/dist/product-set/form/ProductsControl.js +0 -24
  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 +86 -2
  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 +13 -11
  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/Select/Select.scss.js +1 -1
  21. package/dist/v2/components/StatusBadge/StatusBadge.scss.js +1 -1
  22. package/dist/v2/components/StepIndicator/StepIndicator.scss.js +1 -1
  23. package/dist/v2/components/Tabs/Tabs.scss.js +1 -1
  24. package/dist/v2/components/Toggle/Toggle.d.ts.map +1 -1
  25. package/dist/v2/components/Toggle/Toggle.js +8 -5
  26. package/dist/v2/components/Tooltip/Tooltip.scss.js +1 -1
  27. package/dist/v2/components/UserAvatar/UserAvatar.scss.js +1 -1
  28. package/dist/v2/components/UserPanel/UserPanel.scss.js +1 -1
  29. package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.scss.js +1 -1
  30. package/dist/v2/components/ZoneCard/ZoneCard.scss.js +1 -1
  31. package/dist/v2/dashboard-analytics/chart/Chart.scss.js +1 -1
  32. package/dist/v2/dashboard-analytics/metric-card/MetricCard.scss.js +1 -1
  33. package/dist/v2/dashboard-analytics/venue-card/VenueCard.scss.js +1 -1
  34. package/dist/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.scss.js +1 -1
  35. package/dist/v2/icons/index.js +1 -16
  36. package/dist/v2/index.d.ts +0 -4
  37. package/dist/v2/index.d.ts.map +1 -1
  38. package/dist/v2/navigation/DashboardLayout/AdminSidebar.scss.js +1 -1
  39. package/dist/v2/navigation/DashboardLayout/DashboardLayout.scss.js +1 -1
  40. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.scss.js +1 -1
  41. package/dist/v2/navigation/DashboardLayout/TopNavigation.scss.js +1 -1
  42. package/dist/v2/pages/Settings/SettingsTabs.scss.js +1 -1
  43. package/dist/v2/pages/Settings/components/SidebarCustomisation.js +0 -3
  44. package/dist/v2/pages/Settings/components/SidebarCustomisation.scss.js +1 -1
  45. package/dist/v2/pages/Settings/components/SidebarNavItem.js +0 -3
  46. package/dist/v2/pages/auth/AuthLayout/AuthLayout.scss.js +1 -1
  47. package/dist/v2/styles/form/NewInput.scss.js +1 -1
  48. package/package.json +6 -6
  49. package/rollup.config.js +16 -2
  50. package/src/iframe/payment/payment-status-page/PaymentStatusPage.tsx +1 -1
  51. package/src/product-set/form/ProductsControl.tsx +2 -1
  52. package/src/v2/components/DataTable/DataTable.tsx +23 -1
  53. package/src/v2/components/Modal/DeleteModal.tsx +12 -20
  54. package/src/v2/components/Toggle/Toggle.tsx +6 -5
  55. package/src/v2/index.ts +0 -73
  56. package/dist/v2/shadcn/components/ui/accordion.d.ts +0 -8
  57. package/dist/v2/shadcn/components/ui/accordion.d.ts.map +0 -1
  58. package/dist/v2/shadcn/components/ui/alert-dialog.d.ts +0 -21
  59. package/dist/v2/shadcn/components/ui/alert-dialog.d.ts.map +0 -1
  60. package/dist/v2/shadcn/components/ui/alert.d.ts +0 -9
  61. package/dist/v2/shadcn/components/ui/alert.d.ts.map +0 -1
  62. package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts +0 -4
  63. package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts.map +0 -1
  64. package/dist/v2/shadcn/components/ui/avatar.d.ts +0 -7
  65. package/dist/v2/shadcn/components/ui/avatar.d.ts.map +0 -1
  66. package/dist/v2/shadcn/components/ui/badge.d.ts +0 -10
  67. package/dist/v2/shadcn/components/ui/badge.d.ts.map +0 -1
  68. package/dist/v2/shadcn/components/ui/breadcrumb.d.ts +0 -20
  69. package/dist/v2/shadcn/components/ui/breadcrumb.d.ts.map +0 -1
  70. package/dist/v2/shadcn/components/ui/button.d.ts +0 -14
  71. package/dist/v2/shadcn/components/ui/button.d.ts.map +0 -1
  72. package/dist/v2/shadcn/components/ui/calendar.d.ts +0 -9
  73. package/dist/v2/shadcn/components/ui/calendar.d.ts.map +0 -1
  74. package/dist/v2/shadcn/components/ui/card.d.ts +0 -9
  75. package/dist/v2/shadcn/components/ui/card.d.ts.map +0 -1
  76. package/dist/v2/shadcn/components/ui/carousel.d.ts +0 -19
  77. package/dist/v2/shadcn/components/ui/carousel.d.ts.map +0 -1
  78. package/dist/v2/shadcn/components/ui/checkbox.d.ts +0 -6
  79. package/dist/v2/shadcn/components/ui/checkbox.d.ts.map +0 -1
  80. package/dist/v2/shadcn/components/ui/checkbox.js +0 -115
  81. package/dist/v2/shadcn/components/ui/checkbox.scss.js +0 -6
  82. package/dist/v2/shadcn/components/ui/collapsible.d.ts +0 -6
  83. package/dist/v2/shadcn/components/ui/collapsible.d.ts.map +0 -1
  84. package/dist/v2/shadcn/components/ui/command.d.ts +0 -83
  85. package/dist/v2/shadcn/components/ui/command.d.ts.map +0 -1
  86. package/dist/v2/shadcn/components/ui/context-menu.d.ts +0 -28
  87. package/dist/v2/shadcn/components/ui/context-menu.d.ts.map +0 -1
  88. package/dist/v2/shadcn/components/ui/dialog.d.ts +0 -20
  89. package/dist/v2/shadcn/components/ui/dialog.d.ts.map +0 -1
  90. package/dist/v2/shadcn/components/ui/dialog.js +0 -169
  91. package/dist/v2/shadcn/components/ui/drawer.d.ts +0 -23
  92. package/dist/v2/shadcn/components/ui/drawer.d.ts.map +0 -1
  93. package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts +0 -28
  94. package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts.map +0 -1
  95. package/dist/v2/shadcn/components/ui/form.d.ts +0 -24
  96. package/dist/v2/shadcn/components/ui/form.d.ts.map +0 -1
  97. package/dist/v2/shadcn/components/ui/hover-card.d.ts +0 -7
  98. package/dist/v2/shadcn/components/ui/hover-card.d.ts.map +0 -1
  99. package/dist/v2/shadcn/components/ui/input-otp.d.ts +0 -35
  100. package/dist/v2/shadcn/components/ui/input-otp.d.ts.map +0 -1
  101. package/dist/v2/shadcn/components/ui/input.d.ts +0 -6
  102. package/dist/v2/shadcn/components/ui/input.d.ts.map +0 -1
  103. package/dist/v2/shadcn/components/ui/label.d.ts +0 -6
  104. package/dist/v2/shadcn/components/ui/label.d.ts.map +0 -1
  105. package/dist/v2/shadcn/components/ui/menubar.d.ts +0 -34
  106. package/dist/v2/shadcn/components/ui/menubar.d.ts.map +0 -1
  107. package/dist/v2/shadcn/components/ui/navigation-menu.d.ts +0 -13
  108. package/dist/v2/shadcn/components/ui/navigation-menu.d.ts.map +0 -1
  109. package/dist/v2/shadcn/components/ui/pagination.d.ts +0 -29
  110. package/dist/v2/shadcn/components/ui/pagination.d.ts.map +0 -1
  111. package/dist/v2/shadcn/components/ui/popover.d.ts +0 -7
  112. package/dist/v2/shadcn/components/ui/popover.d.ts.map +0 -1
  113. package/dist/v2/shadcn/components/ui/progress.d.ts +0 -5
  114. package/dist/v2/shadcn/components/ui/progress.d.ts.map +0 -1
  115. package/dist/v2/shadcn/components/ui/radio-card.d.ts +0 -12
  116. package/dist/v2/shadcn/components/ui/radio-card.d.ts.map +0 -1
  117. package/dist/v2/shadcn/components/ui/radio-group.d.ts +0 -6
  118. package/dist/v2/shadcn/components/ui/radio-group.d.ts.map +0 -1
  119. package/dist/v2/shadcn/components/ui/scroll-area.d.ts +0 -6
  120. package/dist/v2/shadcn/components/ui/scroll-area.d.ts.map +0 -1
  121. package/dist/v2/shadcn/components/ui/select.d.ts +0 -14
  122. package/dist/v2/shadcn/components/ui/select.d.ts.map +0 -1
  123. package/dist/v2/shadcn/components/ui/separator.d.ts +0 -5
  124. package/dist/v2/shadcn/components/ui/separator.d.ts.map +0 -1
  125. package/dist/v2/shadcn/components/ui/sheet.d.ts +0 -26
  126. package/dist/v2/shadcn/components/ui/sheet.d.ts.map +0 -1
  127. package/dist/v2/shadcn/components/ui/sidebar.d.ts +0 -67
  128. package/dist/v2/shadcn/components/ui/sidebar.d.ts.map +0 -1
  129. package/dist/v2/shadcn/components/ui/skeleton.d.ts +0 -3
  130. package/dist/v2/shadcn/components/ui/skeleton.d.ts.map +0 -1
  131. package/dist/v2/shadcn/components/ui/slider.d.ts +0 -5
  132. package/dist/v2/shadcn/components/ui/slider.d.ts.map +0 -1
  133. package/dist/v2/shadcn/components/ui/switch.d.ts +0 -6
  134. package/dist/v2/shadcn/components/ui/switch.d.ts.map +0 -1
  135. package/dist/v2/shadcn/components/ui/switch.js +0 -115
  136. package/dist/v2/shadcn/components/ui/switch.scss.js +0 -6
  137. package/dist/v2/shadcn/components/ui/table-pagination.d.ts +0 -11
  138. package/dist/v2/shadcn/components/ui/table-pagination.d.ts.map +0 -1
  139. package/dist/v2/shadcn/components/ui/table.d.ts +0 -11
  140. package/dist/v2/shadcn/components/ui/table.d.ts.map +0 -1
  141. package/dist/v2/shadcn/components/ui/tabs.d.ts +0 -8
  142. package/dist/v2/shadcn/components/ui/tabs.d.ts.map +0 -1
  143. package/dist/v2/shadcn/components/ui/textarea.d.ts +0 -6
  144. package/dist/v2/shadcn/components/ui/textarea.d.ts.map +0 -1
  145. package/dist/v2/shadcn/components/ui/toast.d.ts +0 -16
  146. package/dist/v2/shadcn/components/ui/toast.d.ts.map +0 -1
  147. package/dist/v2/shadcn/components/ui/toaster.d.ts +0 -2
  148. package/dist/v2/shadcn/components/ui/toaster.d.ts.map +0 -1
  149. package/dist/v2/shadcn/components/ui/toggle-group.d.ts +0 -13
  150. package/dist/v2/shadcn/components/ui/toggle-group.d.ts.map +0 -1
  151. package/dist/v2/shadcn/components/ui/toggle.d.ts +0 -13
  152. package/dist/v2/shadcn/components/ui/toggle.d.ts.map +0 -1
  153. package/dist/v2/shadcn/components/ui/tooltip.d.ts +0 -8
  154. package/dist/v2/shadcn/components/ui/tooltip.d.ts.map +0 -1
  155. package/dist/v2/shadcn/components/ui/use-toast.d.ts +0 -3
  156. package/dist/v2/shadcn/components/ui/use-toast.d.ts.map +0 -1
  157. package/dist/v2/shadcn/hooks/use-mobile.d.ts +0 -2
  158. package/dist/v2/shadcn/hooks/use-mobile.d.ts.map +0 -1
  159. package/dist/v2/shadcn/hooks/use-toast.d.ts +0 -45
  160. package/dist/v2/shadcn/hooks/use-toast.d.ts.map +0 -1
  161. package/dist/v2/shadcn/index.d.ts +0 -20
  162. package/dist/v2/shadcn/index.d.ts.map +0 -1
  163. package/dist/v2/shadcn/lib/utils.d.ts +0 -3
  164. package/dist/v2/shadcn/lib/utils.d.ts.map +0 -1
  165. package/dist/v2/shadcn/lib/utils.js +0 -11
  166. package/dist/v2/shadcn/styles/globals.css +0 -112
  167. package/src/v2/shadcn/_reference/AccountManagerCard.tsx +0 -45
  168. package/src/v2/shadcn/_reference/AffiliatesTable.tsx +0 -178
  169. package/src/v2/shadcn/_reference/AuditArchive.tsx +0 -165
  170. package/src/v2/shadcn/_reference/AuditContent.tsx +0 -270
  171. package/src/v2/shadcn/_reference/AutomationsGeneralSettings.tsx +0 -251
  172. package/src/v2/shadcn/_reference/AvatarUpload.tsx +0 -150
  173. package/src/v2/shadcn/_reference/BookingsSummaryCard.tsx +0 -268
  174. package/src/v2/shadcn/_reference/CodeCleanUpAudit.tsx +0 -274
  175. package/src/v2/shadcn/_reference/CompaniesTable.tsx +0 -387
  176. package/src/v2/shadcn/_reference/ComponentAudit.tsx +0 -239
  177. package/src/v2/shadcn/_reference/ConfigureSettingsCard.tsx +0 -95
  178. package/src/v2/shadcn/_reference/CustomerCard.tsx +0 -155
  179. package/src/v2/shadcn/_reference/DashboardCards.tsx +0 -50
  180. package/src/v2/shadcn/_reference/DashboardFooter.tsx +0 -18
  181. package/src/v2/shadcn/_reference/DiarySettings.tsx +0 -187
  182. package/src/v2/shadcn/_reference/DiaryView.tsx +0 -998
  183. package/src/v2/shadcn/_reference/EmptyState.tsx +0 -76
  184. package/src/v2/shadcn/_reference/EntityInfoCard.tsx +0 -48
  185. package/src/v2/shadcn/_reference/ExistingUserAssignments.tsx +0 -131
  186. package/src/v2/shadcn/_reference/FeatureToggle.tsx +0 -72
  187. package/src/v2/shadcn/_reference/FlowCard.tsx +0 -170
  188. package/src/v2/shadcn/_reference/FlowsContent.tsx +0 -688
  189. package/src/v2/shadcn/_reference/FlowsGeneralSettings.tsx +0 -27
  190. package/src/v2/shadcn/_reference/GeneralSettings.tsx +0 -33
  191. package/src/v2/shadcn/_reference/InventoryGeneralSettings.tsx +0 -82
  192. package/src/v2/shadcn/_reference/LanguageSelector.tsx +0 -97
  193. package/src/v2/shadcn/_reference/LoadingScreen.tsx +0 -25
  194. package/src/v2/shadcn/_reference/LoadingSpinner.tsx +0 -41
  195. package/src/v2/shadcn/_reference/ManagedClientsList.tsx +0 -121
  196. package/src/v2/shadcn/_reference/NPSScore.tsx +0 -379
  197. package/src/v2/shadcn/_reference/NPSSummaryCard.tsx +0 -181
  198. package/src/v2/shadcn/_reference/NotificationBanner.tsx +0 -129
  199. package/src/v2/shadcn/_reference/NotificationPanel.tsx +0 -208
  200. package/src/v2/shadcn/_reference/OnlineUsersCard.tsx +0 -73
  201. package/src/v2/shadcn/_reference/ProtectedRoute.tsx +0 -39
  202. package/src/v2/shadcn/_reference/ProvidersTable.tsx +0 -353
  203. package/src/v2/shadcn/_reference/QuickAddPanel.tsx +0 -1057
  204. package/src/v2/shadcn/_reference/QuickFilters.tsx +0 -112
  205. package/src/v2/shadcn/_reference/ScheduleView.tsx +0 -410
  206. package/src/v2/shadcn/_reference/ScrollToTop.tsx +0 -14
  207. package/src/v2/shadcn/_reference/SecondaryNav.tsx +0 -50
  208. package/src/v2/shadcn/_reference/SecuritySettings.tsx +0 -258
  209. package/src/v2/shadcn/_reference/SessionDetailView.tsx +0 -294
  210. package/src/v2/shadcn/_reference/Sidebar.tsx +0 -14
  211. package/src/v2/shadcn/_reference/SidebarAwareLayout.tsx +0 -30
  212. package/src/v2/shadcn/_reference/SidebarLabelCustomization.tsx +0 -285
  213. package/src/v2/shadcn/_reference/SimulationBanner.tsx +0 -57
  214. package/src/v2/shadcn/_reference/SortControls.tsx +0 -65
  215. package/src/v2/shadcn/_reference/StatusBadge.tsx +0 -49
  216. package/src/v2/shadcn/_reference/StyleGuideContent.tsx +0 -331
  217. package/src/v2/shadcn/_reference/TableActionMenu.tsx +0 -126
  218. package/src/v2/shadcn/_reference/ThemeProvider.tsx +0 -119
  219. package/src/v2/shadcn/_reference/ThemeSettings.tsx +0 -73
  220. package/src/v2/shadcn/_reference/TopNavigation.tsx +0 -332
  221. package/src/v2/shadcn/_reference/UserActivityHistory.tsx +0 -209
  222. package/src/v2/shadcn/_reference/UserLanguageSettings.tsx +0 -94
  223. package/src/v2/shadcn/_reference/UserPanel.tsx +0 -472
  224. package/src/v2/shadcn/_reference/UsersTable.tsx +0 -1023
  225. package/src/v2/shadcn/_reference/WaiverForm.tsx +0 -301
  226. package/src/v2/shadcn/_reference/WaiversGeneralSettings.tsx +0 -46
  227. package/src/v2/shadcn/_reference/WaiversTable.tsx +0 -290
  228. package/src/v2/shadcn/_reference/WaiversTemplatesSettings.tsx +0 -416
  229. package/src/v2/shadcn/_reference/ai/AIChatPanel.tsx +0 -313
  230. package/src/v2/shadcn/_reference/ai/AIChatSearchBar.tsx +0 -36
  231. package/src/v2/shadcn/_reference/ai/ChatInteractiveBlock.tsx +0 -298
  232. package/src/v2/shadcn/_reference/ai/ChatMessageContent.tsx +0 -40
  233. package/src/v2/shadcn/_reference/ai/parseInteractiveBlocks.ts +0 -142
  234. package/src/v2/shadcn/_reference/auth/AuthLayout.tsx +0 -55
  235. package/src/v2/shadcn/_reference/auth/CreatePasswordForm.tsx +0 -285
  236. package/src/v2/shadcn/_reference/auth/CreatePasswordPanel.tsx +0 -20
  237. package/src/v2/shadcn/_reference/auth/LoginFooter.tsx +0 -14
  238. package/src/v2/shadcn/_reference/auth/LoginForm.tsx +0 -205
  239. package/src/v2/shadcn/_reference/auth/LoginPanel.tsx +0 -41
  240. package/src/v2/shadcn/_reference/auth/ResetPasswordForm.tsx +0 -102
  241. package/src/v2/shadcn/_reference/auth/ResetPasswordPanel.tsx +0 -20
  242. package/src/v2/shadcn/_reference/auth/VerifyEmailForm.tsx +0 -95
  243. package/src/v2/shadcn/_reference/auth/VerifyEmailPanel.tsx +0 -20
  244. package/src/v2/shadcn/_reference/email/EmailAttachment.tsx +0 -119
  245. package/src/v2/shadcn/_reference/email/EmailAutomation.tsx +0 -92
  246. package/src/v2/shadcn/_reference/email/EmailPlaceholders.tsx +0 -64
  247. package/src/v2/shadcn/_reference/email/UnlayerEmailEditor.tsx +0 -41
  248. package/src/v2/shadcn/_reference/email/emailTemplateData.ts +0 -53
  249. package/src/v2/shadcn/_reference/emptyStateIcons.tsx +0 -103
  250. package/src/v2/shadcn/_reference/games/MazeGame.tsx +0 -394
  251. package/src/v2/shadcn/_reference/games/RunnerGame.tsx +0 -497
  252. package/src/v2/shadcn/_reference/logos/BookedLogoFull.tsx +0 -36
  253. package/src/v2/shadcn/_reference/logos/BookedLogoMark.tsx +0 -31
  254. package/src/v2/shadcn/_reference/logos/BookedLogoNew.tsx +0 -36
  255. package/src/v2/shadcn/_reference/pricing/DynamicPricingRulesEditor.tsx +0 -401
  256. package/src/v2/shadcn/_reference/pricing/DynamicPricingTierCard.tsx +0 -77
  257. package/src/v2/shadcn/_reference/pricing/DynamicPricingTiersList.tsx +0 -218
  258. package/src/v2/shadcn/_reference/pricing/PricingCalendar.tsx +0 -810
  259. package/src/v2/shadcn/_reference/pricing/PricingPeriodCard.tsx +0 -152
  260. package/src/v2/shadcn/_reference/pricing/PricingPeriodForm.tsx +0 -377
  261. package/src/v2/shadcn/_reference/pricing/PricingPeriodsList.tsx +0 -213
  262. package/src/v2/shadcn/_reference/pricing/getRuleSummary.ts +0 -39
  263. package/src/v2/shadcn/_reference/products/AvailabilityRulesSection.tsx +0 -184
  264. package/src/v2/shadcn/_reference/products/AvailabilitySection.tsx +0 -677
  265. package/src/v2/shadcn/_reference/products/BookingTypeConfigOptions.tsx +0 -40
  266. package/src/v2/shadcn/_reference/products/CapacityPeriodsSection.tsx +0 -238
  267. package/src/v2/shadcn/_reference/products/DynamicPricingTiersSection.tsx +0 -131
  268. package/src/v2/shadcn/_reference/products/GiftCardOrdersTab.tsx +0 -192
  269. package/src/v2/shadcn/_reference/products/GiftCardSettings.tsx +0 -342
  270. package/src/v2/shadcn/_reference/products/PackageProductsSection.tsx +0 -322
  271. package/src/v2/shadcn/_reference/products/PricingSection.tsx +0 -173
  272. package/src/v2/shadcn/_reference/products/ProductTypeFields.tsx +0 -353
  273. package/src/v2/shadcn/_reference/products/ProductTypeIcon.tsx +0 -95
  274. package/src/v2/shadcn/_reference/products/VariablePricingSection.tsx +0 -140
  275. package/src/v2/shadcn/_reference/products/productTypeConfig.ts +0 -182
  276. package/src/v2/shadcn/_reference/shared/BackButton.tsx +0 -50
  277. package/src/v2/shadcn/_reference/shared/CancelConfirmationDialog.tsx +0 -18
  278. package/src/v2/shadcn/_reference/shared/ConfirmationDialog.tsx +0 -136
  279. package/src/v2/shadcn/_reference/shared/DeleteConfirmationDialog.tsx +0 -18
  280. package/src/v2/shadcn/_reference/shared/DeleteEntityPage.tsx +0 -221
  281. package/src/v2/shadcn/_reference/shared/SidebarIcons.tsx +0 -108
  282. package/src/v2/shadcn/_reference/shared/UnifiedSidebar.tsx +0 -722
  283. package/src/v2/shadcn/_reference/tables/BulkActionsBar.tsx +0 -68
  284. package/src/v2/shadcn/_reference/tables/DataTable.tsx +0 -221
  285. package/src/v2/shadcn/_reference/tables/TableControls.tsx +0 -94
  286. package/src/v2/shadcn/_reference/tables/index.ts +0 -3
  287. package/src/v2/shadcn/_reference/tables/types.ts +0 -79
  288. package/src/v2/shadcn/_reference/zones/LegacyZoneSettings.tsx +0 -299
  289. package/src/v2/shadcn/components/ui/accordion.stories.tsx +0 -63
  290. package/src/v2/shadcn/components/ui/accordion.tsx +0 -52
  291. package/src/v2/shadcn/components/ui/alert-dialog.stories.tsx +0 -44
  292. package/src/v2/shadcn/components/ui/alert-dialog.tsx +0 -104
  293. package/src/v2/shadcn/components/ui/alert.stories.tsx +0 -44
  294. package/src/v2/shadcn/components/ui/alert.tsx +0 -43
  295. package/src/v2/shadcn/components/ui/aspect-ratio.stories.tsx +0 -46
  296. package/src/v2/shadcn/components/ui/aspect-ratio.tsx +0 -5
  297. package/src/v2/shadcn/components/ui/avatar.stories.tsx +0 -39
  298. package/src/v2/shadcn/components/ui/avatar.tsx +0 -38
  299. package/src/v2/shadcn/components/ui/badge.stories.tsx +0 -17
  300. package/src/v2/shadcn/components/ui/badge.tsx +0 -30
  301. package/src/v2/shadcn/components/ui/breadcrumb.stories.tsx +0 -91
  302. package/src/v2/shadcn/components/ui/breadcrumb.tsx +0 -90
  303. package/src/v2/shadcn/components/ui/button.stories.tsx +0 -20
  304. package/src/v2/shadcn/components/ui/button.tsx +0 -60
  305. package/src/v2/shadcn/components/ui/calendar.stories.tsx +0 -61
  306. package/src/v2/shadcn/components/ui/calendar.tsx +0 -54
  307. package/src/v2/shadcn/components/ui/card.stories.tsx +0 -37
  308. package/src/v2/shadcn/components/ui/card.tsx +0 -43
  309. package/src/v2/shadcn/components/ui/carousel.stories.tsx +0 -92
  310. package/src/v2/shadcn/components/ui/carousel.tsx +0 -224
  311. package/src/v2/shadcn/components/ui/checkbox.scss +0 -38
  312. package/src/v2/shadcn/components/ui/checkbox.stories.tsx +0 -23
  313. package/src/v2/shadcn/components/ui/checkbox.tsx +0 -24
  314. package/src/v2/shadcn/components/ui/collapsible.stories.tsx +0 -59
  315. package/src/v2/shadcn/components/ui/collapsible.tsx +0 -9
  316. package/src/v2/shadcn/components/ui/command.stories.tsx +0 -70
  317. package/src/v2/shadcn/components/ui/command.tsx +0 -132
  318. package/src/v2/shadcn/components/ui/context-menu.stories.tsx +0 -72
  319. package/src/v2/shadcn/components/ui/context-menu.tsx +0 -178
  320. package/src/v2/shadcn/components/ui/dialog.stories.tsx +0 -67
  321. package/src/v2/shadcn/components/ui/dialog.tsx +0 -95
  322. package/src/v2/shadcn/components/ui/drawer.stories.tsx +0 -50
  323. package/src/v2/shadcn/components/ui/drawer.tsx +0 -87
  324. package/src/v2/shadcn/components/ui/dropdown-menu.stories.tsx +0 -73
  325. package/src/v2/shadcn/components/ui/dropdown-menu.tsx +0 -179
  326. package/src/v2/shadcn/components/ui/form.stories.tsx +0 -105
  327. package/src/v2/shadcn/components/ui/form.tsx +0 -129
  328. package/src/v2/shadcn/components/ui/hover-card.stories.tsx +0 -35
  329. package/src/v2/shadcn/components/ui/hover-card.tsx +0 -27
  330. package/src/v2/shadcn/components/ui/input-otp.stories.tsx +0 -72
  331. package/src/v2/shadcn/components/ui/input-otp.tsx +0 -61
  332. package/src/v2/shadcn/components/ui/input.stories.tsx +0 -16
  333. package/src/v2/shadcn/components/ui/input.tsx +0 -25
  334. package/src/v2/shadcn/components/ui/label.stories.tsx +0 -13
  335. package/src/v2/shadcn/components/ui/label.tsx +0 -17
  336. package/src/v2/shadcn/components/ui/menubar.stories.tsx +0 -86
  337. package/src/v2/shadcn/components/ui/menubar.tsx +0 -207
  338. package/src/v2/shadcn/components/ui/navigation-menu.stories.tsx +0 -68
  339. package/src/v2/shadcn/components/ui/navigation-menu.tsx +0 -120
  340. package/src/v2/shadcn/components/ui/pagination.stories.tsx +0 -78
  341. package/src/v2/shadcn/components/ui/pagination.tsx +0 -81
  342. package/src/v2/shadcn/components/ui/popover.stories.tsx +0 -44
  343. package/src/v2/shadcn/components/ui/popover.tsx +0 -29
  344. package/src/v2/shadcn/components/ui/progress.stories.tsx +0 -17
  345. package/src/v2/shadcn/components/ui/progress.tsx +0 -23
  346. package/src/v2/shadcn/components/ui/radio-card.stories.tsx +0 -68
  347. package/src/v2/shadcn/components/ui/radio-card.tsx +0 -52
  348. package/src/v2/shadcn/components/ui/radio-group.stories.tsx +0 -77
  349. package/src/v2/shadcn/components/ui/radio-group.tsx +0 -35
  350. package/src/v2/shadcn/components/ui/scroll-area.stories.tsx +0 -56
  351. package/src/v2/shadcn/components/ui/scroll-area.tsx +0 -38
  352. package/src/v2/shadcn/components/ui/select.stories.tsx +0 -60
  353. package/src/v2/shadcn/components/ui/select.tsx +0 -148
  354. package/src/v2/shadcn/components/ui/separator.stories.tsx +0 -30
  355. package/src/v2/shadcn/components/ui/separator.tsx +0 -20
  356. package/src/v2/shadcn/components/ui/sheet.stories.tsx +0 -115
  357. package/src/v2/shadcn/components/ui/sheet.tsx +0 -107
  358. package/src/v2/shadcn/components/ui/sidebar.stories.tsx +0 -167
  359. package/src/v2/shadcn/components/ui/sidebar.tsx +0 -637
  360. package/src/v2/shadcn/components/ui/skeleton.stories.tsx +0 -36
  361. package/src/v2/shadcn/components/ui/skeleton.tsx +0 -7
  362. package/src/v2/shadcn/components/ui/slider.stories.tsx +0 -16
  363. package/src/v2/shadcn/components/ui/slider.tsx +0 -23
  364. package/src/v2/shadcn/components/ui/switch.scss +0 -63
  365. package/src/v2/shadcn/components/ui/switch.stories.tsx +0 -23
  366. package/src/v2/shadcn/components/ui/switch.tsx +0 -24
  367. package/src/v2/shadcn/components/ui/table-pagination.stories.tsx +0 -81
  368. package/src/v2/shadcn/components/ui/table-pagination.tsx +0 -61
  369. package/src/v2/shadcn/components/ui/table.stories.tsx +0 -40
  370. package/src/v2/shadcn/components/ui/table.tsx +0 -72
  371. package/src/v2/shadcn/components/ui/tabs.stories.tsx +0 -85
  372. package/src/v2/shadcn/components/ui/tabs.tsx +0 -53
  373. package/src/v2/shadcn/components/ui/textarea.stories.tsx +0 -15
  374. package/src/v2/shadcn/components/ui/textarea.tsx +0 -21
  375. package/src/v2/shadcn/components/ui/toast.stories.tsx +0 -77
  376. package/src/v2/shadcn/components/ui/toast.tsx +0 -111
  377. package/src/v2/shadcn/components/ui/toaster.stories.tsx +0 -46
  378. package/src/v2/shadcn/components/ui/toaster.tsx +0 -24
  379. package/src/v2/shadcn/components/ui/toggle-group.stories.tsx +0 -95
  380. package/src/v2/shadcn/components/ui/toggle-group.tsx +0 -49
  381. package/src/v2/shadcn/components/ui/toggle.stories.tsx +0 -18
  382. package/src/v2/shadcn/components/ui/toggle.tsx +0 -37
  383. package/src/v2/shadcn/components/ui/tooltip.stories.tsx +0 -57
  384. package/src/v2/shadcn/components/ui/tooltip.tsx +0 -28
  385. package/src/v2/shadcn/components/ui/use-toast.ts +0 -3
  386. package/src/v2/shadcn/hooks/use-mobile.tsx +0 -19
  387. package/src/v2/shadcn/hooks/use-toast.ts +0 -184
  388. package/src/v2/shadcn/index.ts +0 -76
  389. package/src/v2/shadcn/lib/utils.ts +0 -6
  390. package/src/v2/shadcn/styles/globals.css +0 -112
@@ -1,379 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { useParams, useLocation } from 'react-router-dom';
3
- import { Button } from './ui/button';
4
- import { Textarea } from './ui/textarea';
5
- import { RadioGroup, RadioGroupItem } from './ui/radio-group';
6
- import { Label } from './ui/label';
7
- import { supabase } from '@/integrations/supabase/client';
8
- import { useAuth } from '@/contexts/AuthContext';
9
- import { useUser } from '@/contexts/UserContext';
10
- import { useSimulation } from '@/contexts/SimulationContext';
11
- import { IconSad, IconBigSmile } from '../../icons';
12
- import { Notification } from './NotificationBanner';
13
-
14
- const NPS_STORAGE_KEY_PREFIX = 'nps_data_';
15
- const THREE_MONTHS_MS = 90 * 24 * 60 * 60 * 1000; // 90 days in milliseconds
16
-
17
- interface NPSData {
18
- submittedAt?: number;
19
- }
20
-
21
- const roleOptions = [
22
- { value: 'owner', label: 'Business Owner' },
23
- { value: 'manager', label: 'Manager' },
24
- { value: 'finance', label: 'Finance' },
25
- { value: 'marketing', label: 'Marketing' },
26
- { value: 'staff', label: 'Staff Member' },
27
- { value: 'other', label: 'Other' },
28
- ];
29
-
30
- interface NPSScoreProps {
31
- onShowNotification?: (notification: Notification) => void;
32
- }
33
-
34
- const NPSScore: React.FC<NPSScoreProps> = ({ onShowNotification }) => {
35
- const { companyId, providerId } = useParams();
36
- const location = useLocation();
37
- const { user } = useAuth();
38
- const { primaryRole } = useUser();
39
- const { isSimulating } = useSimulation();
40
- const [providerUuid, setProviderUuid] = useState<string | null>(null);
41
- const [companyUuid, setCompanyUuid] = useState<string | null>(null);
42
- const [firstName, setFirstName] = useState<string | null>(null);
43
-
44
- // Determine context key based on route
45
- const getContextKey = () => {
46
- const path = location.pathname;
47
- if (path.includes('/venue/') || path.includes('/promoter/')) {
48
- const providerType = path.includes('/venue/') ? 'venue' : 'promoter';
49
- if (companyId) {
50
- return `company_${companyId}_${providerType}_${providerId}`;
51
- }
52
- return `${providerType}_${providerId}`;
53
- }
54
- if (companyId) {
55
- return `company_${companyId}`;
56
- }
57
- return 'default';
58
- };
59
-
60
- const contextKey = getContextKey();
61
- const storageKey = `${NPS_STORAGE_KEY_PREFIX}${contextKey}`;
62
-
63
- const [isVisible, setIsVisible] = useState(false);
64
- const [selectedScore, setSelectedScore] = useState<number | null>(null);
65
- const [reason, setReason] = useState('');
66
- const [role, setRole] = useState('');
67
- const [isSubmitting, setIsSubmitting] = useState(false);
68
- const [errors, setErrors] = useState<{ reason?: string; role?: string }>({});
69
- const [showReasonField, setShowReasonField] = useState(false);
70
-
71
- // Fetch user's first name from profile
72
- useEffect(() => {
73
- const fetchUserName = async () => {
74
- if (!user) return;
75
-
76
- const { data } = await supabase
77
- .from('profiles')
78
- .select('full_name')
79
- .eq('id', user.id)
80
- .maybeSingle();
81
-
82
- if (data?.full_name) {
83
- // Extract first name from full name
84
- const nameParts = data.full_name.trim().split(' ');
85
- setFirstName(nameParts[0]);
86
- }
87
- };
88
-
89
- fetchUserName();
90
- }, [user]);
91
-
92
- // Fetch provider UUID based on friendly ID
93
- useEffect(() => {
94
- const fetchProviderUuid = async () => {
95
- if (!providerId) {
96
- setProviderUuid(null);
97
- return;
98
- }
99
-
100
- const path = location.pathname;
101
- const providerType = path.includes('/venue/') ? 'venue' : 'promoter';
102
-
103
- const { data } = await supabase
104
- .from('providers')
105
- .select('id')
106
- .eq('venue_id', providerId)
107
- .eq('type', providerType)
108
- .maybeSingle();
109
-
110
- setProviderUuid(data?.id || null);
111
- };
112
-
113
- fetchProviderUuid();
114
- }, [providerId, location.pathname]);
115
-
116
- // Fetch company UUID if companyId is a friendly ID (not a UUID)
117
- useEffect(() => {
118
- const fetchCompanyUuid = async () => {
119
- if (!companyId) {
120
- setCompanyUuid(null);
121
- return;
122
- }
123
-
124
- // Check if it's already a UUID
125
- const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
126
- if (uuidPattern.test(companyId)) {
127
- setCompanyUuid(companyId);
128
- return;
129
- }
130
-
131
- const { data } = await supabase
132
- .from('companies')
133
- .select('id')
134
- .eq('company_id', companyId)
135
- .maybeSingle();
136
-
137
- setCompanyUuid(data?.id || null);
138
- };
139
-
140
- fetchCompanyUuid();
141
- }, [companyId]);
142
-
143
- useEffect(() => {
144
- // Reset form state when context changes
145
- setSelectedScore(null);
146
- setReason('');
147
- setRole('');
148
- setErrors({});
149
-
150
- const checkVisibility = async () => {
151
- // For demo: just check if user has submitted for this specific context before
152
- // No time window - show widget if no submission exists for this venue/company
153
-
154
- if (!user) {
155
- setIsVisible(false);
156
- return;
157
- }
158
-
159
- // Build query based on context
160
- let query = supabase
161
- .from('nps_responses')
162
- .select('id')
163
- .eq('user_id', user.id);
164
-
165
- // Check context-specific submission
166
- if (providerUuid) {
167
- query = query.eq('provider_id', providerUuid);
168
- } else if (companyUuid) {
169
- query = query.eq('company_id', companyUuid);
170
- }
171
-
172
- const { data: existingSubmission } = await query.limit(1).maybeSingle();
173
-
174
- // Show widget if no submission exists for this context
175
- setIsVisible(!existingSubmission);
176
- };
177
-
178
- checkVisibility();
179
- }, [user, providerUuid, companyUuid]);
180
-
181
-
182
- const handleSubmit = async () => {
183
- if (!selectedScore || !user) return;
184
-
185
- // Validate required fields - reason required for all scores
186
- const newErrors: { reason?: string; role?: string } = {};
187
- if (!reason.trim()) {
188
- newErrors.reason = 'Please provide a reason for your score';
189
- }
190
- if (!role) {
191
- newErrors.role = 'Please select your role';
192
- }
193
-
194
- if (Object.keys(newErrors).length > 0) {
195
- setErrors(newErrors);
196
- return;
197
- }
198
-
199
- setErrors({});
200
- setIsSubmitting(true);
201
-
202
- try {
203
- // Save NPS response to database
204
- const { error } = await supabase
205
- .from('nps_responses')
206
- .insert({
207
- user_id: user.id,
208
- provider_id: providerUuid,
209
- company_id: companyUuid,
210
- score: selectedScore,
211
- role: role,
212
- reason: reason.trim() || null,
213
- });
214
-
215
- if (error) {
216
- console.error('Error saving NPS response:', error);
217
- onShowNotification?.({
218
- type: 'error',
219
- title: 'Error',
220
- message: 'Failed to submit feedback. Please try again.'
221
- });
222
- setIsSubmitting(false);
223
- return;
224
- }
225
-
226
- // Store submission data in localStorage to hide widget
227
- const data: NPSData = { submittedAt: Date.now() };
228
- localStorage.setItem(storageKey, JSON.stringify(data));
229
-
230
- onShowNotification?.({
231
- type: 'success',
232
- title: 'Thank you!',
233
- message: 'Your feedback has been submitted successfully.'
234
- });
235
- setIsVisible(false);
236
- } catch (err) {
237
- console.error('Error submitting NPS:', err);
238
- onShowNotification?.({
239
- type: 'error',
240
- title: 'Error',
241
- message: 'Failed to submit feedback. Please try again.'
242
- });
243
- } finally {
244
- setIsSubmitting(false);
245
- }
246
- };
247
-
248
- // Hide for super_admin/system_admin unless they are simulating another role
249
- const isAdminRole = primaryRole === 'super_admin' || primaryRole === 'system_admin';
250
- if (!isVisible || (isAdminRole && !isSimulating)) return null;
251
-
252
- return (
253
- <div className="w-full mt-6">
254
- <div className="bg-surface-secondary rounded-2xl p-6 border border-border-primary">
255
- <div className="flex flex-col lg:flex-row gap-6">
256
- {/* Main NPS Content */}
257
- <div className="flex-1">
258
- {/* Question */}
259
- <h3 className="text-label-primary text-lg font-semibold leading-6 mb-4">
260
- {firstName ? `Hey ${firstName}, how` : 'How'} likely would you be to recommend Booked it to a friend or colleague?
261
- </h3>
262
-
263
- {/* Scale labels - both on same row on desktop */}
264
- <div className="flex justify-between items-center mb-3">
265
- <div className="flex items-center gap-2">
266
- <IconSad size={24} className="text-fill-secondary" />
267
- <span className="text-label-secondary text-sm font-medium">Not Likely</span>
268
- </div>
269
- {/* Most Likely - hidden on mobile, shown on desktop */}
270
- <div className="hidden md:flex items-center gap-2">
271
- <span className="text-label-secondary text-sm font-medium">Most Likely</span>
272
- <IconBigSmile size={24} className="text-fill-secondary" />
273
- </div>
274
- </div>
275
-
276
- {/* Score buttons - wrap on mobile */}
277
- <div className="grid grid-cols-5 md:grid-cols-10 gap-2">
278
- {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((score) => (
279
- <button
280
- key={score}
281
- onClick={() => setSelectedScore(score)}
282
- className={`
283
- h-12 rounded-xl text-lg font-semibold transition-colors
284
- ${selectedScore === score
285
- ? 'bg-fill-primary text-label-primary-alt border border-transparent'
286
- : 'bg-surface-primary border border-border-primary text-label-primary hover:bg-surface-primary-hover'
287
- }
288
- `}
289
- >
290
- {score}
291
- </button>
292
- ))}
293
- </div>
294
-
295
- {/* Most Likely label - only shown on mobile below numbers */}
296
- <div className="flex md:hidden items-center gap-2 justify-end mt-3">
297
- <span className="text-label-secondary text-sm font-medium">Most Likely</span>
298
- <IconBigSmile size={24} className="text-fill-secondary" />
299
- </div>
300
- </div>
301
-
302
- </div>
303
-
304
- {/* Expanded section after score selection */}
305
- {selectedScore !== null && (
306
- <div className="space-y-4 mt-4 animate-in fade-in slide-in-from-top-2 duration-200">
307
- {/* Reason textarea - required for all scores */}
308
- <div>
309
- <label className="block text-label-primary text-sm font-medium mb-2">
310
- Reason for this score?
311
- </label>
312
- <Textarea
313
- value={reason}
314
- onChange={(e) => {
315
- setReason(e.target.value);
316
- if (errors.reason) setErrors(prev => ({ ...prev, reason: undefined }));
317
- }}
318
- placeholder=""
319
- className={`min-h-[100px] bg-surface-primary border-border-primary resize-y ${errors.reason ? 'border-fill-danger' : ''}`}
320
- />
321
- {errors.reason ? (
322
- <p className="text-fill-danger text-sm mt-1">{errors.reason}</p>
323
- ) : (
324
- <p className="text-label-secondary text-sm mt-1">
325
- Help us improve by explaining your score.
326
- </p>
327
- )}
328
- </div>
329
-
330
- {/* Role selection - 2 column radio layout */}
331
- <div className="pt-4">
332
- <label className="block text-label-primary text-sm font-medium mb-3">
333
- The role that best describes you?
334
- </label>
335
- <RadioGroup
336
- value={role}
337
- onValueChange={(val) => {
338
- setRole(val);
339
- if (errors.role) setErrors(prev => ({ ...prev, role: undefined }));
340
- }}
341
- className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3"
342
- >
343
- {roleOptions.map((option) => (
344
- <div key={option.value} className="flex items-center space-x-2">
345
- <RadioGroupItem
346
- value={option.value}
347
- id={`role-${option.value}`}
348
- className="border-border-primary text-fill-primary"
349
- />
350
- <Label
351
- htmlFor={`role-${option.value}`}
352
- className="text-label-primary text-sm font-normal cursor-pointer"
353
- >
354
- {option.label}
355
- </Label>
356
- </div>
357
- ))}
358
- </RadioGroup>
359
- {errors.role && (
360
- <p className="text-fill-danger text-sm mt-1">{errors.role}</p>
361
- )}
362
- </div>
363
-
364
- {/* Submit button */}
365
- <Button
366
- onClick={handleSubmit}
367
- disabled={isSubmitting}
368
- className="bg-surface-action hover:bg-surface-action-hover text-label-primary-alt font-semibold px-6"
369
- >
370
- {isSubmitting ? 'Submitting...' : 'Submit'}
371
- </Button>
372
- </div>
373
- )}
374
- </div>
375
- </div>
376
- );
377
- };
378
-
379
- export default NPSScore;
@@ -1,181 +0,0 @@
1
- import React, { useState, useEffect, useMemo } from 'react';
2
- import { useNavigate } from 'react-router-dom';
3
- import { subDays } from 'date-fns';
4
- import { supabase } from '@/integrations/supabase/client';
5
- import { IconTrendUp, IconTrendDown, IconMinus } from '../../icons';
6
-
7
- interface NPSResponse {
8
- id: string;
9
- score: number;
10
- created_at: string;
11
- }
12
-
13
- interface NPSSummaryCardProps {
14
- className?: string;
15
- linkTo?: string;
16
- }
17
-
18
- const NPSSummaryCard: React.FC<NPSSummaryCardProps> = ({ className = '', linkTo }) => {
19
- const navigate = useNavigate();
20
- const [responses, setResponses] = useState<NPSResponse[]>([]);
21
- const [loading, setLoading] = useState(true);
22
- const [trend, setTrend] = useState<'up' | 'down' | 'neutral' | null>(null);
23
- const [trendLoading, setTrendLoading] = useState(true);
24
-
25
- useEffect(() => {
26
- fetchData();
27
- fetchTrend();
28
- }, []);
29
-
30
- const fetchData = async () => {
31
- setLoading(true);
32
-
33
- const { data, error } = await supabase
34
- .from('nps_responses')
35
- .select('id, score, created_at')
36
- .order('created_at', { ascending: false });
37
-
38
- if (error) {
39
- console.error('Error fetching NPS responses:', error);
40
- setLoading(false);
41
- return;
42
- }
43
-
44
- setResponses(data || []);
45
- setLoading(false);
46
- };
47
-
48
- const fetchTrend = async () => {
49
- setTrendLoading(true);
50
-
51
- const threeMonthsAgo = subDays(new Date(), 90);
52
- const sevenDaysAgo = subDays(new Date(), 7);
53
-
54
- try {
55
- // Fetch all responses from the last 3 months
56
- const { data, error } = await supabase
57
- .from('nps_responses')
58
- .select('score, created_at')
59
- .gte('created_at', threeMonthsAgo.toISOString())
60
- .order('created_at', { ascending: true });
61
-
62
- if (error || !data || data.length < 3) {
63
- // Need at least 3 responses overall to calculate trend
64
- setTrend(null);
65
- setTrendLoading(false);
66
- return;
67
- }
68
-
69
- // Calculate overall 3-month average as baseline
70
- const overallAvg = data.reduce((sum, r) => sum + r.score, 0) / data.length;
71
-
72
- // Get responses from the last 7 days
73
- const recentResponses = data.filter(r => new Date(r.created_at) >= sevenDaysAgo);
74
-
75
- // Need at least 3 recent responses to determine trend
76
- if (recentResponses.length < 3) {
77
- setTrend('neutral'); // Default to steady if not enough recent data
78
- setTrendLoading(false);
79
- return;
80
- }
81
-
82
- // Calculate recent 7-day average
83
- const recentAvg = recentResponses.reduce((sum, r) => sum + r.score, 0) / recentResponses.length;
84
-
85
- // Compare recent vs overall with 0.75 threshold
86
- const difference = recentAvg - overallAvg;
87
- if (difference > 0.75) {
88
- setTrend('up');
89
- } else if (difference < -0.75) {
90
- setTrend('down');
91
- } else {
92
- setTrend('neutral');
93
- }
94
- } catch (err) {
95
- console.error('Error fetching trend data:', err);
96
- setTrend(null);
97
- } finally {
98
- setTrendLoading(false);
99
- }
100
- };
101
-
102
- const npsMetrics = useMemo(() => {
103
- const total = responses.length;
104
- if (total === 0) return { nps: 0, total: 0 };
105
-
106
- const promoters = responses.filter(r => r.score >= 9).length;
107
- const detractors = responses.filter(r => r.score <= 6).length;
108
-
109
- const nps = Math.round(((promoters - detractors) / total) * 100);
110
-
111
- return { nps, total };
112
- }, [responses]);
113
-
114
- const handleClick = () => {
115
- if (linkTo) {
116
- navigate(linkTo);
117
- }
118
- };
119
-
120
- if (loading) {
121
- return (
122
- <div className={`bg-surface-secondary rounded-xl p-4 border border-border-primary ${className}`}>
123
- <p className="text-label-secondary text-sm">Loading NPS data...</p>
124
- </div>
125
- );
126
- }
127
-
128
- return (
129
- <div
130
- className={`bg-surface-secondary rounded-xl p-4 border border-border-primary ${linkTo ? 'cursor-pointer hover:bg-surface-secondary-hover transition-colors' : ''} ${className}`}
131
- onClick={handleClick}
132
- >
133
- <div className="flex justify-between items-center gap-4 h-full">
134
- <div>
135
- <p className="text-label-secondary text-[11px] font-medium uppercase tracking-wide mb-1">NPS Score</p>
136
- <p className="text-label-primary text-3xl font-bold">{npsMetrics.nps}</p>
137
- <p className="text-label-primary text-[13px] mt-2">
138
- from {npsMetrics.total || 0} {npsMetrics.total === 1 ? 'response' : 'responses'}
139
- </p>
140
- </div>
141
-
142
- {/* Trend Section */}
143
- {!trendLoading && trend !== null && (
144
- <div className="flex flex-col items-center justify-center gap-1 pr-4">
145
- <div className={`w-12 h-12 rounded-full flex items-center justify-center ${
146
- trend === 'up' ? 'bg-surface-status-success' :
147
- trend === 'down' ? 'bg-surface-status-error' :
148
- 'bg-surface-tertiary'
149
- }`}>
150
- {trend === 'up' && <IconTrendUp size={24} className="text-fill-status-success" />}
151
- {trend === 'down' && <IconTrendDown size={24} className="text-fill-status-error" />}
152
- {trend === 'neutral' && <IconMinus size={24} className="text-fill-secondary" />}
153
- </div>
154
-
155
- <span className={`text-sm font-semibold ${
156
- trend === 'up' ? 'text-fill-status-success' :
157
- trend === 'down' ? 'text-fill-status-error' :
158
- 'text-label-secondary'
159
- }`}>
160
- {trend === 'up' ? 'Improving' : trend === 'down' ? 'Declining' : 'Steady'}
161
- </span>
162
-
163
- <p className="text-label-secondary text-[10px] font-medium uppercase tracking-wide">3 Month Trend</p>
164
- </div>
165
- )}
166
-
167
- {/* Loading/No data state */}
168
- {(trendLoading || trend === null) && (
169
- <div className="flex flex-col items-center justify-center pr-4">
170
- <span className="text-label-secondary text-sm">
171
- {trendLoading ? 'Loading...' : 'Not enough data'}
172
- </span>
173
- <p className="text-label-secondary text-[10px] font-medium uppercase tracking-wide mt-1">3 Month Trend</p>
174
- </div>
175
- )}
176
- </div>
177
- </div>
178
- );
179
- };
180
-
181
- export default NPSSummaryCard;
@@ -1,129 +0,0 @@
1
- import React, { useEffect, useRef } from 'react';
2
- import { useLocation, useNavigate } from 'react-router-dom';
3
- import { IconTick, IconCross, IconInfoCard, IconArrowRight, IconArrowInternalReturn } from '../../icons';
4
-
5
- export type NotificationType = 'success' | 'error' | 'info';
6
-
7
- export interface Notification {
8
- type: NotificationType;
9
- title: string;
10
- message: string;
11
- action?: {
12
- label: string;
13
- onClick: () => void;
14
- };
15
- }
16
-
17
- interface NotificationBannerProps {
18
- notification: Notification;
19
- onClose: () => void;
20
- showNotificationsLink?: boolean;
21
- autoDismissOnRouteChange?: boolean;
22
- }
23
-
24
- const NotificationBanner: React.FC<NotificationBannerProps> = ({
25
- notification,
26
- onClose,
27
- showNotificationsLink = true,
28
- autoDismissOnRouteChange = true
29
- }) => {
30
- const location = useLocation();
31
- const navigate = useNavigate();
32
- const isSuccess = notification.type === 'success';
33
- const isError = notification.type === 'error';
34
- const isInfo = notification.type === 'info';
35
-
36
- // Use ref to avoid stale closure while not triggering effect re-runs
37
- const onCloseRef = useRef(onClose);
38
- onCloseRef.current = onClose;
39
-
40
- // Auto-dismiss notification when the route actually changes (not on initial mount)
41
- useEffect(() => {
42
- if (!autoDismissOnRouteChange) return;
43
-
44
- const currentPath = location.pathname;
45
- return () => {
46
- if (location.pathname !== currentPath) {
47
- onCloseRef.current();
48
- }
49
- };
50
- }, [location.pathname, autoDismissOnRouteChange]);
51
-
52
- return (
53
- <div
54
- className={`w-full flex items-start gap-4 px-6 py-4 rounded-lg border animate-fade-in mt-4 ${
55
- isSuccess
56
- ? 'bg-surface-status-success border-border-status-success'
57
- : isError
58
- ? 'bg-surface-status-error border-border-status-error'
59
- : 'bg-surface-status-info border-border-status-info'
60
- }`}
61
- >
62
- {/* Icon */}
63
- <div className="flex-shrink-0 mt-0.5">
64
- {isSuccess ? (
65
- <div className="w-[32px] h-[32px] rounded-full bg-success-regular flex items-center justify-center">
66
- <IconTick className="w-4 h-4 fill-fill-white" />
67
- </div>
68
- ) : isError ? (
69
- <div className="w-[32px] h-[32px] rounded-full bg-errors-regular flex items-center justify-center">
70
- <IconCross className="w-4 h-4 fill-fill-white" />
71
- </div>
72
- ) : (
73
- <div className="w-[32px] h-[32px] rounded-full bg-info-regular flex items-center justify-center">
74
- <IconInfoCard className="w-4 h-4 fill-fill-white" />
75
- </div>
76
- )}
77
- </div>
78
-
79
- {/* Content */}
80
- <div className="flex-1 min-w-0">
81
- <h3 className={`text-sm font-semibold mb-0.5 ${
82
- isSuccess ? 'text-label-status-success' : isError ? 'text-label-status-error' : 'text-label-status-info'
83
- }`}>
84
- {notification.title}
85
- </h3>
86
- {notification.message && (
87
- <p className="text-xs text-label-primary">
88
- {notification.message}
89
- </p>
90
- )}
91
- {notification.action && (
92
- <button
93
- onClick={notification.action.onClick}
94
- className="inline-flex items-center text-xs font-semibold text-label-primary transition-opacity hover:opacity-70 mt-2"
95
- >
96
- {notification.action.label}
97
- </button>
98
- )}
99
- </div>
100
-
101
- {/* Action Buttons */}
102
- <div className="flex items-center gap-2 self-center">
103
- {showNotificationsLink && (
104
- <button
105
- onClick={() => navigate('/notifications')}
106
- className={`flex-shrink-0 w-10 h-10 flex items-center justify-center transition-opacity hover:opacity-70 ${
107
- isSuccess ? 'text-label-status-success' : isError ? 'text-label-status-error' : 'text-label-status-info'
108
- }`}
109
- aria-label="View all notifications"
110
- >
111
- <IconArrowInternalReturn className="w-5 h-5" />
112
- </button>
113
- )}
114
-
115
- <button
116
- onClick={onClose}
117
- className={`flex-shrink-0 w-10 h-10 flex items-center justify-center transition-opacity hover:opacity-70 ${
118
- isSuccess ? 'text-label-status-success' : isError ? 'text-label-status-error' : 'text-label-status-info'
119
- }`}
120
- aria-label="Close notification"
121
- >
122
- <IconCross className="w-5 h-5" />
123
- </button>
124
- </div>
125
- </div>
126
- );
127
- };
128
-
129
- export default NotificationBanner;