@licklist/design 0.78.5-dev.105 → 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 (371) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/bitbucket-pipelines.yml +13 -4
  3. package/dist/index.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/DataTable/DataTable.d.ts.map +1 -1
  8. package/dist/v2/components/DataTable/DataTable.js +86 -2
  9. package/dist/v2/components/InputCheckbox/InputCheckbox.scss.js +1 -1
  10. package/dist/v2/components/Modal/DeleteModal.d.ts.map +1 -1
  11. package/dist/v2/components/Modal/DeleteModal.js +13 -11
  12. package/dist/v2/components/Toggle/Toggle.d.ts.map +1 -1
  13. package/dist/v2/components/Toggle/Toggle.js +8 -5
  14. package/dist/v2/components/ZoneCard/ZoneCard.scss.js +1 -1
  15. package/dist/v2/components/index.d.ts +1 -1
  16. package/dist/v2/components/index.d.ts.map +1 -1
  17. package/dist/v2/icons/index.d.ts +4 -0
  18. package/dist/v2/icons/index.d.ts.map +1 -1
  19. package/dist/v2/icons/index.js +47 -16
  20. package/dist/v2/index.d.ts +0 -4
  21. package/dist/v2/index.d.ts.map +1 -1
  22. package/dist/v2/pages/Settings/components/SidebarCustomisation.js +0 -3
  23. package/dist/v2/pages/Settings/components/SidebarNavItem.js +0 -3
  24. package/package.json +6 -6
  25. package/rollup.config.js +16 -2
  26. package/src/iframe/payment/payment-status-page/PaymentStatusPage.tsx +1 -1
  27. package/src/product-set/form/ProductsControl.tsx +2 -1
  28. package/src/v2/components/DataTable/DataTable.tsx +23 -1
  29. package/src/v2/components/InputCheckbox/InputCheckbox.scss +6 -6
  30. package/src/v2/components/Modal/DeleteModal.tsx +12 -20
  31. package/src/v2/components/Toggle/Toggle.tsx +6 -5
  32. package/src/v2/components/ZoneCard/ZoneCard.scss +78 -0
  33. package/src/v2/components/index.ts +1 -0
  34. package/src/v2/icons/index.tsx +10 -0
  35. package/src/v2/index.ts +0 -73
  36. package/src/v2/navigation/Navigation/Navigation.stories.tsx +137 -0
  37. package/dist/v2/shadcn/components/ui/accordion.d.ts +0 -8
  38. package/dist/v2/shadcn/components/ui/accordion.d.ts.map +0 -1
  39. package/dist/v2/shadcn/components/ui/alert-dialog.d.ts +0 -21
  40. package/dist/v2/shadcn/components/ui/alert-dialog.d.ts.map +0 -1
  41. package/dist/v2/shadcn/components/ui/alert.d.ts +0 -9
  42. package/dist/v2/shadcn/components/ui/alert.d.ts.map +0 -1
  43. package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts +0 -4
  44. package/dist/v2/shadcn/components/ui/aspect-ratio.d.ts.map +0 -1
  45. package/dist/v2/shadcn/components/ui/avatar.d.ts +0 -7
  46. package/dist/v2/shadcn/components/ui/avatar.d.ts.map +0 -1
  47. package/dist/v2/shadcn/components/ui/badge.d.ts +0 -10
  48. package/dist/v2/shadcn/components/ui/badge.d.ts.map +0 -1
  49. package/dist/v2/shadcn/components/ui/breadcrumb.d.ts +0 -20
  50. package/dist/v2/shadcn/components/ui/breadcrumb.d.ts.map +0 -1
  51. package/dist/v2/shadcn/components/ui/button.d.ts +0 -14
  52. package/dist/v2/shadcn/components/ui/button.d.ts.map +0 -1
  53. package/dist/v2/shadcn/components/ui/calendar.d.ts +0 -9
  54. package/dist/v2/shadcn/components/ui/calendar.d.ts.map +0 -1
  55. package/dist/v2/shadcn/components/ui/card.d.ts +0 -9
  56. package/dist/v2/shadcn/components/ui/card.d.ts.map +0 -1
  57. package/dist/v2/shadcn/components/ui/carousel.d.ts +0 -19
  58. package/dist/v2/shadcn/components/ui/carousel.d.ts.map +0 -1
  59. package/dist/v2/shadcn/components/ui/checkbox.d.ts +0 -6
  60. package/dist/v2/shadcn/components/ui/checkbox.d.ts.map +0 -1
  61. package/dist/v2/shadcn/components/ui/checkbox.js +0 -115
  62. package/dist/v2/shadcn/components/ui/checkbox.scss.js +0 -6
  63. package/dist/v2/shadcn/components/ui/collapsible.d.ts +0 -6
  64. package/dist/v2/shadcn/components/ui/collapsible.d.ts.map +0 -1
  65. package/dist/v2/shadcn/components/ui/command.d.ts +0 -83
  66. package/dist/v2/shadcn/components/ui/command.d.ts.map +0 -1
  67. package/dist/v2/shadcn/components/ui/context-menu.d.ts +0 -28
  68. package/dist/v2/shadcn/components/ui/context-menu.d.ts.map +0 -1
  69. package/dist/v2/shadcn/components/ui/dialog.d.ts +0 -20
  70. package/dist/v2/shadcn/components/ui/dialog.d.ts.map +0 -1
  71. package/dist/v2/shadcn/components/ui/dialog.js +0 -169
  72. package/dist/v2/shadcn/components/ui/drawer.d.ts +0 -23
  73. package/dist/v2/shadcn/components/ui/drawer.d.ts.map +0 -1
  74. package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts +0 -28
  75. package/dist/v2/shadcn/components/ui/dropdown-menu.d.ts.map +0 -1
  76. package/dist/v2/shadcn/components/ui/form.d.ts +0 -24
  77. package/dist/v2/shadcn/components/ui/form.d.ts.map +0 -1
  78. package/dist/v2/shadcn/components/ui/hover-card.d.ts +0 -7
  79. package/dist/v2/shadcn/components/ui/hover-card.d.ts.map +0 -1
  80. package/dist/v2/shadcn/components/ui/input-otp.d.ts +0 -35
  81. package/dist/v2/shadcn/components/ui/input-otp.d.ts.map +0 -1
  82. package/dist/v2/shadcn/components/ui/input.d.ts +0 -6
  83. package/dist/v2/shadcn/components/ui/input.d.ts.map +0 -1
  84. package/dist/v2/shadcn/components/ui/label.d.ts +0 -6
  85. package/dist/v2/shadcn/components/ui/label.d.ts.map +0 -1
  86. package/dist/v2/shadcn/components/ui/menubar.d.ts +0 -34
  87. package/dist/v2/shadcn/components/ui/menubar.d.ts.map +0 -1
  88. package/dist/v2/shadcn/components/ui/navigation-menu.d.ts +0 -13
  89. package/dist/v2/shadcn/components/ui/navigation-menu.d.ts.map +0 -1
  90. package/dist/v2/shadcn/components/ui/pagination.d.ts +0 -29
  91. package/dist/v2/shadcn/components/ui/pagination.d.ts.map +0 -1
  92. package/dist/v2/shadcn/components/ui/popover.d.ts +0 -7
  93. package/dist/v2/shadcn/components/ui/popover.d.ts.map +0 -1
  94. package/dist/v2/shadcn/components/ui/progress.d.ts +0 -5
  95. package/dist/v2/shadcn/components/ui/progress.d.ts.map +0 -1
  96. package/dist/v2/shadcn/components/ui/radio-card.d.ts +0 -12
  97. package/dist/v2/shadcn/components/ui/radio-card.d.ts.map +0 -1
  98. package/dist/v2/shadcn/components/ui/radio-group.d.ts +0 -6
  99. package/dist/v2/shadcn/components/ui/radio-group.d.ts.map +0 -1
  100. package/dist/v2/shadcn/components/ui/scroll-area.d.ts +0 -6
  101. package/dist/v2/shadcn/components/ui/scroll-area.d.ts.map +0 -1
  102. package/dist/v2/shadcn/components/ui/select.d.ts +0 -14
  103. package/dist/v2/shadcn/components/ui/select.d.ts.map +0 -1
  104. package/dist/v2/shadcn/components/ui/separator.d.ts +0 -5
  105. package/dist/v2/shadcn/components/ui/separator.d.ts.map +0 -1
  106. package/dist/v2/shadcn/components/ui/sheet.d.ts +0 -26
  107. package/dist/v2/shadcn/components/ui/sheet.d.ts.map +0 -1
  108. package/dist/v2/shadcn/components/ui/sidebar.d.ts +0 -67
  109. package/dist/v2/shadcn/components/ui/sidebar.d.ts.map +0 -1
  110. package/dist/v2/shadcn/components/ui/skeleton.d.ts +0 -3
  111. package/dist/v2/shadcn/components/ui/skeleton.d.ts.map +0 -1
  112. package/dist/v2/shadcn/components/ui/slider.d.ts +0 -5
  113. package/dist/v2/shadcn/components/ui/slider.d.ts.map +0 -1
  114. package/dist/v2/shadcn/components/ui/switch.d.ts +0 -6
  115. package/dist/v2/shadcn/components/ui/switch.d.ts.map +0 -1
  116. package/dist/v2/shadcn/components/ui/switch.js +0 -115
  117. package/dist/v2/shadcn/components/ui/switch.scss.js +0 -6
  118. package/dist/v2/shadcn/components/ui/table-pagination.d.ts +0 -11
  119. package/dist/v2/shadcn/components/ui/table-pagination.d.ts.map +0 -1
  120. package/dist/v2/shadcn/components/ui/table.d.ts +0 -11
  121. package/dist/v2/shadcn/components/ui/table.d.ts.map +0 -1
  122. package/dist/v2/shadcn/components/ui/tabs.d.ts +0 -8
  123. package/dist/v2/shadcn/components/ui/tabs.d.ts.map +0 -1
  124. package/dist/v2/shadcn/components/ui/textarea.d.ts +0 -6
  125. package/dist/v2/shadcn/components/ui/textarea.d.ts.map +0 -1
  126. package/dist/v2/shadcn/components/ui/toast.d.ts +0 -16
  127. package/dist/v2/shadcn/components/ui/toast.d.ts.map +0 -1
  128. package/dist/v2/shadcn/components/ui/toaster.d.ts +0 -2
  129. package/dist/v2/shadcn/components/ui/toaster.d.ts.map +0 -1
  130. package/dist/v2/shadcn/components/ui/toggle-group.d.ts +0 -13
  131. package/dist/v2/shadcn/components/ui/toggle-group.d.ts.map +0 -1
  132. package/dist/v2/shadcn/components/ui/toggle.d.ts +0 -13
  133. package/dist/v2/shadcn/components/ui/toggle.d.ts.map +0 -1
  134. package/dist/v2/shadcn/components/ui/tooltip.d.ts +0 -8
  135. package/dist/v2/shadcn/components/ui/tooltip.d.ts.map +0 -1
  136. package/dist/v2/shadcn/components/ui/use-toast.d.ts +0 -3
  137. package/dist/v2/shadcn/components/ui/use-toast.d.ts.map +0 -1
  138. package/dist/v2/shadcn/hooks/use-mobile.d.ts +0 -2
  139. package/dist/v2/shadcn/hooks/use-mobile.d.ts.map +0 -1
  140. package/dist/v2/shadcn/hooks/use-toast.d.ts +0 -45
  141. package/dist/v2/shadcn/hooks/use-toast.d.ts.map +0 -1
  142. package/dist/v2/shadcn/index.d.ts +0 -20
  143. package/dist/v2/shadcn/index.d.ts.map +0 -1
  144. package/dist/v2/shadcn/lib/utils.d.ts +0 -3
  145. package/dist/v2/shadcn/lib/utils.d.ts.map +0 -1
  146. package/dist/v2/shadcn/lib/utils.js +0 -11
  147. package/dist/v2/shadcn/styles/globals.css +0 -112
  148. package/src/v2/shadcn/_reference/AccountManagerCard.tsx +0 -45
  149. package/src/v2/shadcn/_reference/AffiliatesTable.tsx +0 -178
  150. package/src/v2/shadcn/_reference/AuditArchive.tsx +0 -165
  151. package/src/v2/shadcn/_reference/AuditContent.tsx +0 -270
  152. package/src/v2/shadcn/_reference/AutomationsGeneralSettings.tsx +0 -251
  153. package/src/v2/shadcn/_reference/AvatarUpload.tsx +0 -150
  154. package/src/v2/shadcn/_reference/BookingsSummaryCard.tsx +0 -268
  155. package/src/v2/shadcn/_reference/CodeCleanUpAudit.tsx +0 -274
  156. package/src/v2/shadcn/_reference/CompaniesTable.tsx +0 -387
  157. package/src/v2/shadcn/_reference/ComponentAudit.tsx +0 -239
  158. package/src/v2/shadcn/_reference/ConfigureSettingsCard.tsx +0 -95
  159. package/src/v2/shadcn/_reference/CustomerCard.tsx +0 -155
  160. package/src/v2/shadcn/_reference/DashboardCards.tsx +0 -50
  161. package/src/v2/shadcn/_reference/DashboardFooter.tsx +0 -18
  162. package/src/v2/shadcn/_reference/DiarySettings.tsx +0 -187
  163. package/src/v2/shadcn/_reference/DiaryView.tsx +0 -998
  164. package/src/v2/shadcn/_reference/EmptyState.tsx +0 -76
  165. package/src/v2/shadcn/_reference/EntityInfoCard.tsx +0 -48
  166. package/src/v2/shadcn/_reference/ExistingUserAssignments.tsx +0 -131
  167. package/src/v2/shadcn/_reference/FeatureToggle.tsx +0 -72
  168. package/src/v2/shadcn/_reference/FlowCard.tsx +0 -170
  169. package/src/v2/shadcn/_reference/FlowsContent.tsx +0 -688
  170. package/src/v2/shadcn/_reference/FlowsGeneralSettings.tsx +0 -27
  171. package/src/v2/shadcn/_reference/GeneralSettings.tsx +0 -33
  172. package/src/v2/shadcn/_reference/InventoryGeneralSettings.tsx +0 -82
  173. package/src/v2/shadcn/_reference/LanguageSelector.tsx +0 -97
  174. package/src/v2/shadcn/_reference/LoadingScreen.tsx +0 -25
  175. package/src/v2/shadcn/_reference/LoadingSpinner.tsx +0 -41
  176. package/src/v2/shadcn/_reference/ManagedClientsList.tsx +0 -121
  177. package/src/v2/shadcn/_reference/NPSScore.tsx +0 -379
  178. package/src/v2/shadcn/_reference/NPSSummaryCard.tsx +0 -181
  179. package/src/v2/shadcn/_reference/NotificationBanner.tsx +0 -129
  180. package/src/v2/shadcn/_reference/NotificationPanel.tsx +0 -208
  181. package/src/v2/shadcn/_reference/OnlineUsersCard.tsx +0 -73
  182. package/src/v2/shadcn/_reference/ProtectedRoute.tsx +0 -39
  183. package/src/v2/shadcn/_reference/ProvidersTable.tsx +0 -353
  184. package/src/v2/shadcn/_reference/QuickAddPanel.tsx +0 -1057
  185. package/src/v2/shadcn/_reference/QuickFilters.tsx +0 -112
  186. package/src/v2/shadcn/_reference/ScheduleView.tsx +0 -410
  187. package/src/v2/shadcn/_reference/ScrollToTop.tsx +0 -14
  188. package/src/v2/shadcn/_reference/SecondaryNav.tsx +0 -50
  189. package/src/v2/shadcn/_reference/SecuritySettings.tsx +0 -258
  190. package/src/v2/shadcn/_reference/SessionDetailView.tsx +0 -294
  191. package/src/v2/shadcn/_reference/Sidebar.tsx +0 -14
  192. package/src/v2/shadcn/_reference/SidebarAwareLayout.tsx +0 -30
  193. package/src/v2/shadcn/_reference/SidebarLabelCustomization.tsx +0 -285
  194. package/src/v2/shadcn/_reference/SimulationBanner.tsx +0 -57
  195. package/src/v2/shadcn/_reference/SortControls.tsx +0 -65
  196. package/src/v2/shadcn/_reference/StatusBadge.tsx +0 -49
  197. package/src/v2/shadcn/_reference/StyleGuideContent.tsx +0 -331
  198. package/src/v2/shadcn/_reference/TableActionMenu.tsx +0 -126
  199. package/src/v2/shadcn/_reference/ThemeProvider.tsx +0 -119
  200. package/src/v2/shadcn/_reference/ThemeSettings.tsx +0 -73
  201. package/src/v2/shadcn/_reference/TopNavigation.tsx +0 -332
  202. package/src/v2/shadcn/_reference/UserActivityHistory.tsx +0 -209
  203. package/src/v2/shadcn/_reference/UserLanguageSettings.tsx +0 -94
  204. package/src/v2/shadcn/_reference/UserPanel.tsx +0 -472
  205. package/src/v2/shadcn/_reference/UsersTable.tsx +0 -1023
  206. package/src/v2/shadcn/_reference/WaiverForm.tsx +0 -301
  207. package/src/v2/shadcn/_reference/WaiversGeneralSettings.tsx +0 -46
  208. package/src/v2/shadcn/_reference/WaiversTable.tsx +0 -290
  209. package/src/v2/shadcn/_reference/WaiversTemplatesSettings.tsx +0 -416
  210. package/src/v2/shadcn/_reference/ai/AIChatPanel.tsx +0 -313
  211. package/src/v2/shadcn/_reference/ai/AIChatSearchBar.tsx +0 -36
  212. package/src/v2/shadcn/_reference/ai/ChatInteractiveBlock.tsx +0 -298
  213. package/src/v2/shadcn/_reference/ai/ChatMessageContent.tsx +0 -40
  214. package/src/v2/shadcn/_reference/ai/parseInteractiveBlocks.ts +0 -142
  215. package/src/v2/shadcn/_reference/auth/AuthLayout.tsx +0 -55
  216. package/src/v2/shadcn/_reference/auth/CreatePasswordForm.tsx +0 -285
  217. package/src/v2/shadcn/_reference/auth/CreatePasswordPanel.tsx +0 -20
  218. package/src/v2/shadcn/_reference/auth/LoginFooter.tsx +0 -14
  219. package/src/v2/shadcn/_reference/auth/LoginForm.tsx +0 -205
  220. package/src/v2/shadcn/_reference/auth/LoginPanel.tsx +0 -41
  221. package/src/v2/shadcn/_reference/auth/ResetPasswordForm.tsx +0 -102
  222. package/src/v2/shadcn/_reference/auth/ResetPasswordPanel.tsx +0 -20
  223. package/src/v2/shadcn/_reference/auth/VerifyEmailForm.tsx +0 -95
  224. package/src/v2/shadcn/_reference/auth/VerifyEmailPanel.tsx +0 -20
  225. package/src/v2/shadcn/_reference/email/EmailAttachment.tsx +0 -119
  226. package/src/v2/shadcn/_reference/email/EmailAutomation.tsx +0 -92
  227. package/src/v2/shadcn/_reference/email/EmailPlaceholders.tsx +0 -64
  228. package/src/v2/shadcn/_reference/email/UnlayerEmailEditor.tsx +0 -41
  229. package/src/v2/shadcn/_reference/email/emailTemplateData.ts +0 -53
  230. package/src/v2/shadcn/_reference/emptyStateIcons.tsx +0 -103
  231. package/src/v2/shadcn/_reference/games/MazeGame.tsx +0 -394
  232. package/src/v2/shadcn/_reference/games/RunnerGame.tsx +0 -497
  233. package/src/v2/shadcn/_reference/logos/BookedLogoFull.tsx +0 -36
  234. package/src/v2/shadcn/_reference/logos/BookedLogoMark.tsx +0 -31
  235. package/src/v2/shadcn/_reference/logos/BookedLogoNew.tsx +0 -36
  236. package/src/v2/shadcn/_reference/pricing/DynamicPricingRulesEditor.tsx +0 -401
  237. package/src/v2/shadcn/_reference/pricing/DynamicPricingTierCard.tsx +0 -77
  238. package/src/v2/shadcn/_reference/pricing/DynamicPricingTiersList.tsx +0 -218
  239. package/src/v2/shadcn/_reference/pricing/PricingCalendar.tsx +0 -810
  240. package/src/v2/shadcn/_reference/pricing/PricingPeriodCard.tsx +0 -152
  241. package/src/v2/shadcn/_reference/pricing/PricingPeriodForm.tsx +0 -377
  242. package/src/v2/shadcn/_reference/pricing/PricingPeriodsList.tsx +0 -213
  243. package/src/v2/shadcn/_reference/pricing/getRuleSummary.ts +0 -39
  244. package/src/v2/shadcn/_reference/products/AvailabilityRulesSection.tsx +0 -184
  245. package/src/v2/shadcn/_reference/products/AvailabilitySection.tsx +0 -677
  246. package/src/v2/shadcn/_reference/products/BookingTypeConfigOptions.tsx +0 -40
  247. package/src/v2/shadcn/_reference/products/CapacityPeriodsSection.tsx +0 -238
  248. package/src/v2/shadcn/_reference/products/DynamicPricingTiersSection.tsx +0 -131
  249. package/src/v2/shadcn/_reference/products/GiftCardOrdersTab.tsx +0 -192
  250. package/src/v2/shadcn/_reference/products/GiftCardSettings.tsx +0 -342
  251. package/src/v2/shadcn/_reference/products/PackageProductsSection.tsx +0 -322
  252. package/src/v2/shadcn/_reference/products/PricingSection.tsx +0 -173
  253. package/src/v2/shadcn/_reference/products/ProductTypeFields.tsx +0 -353
  254. package/src/v2/shadcn/_reference/products/ProductTypeIcon.tsx +0 -95
  255. package/src/v2/shadcn/_reference/products/VariablePricingSection.tsx +0 -140
  256. package/src/v2/shadcn/_reference/products/productTypeConfig.ts +0 -182
  257. package/src/v2/shadcn/_reference/shared/BackButton.tsx +0 -50
  258. package/src/v2/shadcn/_reference/shared/CancelConfirmationDialog.tsx +0 -18
  259. package/src/v2/shadcn/_reference/shared/ConfirmationDialog.tsx +0 -136
  260. package/src/v2/shadcn/_reference/shared/DeleteConfirmationDialog.tsx +0 -18
  261. package/src/v2/shadcn/_reference/shared/DeleteEntityPage.tsx +0 -221
  262. package/src/v2/shadcn/_reference/shared/SidebarIcons.tsx +0 -108
  263. package/src/v2/shadcn/_reference/shared/UnifiedSidebar.tsx +0 -722
  264. package/src/v2/shadcn/_reference/tables/BulkActionsBar.tsx +0 -68
  265. package/src/v2/shadcn/_reference/tables/DataTable.tsx +0 -221
  266. package/src/v2/shadcn/_reference/tables/TableControls.tsx +0 -94
  267. package/src/v2/shadcn/_reference/tables/index.ts +0 -3
  268. package/src/v2/shadcn/_reference/tables/types.ts +0 -79
  269. package/src/v2/shadcn/_reference/zones/LegacyZoneSettings.tsx +0 -299
  270. package/src/v2/shadcn/components/ui/accordion.stories.tsx +0 -63
  271. package/src/v2/shadcn/components/ui/accordion.tsx +0 -52
  272. package/src/v2/shadcn/components/ui/alert-dialog.stories.tsx +0 -44
  273. package/src/v2/shadcn/components/ui/alert-dialog.tsx +0 -104
  274. package/src/v2/shadcn/components/ui/alert.stories.tsx +0 -44
  275. package/src/v2/shadcn/components/ui/alert.tsx +0 -43
  276. package/src/v2/shadcn/components/ui/aspect-ratio.stories.tsx +0 -46
  277. package/src/v2/shadcn/components/ui/aspect-ratio.tsx +0 -5
  278. package/src/v2/shadcn/components/ui/avatar.stories.tsx +0 -39
  279. package/src/v2/shadcn/components/ui/avatar.tsx +0 -38
  280. package/src/v2/shadcn/components/ui/badge.stories.tsx +0 -17
  281. package/src/v2/shadcn/components/ui/badge.tsx +0 -30
  282. package/src/v2/shadcn/components/ui/breadcrumb.stories.tsx +0 -91
  283. package/src/v2/shadcn/components/ui/breadcrumb.tsx +0 -90
  284. package/src/v2/shadcn/components/ui/button.stories.tsx +0 -20
  285. package/src/v2/shadcn/components/ui/button.tsx +0 -60
  286. package/src/v2/shadcn/components/ui/calendar.stories.tsx +0 -61
  287. package/src/v2/shadcn/components/ui/calendar.tsx +0 -54
  288. package/src/v2/shadcn/components/ui/card.stories.tsx +0 -37
  289. package/src/v2/shadcn/components/ui/card.tsx +0 -43
  290. package/src/v2/shadcn/components/ui/carousel.stories.tsx +0 -92
  291. package/src/v2/shadcn/components/ui/carousel.tsx +0 -224
  292. package/src/v2/shadcn/components/ui/checkbox.scss +0 -38
  293. package/src/v2/shadcn/components/ui/checkbox.stories.tsx +0 -23
  294. package/src/v2/shadcn/components/ui/checkbox.tsx +0 -24
  295. package/src/v2/shadcn/components/ui/collapsible.stories.tsx +0 -59
  296. package/src/v2/shadcn/components/ui/collapsible.tsx +0 -9
  297. package/src/v2/shadcn/components/ui/command.stories.tsx +0 -70
  298. package/src/v2/shadcn/components/ui/command.tsx +0 -132
  299. package/src/v2/shadcn/components/ui/context-menu.stories.tsx +0 -72
  300. package/src/v2/shadcn/components/ui/context-menu.tsx +0 -178
  301. package/src/v2/shadcn/components/ui/dialog.stories.tsx +0 -67
  302. package/src/v2/shadcn/components/ui/dialog.tsx +0 -95
  303. package/src/v2/shadcn/components/ui/drawer.stories.tsx +0 -50
  304. package/src/v2/shadcn/components/ui/drawer.tsx +0 -87
  305. package/src/v2/shadcn/components/ui/dropdown-menu.stories.tsx +0 -73
  306. package/src/v2/shadcn/components/ui/dropdown-menu.tsx +0 -179
  307. package/src/v2/shadcn/components/ui/form.stories.tsx +0 -105
  308. package/src/v2/shadcn/components/ui/form.tsx +0 -129
  309. package/src/v2/shadcn/components/ui/hover-card.stories.tsx +0 -35
  310. package/src/v2/shadcn/components/ui/hover-card.tsx +0 -27
  311. package/src/v2/shadcn/components/ui/input-otp.stories.tsx +0 -72
  312. package/src/v2/shadcn/components/ui/input-otp.tsx +0 -61
  313. package/src/v2/shadcn/components/ui/input.stories.tsx +0 -16
  314. package/src/v2/shadcn/components/ui/input.tsx +0 -25
  315. package/src/v2/shadcn/components/ui/label.stories.tsx +0 -13
  316. package/src/v2/shadcn/components/ui/label.tsx +0 -17
  317. package/src/v2/shadcn/components/ui/menubar.stories.tsx +0 -86
  318. package/src/v2/shadcn/components/ui/menubar.tsx +0 -207
  319. package/src/v2/shadcn/components/ui/navigation-menu.stories.tsx +0 -68
  320. package/src/v2/shadcn/components/ui/navigation-menu.tsx +0 -120
  321. package/src/v2/shadcn/components/ui/pagination.stories.tsx +0 -78
  322. package/src/v2/shadcn/components/ui/pagination.tsx +0 -81
  323. package/src/v2/shadcn/components/ui/popover.stories.tsx +0 -44
  324. package/src/v2/shadcn/components/ui/popover.tsx +0 -29
  325. package/src/v2/shadcn/components/ui/progress.stories.tsx +0 -17
  326. package/src/v2/shadcn/components/ui/progress.tsx +0 -23
  327. package/src/v2/shadcn/components/ui/radio-card.stories.tsx +0 -68
  328. package/src/v2/shadcn/components/ui/radio-card.tsx +0 -52
  329. package/src/v2/shadcn/components/ui/radio-group.stories.tsx +0 -77
  330. package/src/v2/shadcn/components/ui/radio-group.tsx +0 -35
  331. package/src/v2/shadcn/components/ui/scroll-area.stories.tsx +0 -56
  332. package/src/v2/shadcn/components/ui/scroll-area.tsx +0 -38
  333. package/src/v2/shadcn/components/ui/select.stories.tsx +0 -60
  334. package/src/v2/shadcn/components/ui/select.tsx +0 -148
  335. package/src/v2/shadcn/components/ui/separator.stories.tsx +0 -30
  336. package/src/v2/shadcn/components/ui/separator.tsx +0 -20
  337. package/src/v2/shadcn/components/ui/sheet.stories.tsx +0 -115
  338. package/src/v2/shadcn/components/ui/sheet.tsx +0 -107
  339. package/src/v2/shadcn/components/ui/sidebar.stories.tsx +0 -167
  340. package/src/v2/shadcn/components/ui/sidebar.tsx +0 -637
  341. package/src/v2/shadcn/components/ui/skeleton.stories.tsx +0 -36
  342. package/src/v2/shadcn/components/ui/skeleton.tsx +0 -7
  343. package/src/v2/shadcn/components/ui/slider.stories.tsx +0 -16
  344. package/src/v2/shadcn/components/ui/slider.tsx +0 -23
  345. package/src/v2/shadcn/components/ui/switch.scss +0 -63
  346. package/src/v2/shadcn/components/ui/switch.stories.tsx +0 -23
  347. package/src/v2/shadcn/components/ui/switch.tsx +0 -24
  348. package/src/v2/shadcn/components/ui/table-pagination.stories.tsx +0 -81
  349. package/src/v2/shadcn/components/ui/table-pagination.tsx +0 -61
  350. package/src/v2/shadcn/components/ui/table.stories.tsx +0 -40
  351. package/src/v2/shadcn/components/ui/table.tsx +0 -72
  352. package/src/v2/shadcn/components/ui/tabs.stories.tsx +0 -85
  353. package/src/v2/shadcn/components/ui/tabs.tsx +0 -53
  354. package/src/v2/shadcn/components/ui/textarea.stories.tsx +0 -15
  355. package/src/v2/shadcn/components/ui/textarea.tsx +0 -21
  356. package/src/v2/shadcn/components/ui/toast.stories.tsx +0 -77
  357. package/src/v2/shadcn/components/ui/toast.tsx +0 -111
  358. package/src/v2/shadcn/components/ui/toaster.stories.tsx +0 -46
  359. package/src/v2/shadcn/components/ui/toaster.tsx +0 -24
  360. package/src/v2/shadcn/components/ui/toggle-group.stories.tsx +0 -95
  361. package/src/v2/shadcn/components/ui/toggle-group.tsx +0 -49
  362. package/src/v2/shadcn/components/ui/toggle.stories.tsx +0 -18
  363. package/src/v2/shadcn/components/ui/toggle.tsx +0 -37
  364. package/src/v2/shadcn/components/ui/tooltip.stories.tsx +0 -57
  365. package/src/v2/shadcn/components/ui/tooltip.tsx +0 -28
  366. package/src/v2/shadcn/components/ui/use-toast.ts +0 -3
  367. package/src/v2/shadcn/hooks/use-mobile.tsx +0 -19
  368. package/src/v2/shadcn/hooks/use-toast.ts +0 -184
  369. package/src/v2/shadcn/index.ts +0 -76
  370. package/src/v2/shadcn/lib/utils.ts +0 -6
  371. package/src/v2/shadcn/styles/globals.css +0 -112
@@ -1,205 +0,0 @@
1
- import React from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { useForm } from 'react-hook-form';
4
- import { zodResolver } from '@hookform/resolvers/zod';
5
- import { z } from 'zod';
6
- import { Button } from '../ui/button';
7
- import { Input } from '../ui/input';
8
- import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '../ui/form';
9
- import { useNotify } from '../../hooks/useNotify';
10
- import { useNavigate } from 'react-router-dom';
11
- import { useAuth } from '@/contexts/AuthContext';
12
- import { supabase } from '@/integrations/supabase/client';
13
-
14
- type LoginFormData = {
15
- email: string;
16
- password: string;
17
- };
18
-
19
- export const LoginForm: React.FC = () => {
20
- const navigate = useNavigate();
21
- const { signIn } = useAuth();
22
- const { showSuccess, showError } = useNotify();
23
- const { t } = useTranslation(['Design', 'User', 'Validation']);
24
-
25
- const loginSchema = z.object({
26
- email: z.string().email(t('invalidEmailAddress', { ns: 'Validation' })),
27
- password: z.string().min(1, t('passwordRequired', { ns: 'Validation' })),
28
- });
29
-
30
- const form = useForm<LoginFormData>({
31
- resolver: zodResolver(loginSchema),
32
- defaultValues: {
33
- email: '',
34
- password: '',
35
- },
36
- });
37
-
38
- const onSubmit = async (data: LoginFormData) => {
39
- try {
40
- // Standard password-based login
41
- const { error } = await signIn(data.email, data.password);
42
-
43
- if (error) {
44
- showError(t('signInFailed', { ns: 'User' }), error.message);
45
- return;
46
- }
47
-
48
- // Get user's primary role and assignments to determine dashboard
49
- const { data: { user } } = await supabase.auth.getUser();
50
- if (!user) {
51
- showError(t('authenticationFailed', { ns: 'User' }));
52
- return;
53
- }
54
-
55
- // Check if user is suspended
56
- const { data: profile } = await supabase
57
- .from('profiles')
58
- .select('status')
59
- .eq('id', user.id)
60
- .single();
61
-
62
- if (profile?.status === 'suspended') {
63
- // Log them out immediately
64
- await supabase.auth.signOut();
65
- showError(t('accountSuspendedTitle', { ns: 'User' }), t('accountSuspended', { ns: 'User' }));
66
- return;
67
- }
68
-
69
- const { data: primaryRole, error: roleError } = await supabase
70
- .rpc('get_user_primary_role', { _user_id: user.id });
71
-
72
- if (roleError) {
73
- console.error('Error fetching role:', roleError);
74
- showError(t('failedToDeterminePermissions', { ns: 'User' }));
75
- return;
76
- }
77
-
78
- console.log('Primary role fetched:', primaryRole);
79
-
80
- // Super admins and system admins go to admin dashboard
81
- if (primaryRole === 'super_admin' || primaryRole === 'system_admin') {
82
- showSuccess(t('welcomeBackAdmin', { ns: 'User' }));
83
- navigate('/admin');
84
- return;
85
- }
86
-
87
- // For other roles, check their assignments
88
- // First check for company assignments
89
- const { data: companyAssignments } = await supabase
90
- .from('user_companies')
91
- .select('company_id')
92
- .eq('user_id', user.id)
93
- .limit(1);
94
-
95
- if (companyAssignments && companyAssignments.length > 0) {
96
- const companyId = companyAssignments[0].company_id;
97
- showSuccess(t('welcomeBack', { ns: 'User' }));
98
- navigate(`/company/${companyId}`);
99
- return;
100
- }
101
-
102
- // Then check for provider assignments
103
- const { data: providerAssignments } = await supabase
104
- .from('user_providers')
105
- .select('provider_id')
106
- .eq('user_id', user.id)
107
- .limit(1);
108
-
109
- if (providerAssignments && providerAssignments.length > 0) {
110
- const providerId = providerAssignments[0].provider_id;
111
-
112
- // Fetch provider details to get the friendly ID and type
113
- const { data: provider } = await supabase
114
- .from('providers')
115
- .select('venue_id, type')
116
- .eq('id', providerId)
117
- .single();
118
-
119
- if (provider) {
120
- const providerType = provider.type === 'venue' ? 'venue' : 'promoter';
121
- const friendlyId = provider.venue_id || '01';
122
- showSuccess(t('welcomeBack', { ns: 'User' }));
123
- navigate(`/${providerType}/${friendlyId}`);
124
- return;
125
- }
126
- }
127
-
128
- // No assignments found - show error
129
- showError(t('noDashboardAccess', { ns: 'User' }));
130
- console.error('User has role but no company/provider assignments');
131
- } catch (error) {
132
- console.error('Login error:', error);
133
- showError(t('unexpectedError', { ns: 'User' }));
134
- }
135
- };
136
-
137
- return (
138
- <Form {...form}>
139
- <form
140
- onSubmit={form.handleSubmit(onSubmit)}
141
- className="flex min-w-60 flex-col items-stretch flex-1 shrink basis-[0%] max-md:max-w-full"
142
- >
143
- <FormField
144
- control={form.control}
145
- name="email"
146
- render={({ field }) => (
147
- <FormItem className="mb-4">
148
- <FormLabel className="text-label-primary text-[15px] font-semibold leading-[1.4]">
149
- {t('emailAddress')}
150
- </FormLabel>
151
- <FormControl>
152
- <Input
153
- type="email"
154
- placeholder=""
155
- className="border-stroke-primary bg-surface-primary text-label-primary"
156
- autoComplete="email"
157
- {...field}
158
- />
159
- </FormControl>
160
- <FormMessage className="text-feedback-error text-sm" />
161
- </FormItem>
162
- )}
163
- />
164
-
165
- <FormField
166
- control={form.control}
167
- name="password"
168
- render={({ field }) => (
169
- <FormItem className="mb-6">
170
- <FormLabel className="text-label-primary text-[15px] font-semibold leading-[1.4]">
171
- {t('password')}
172
- </FormLabel>
173
- <FormControl>
174
- <Input
175
- type="password"
176
- placeholder=""
177
- className="border-stroke-primary bg-surface-primary text-label-primary"
178
- autoComplete="current-password"
179
- {...field}
180
- />
181
- </FormControl>
182
- <FormMessage className="text-feedback-error text-sm" />
183
- <button
184
- type="button"
185
- onClick={() => navigate('/auth/reset-password')}
186
- className="text-label-action text-[15px] font-normal underline mt-2 inline-block"
187
- >
188
- {t('forgotPassword')}
189
- </button>
190
- </FormItem>
191
- )}
192
- />
193
-
194
- <Button
195
- type="submit"
196
- disabled={form.formState.isSubmitting}
197
- size="lg"
198
- className="min-w-[150px] w-fit"
199
- >
200
- {form.formState.isSubmitting ? t('signingIn') : t('signIn')}
201
- </Button>
202
- </form>
203
- </Form>
204
- );
205
- };
@@ -1,41 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { useLocation } from 'react-router-dom';
4
- import { LoginForm } from './LoginForm';
5
- import { AuthLayout } from './AuthLayout';
6
- import { IconLogin } from '../../../icons';
7
- import { Alert, AlertDescription } from '../ui/alert';
8
-
9
- export const LoginPanel: React.FC = () => {
10
- const location = useLocation();
11
- const [showSuspendedAlert, setShowSuspendedAlert] = useState(false);
12
- const { t } = useTranslation(['User']);
13
-
14
- useEffect(() => {
15
- // Check if user was redirected due to suspension
16
- const params = new URLSearchParams(location.search);
17
- if (params.get('suspended') === 'true') {
18
- setShowSuspendedAlert(true);
19
- }
20
- }, [location]);
21
-
22
- return (
23
- <AuthLayout
24
- badgeLabel={t('logIn')}
25
- icon={
26
- <IconLogin className="w-16 h-16 text-fill-primary" />
27
- }
28
- title={t('logIn')}
29
- subtitle={t('loginSubtitle')}
30
- >
31
- {showSuspendedAlert && (
32
- <Alert className="mb-4 border-status-error bg-status-error/10">
33
- <AlertDescription className="text-label-primary text-sm">
34
- {t('accountSuspended')}
35
- </AlertDescription>
36
- </Alert>
37
- )}
38
- <LoginForm />
39
- </AuthLayout>
40
- );
41
- };
@@ -1,102 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { Button } from '../ui/button';
4
- import { Label } from '../ui/label';
5
- import { Input } from '../ui/input';
6
- import { useNotify } from '../../hooks/useNotify';
7
- import { useNavigate } from 'react-router-dom';
8
- import { supabase } from '@/integrations/supabase/client';
9
-
10
- export const ResetPasswordForm: React.FC = () => {
11
- const [email, setEmail] = useState('');
12
- const [isSubmitting, setIsSubmitting] = useState(false);
13
- const navigate = useNavigate();
14
- const { showSuccess, showError } = useNotify();
15
- const { t } = useTranslation(['User']);
16
-
17
- const onSubmit = async (e: React.FormEvent) => {
18
- e.preventDefault();
19
-
20
- if (!email) {
21
- showError(t('pleaseEnterEmailAddress'));
22
- return;
23
- }
24
-
25
- setIsSubmitting(true);
26
- try {
27
- const { error } = await supabase.auth.resetPasswordForEmail(email, {
28
- redirectTo: `${window.location.origin}/auth/create-password`,
29
- });
30
-
31
- if (error) {
32
- showError(t('resetFailed'), error.message);
33
- return;
34
- }
35
-
36
- showSuccess(t('passwordResetEmailSent'), t('checkYourInbox'));
37
- navigate('/auth/verify-email');
38
- } catch (error) {
39
- showError(t('unexpectedError'));
40
- } finally {
41
- setIsSubmitting(false);
42
- }
43
- };
44
-
45
- return (
46
- <form onSubmit={onSubmit} className="flex min-w-60 flex-col items-stretch flex-1 shrink basis-[0%] max-md:max-w-full">
47
- {/* Info text */}
48
- <div className="mb-6">
49
- <p className="text-label-primary text-base leading-[1.4]">
50
- {t('resetPasswordDescription')}
51
- </p>
52
- </div>
53
-
54
- <div className="mb-6">
55
- <Label htmlFor="email" className="text-label-primary text-[15px] font-semibold leading-[1.4] mb-2 block">
56
- {t('emailAddress')}
57
- </Label>
58
- <Input
59
- id="email"
60
- type="email"
61
- value={email}
62
- onChange={(e) => setEmail(e.target.value)}
63
- className="border-stroke-primary bg-surface-primary text-label-primary"
64
-
65
- autoComplete="email"
66
- />
67
- </div>
68
-
69
- <Button
70
- type="submit"
71
- disabled={isSubmitting}
72
- size="lg"
73
- className="mb-4 min-w-[150px] w-fit"
74
- >
75
- {isSubmitting ? t('sendingReset') : t('resetPassword')}
76
- </Button>
77
-
78
- <p className="text-label-primary text-[15px] font-normal mb-2">
79
- {t('resetPasswordAlreadyAccount')}{' '}
80
- <button
81
- type="button"
82
- onClick={() => navigate('/auth')}
83
- className="text-label-action font-normal underline"
84
- >
85
- {t('logIn')}
86
- </button>
87
- <span className="text-label-primary">.</span>
88
- </p>
89
-
90
- <p className="text-label-primary text-[15px] font-normal">
91
- {t('forFurtherSupport')}{' '}
92
- <a
93
- href="mailto:support@booked.it"
94
- className="text-label-action font-normal underline"
95
- >
96
- {t('contactUs')}
97
- </a>
98
- <span className="text-label-primary">.</span>
99
- </p>
100
- </form>
101
- );
102
- };
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { ResetPasswordForm } from './ResetPasswordForm';
4
- import { AuthLayout } from './AuthLayout';
5
- import { IconUpdate } from '../../../icons';
6
- export const ResetPasswordPanel: React.FC = () => {
7
- const { t } = useTranslation(['User']);
8
- return (
9
- <AuthLayout
10
- badgeLabel={t('resetPassword')}
11
- icon={
12
- <IconUpdate className="w-16 h-16 text-fill-primary" />
13
- }
14
- title={t('resetPassword')}
15
- subtitle={t('resetPasswordSubtitle')}
16
- >
17
- <ResetPasswordForm />
18
- </AuthLayout>
19
- );
20
- };
@@ -1,95 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { Button } from '../ui/button';
4
- import { Label } from '../ui/label';
5
- import { Input } from '../ui/input';
6
- import { useNotify } from '../../hooks/useNotify';
7
- import { useNavigate } from 'react-router-dom';
8
-
9
- export const VerifyEmailForm: React.FC = () => {
10
- const [code, setCode] = useState('');
11
- const [isSubmitting, setIsSubmitting] = useState(false);
12
- const navigate = useNavigate();
13
- const { showSuccess, showError } = useNotify();
14
- const { t } = useTranslation(['User']);
15
-
16
- // Add dummy test code on mount for testing
17
- useEffect(() => {
18
- const testCode = '123456';
19
- setCode(testCode);
20
- }, []);
21
-
22
- const onSubmit = async (e: React.FormEvent) => {
23
- e.preventDefault();
24
-
25
- if (!code || code.length !== 6) {
26
- showError(t('pleaseEnterValidCode'));
27
- return;
28
- }
29
-
30
- setIsSubmitting(true);
31
- try {
32
- // Simulate verification
33
- await new Promise(resolve => setTimeout(resolve, 1000));
34
- showSuccess(t('emailVerifiedSuccessfully'));
35
- navigate('/auth/create-password');
36
- } catch (error) {
37
- showError(t('verificationFailed'));
38
- } finally {
39
- setIsSubmitting(false);
40
- }
41
- };
42
-
43
- return (
44
- <>
45
- <form onSubmit={onSubmit} className="flex min-w-60 flex-col items-stretch flex-1 shrink basis-[0%] max-md:max-w-full">
46
- <div className="mb-6">
47
- <Label htmlFor="code" className="text-label-primary text-[15px] font-semibold leading-[1.4] mb-2 block">
48
- {t('verifyEmailCode')}
49
- </Label>
50
- <p className="text-label-secondary text-sm mb-4">
51
- {t('verifyEmailDescription')}
52
- </p>
53
- <div className="flex gap-2 w-full">
54
- {[0, 1, 2, 3, 4, 5].map((index) => (
55
- <Input
56
- key={index}
57
- type="text"
58
- maxLength={1}
59
- className="flex-1 h-16 text-center text-2xl border-stroke-primary bg-surface-primary text-label-primary font-semibold"
60
- value={code[index] || ''}
61
- onChange={(e) => {
62
- const newCode = code.split('');
63
- newCode[index] = e.target.value;
64
- setCode(newCode.join(''));
65
-
66
- // Auto-focus next input
67
- if (e.target.value && index < 5) {
68
- const nextInput = e.target.parentElement?.children[index + 1] as HTMLInputElement;
69
- nextInput?.focus();
70
- }
71
- }}
72
- onKeyDown={(e) => {
73
- // Handle backspace
74
- if (e.key === 'Backspace' && !code[index] && index > 0) {
75
- const prevInput = e.currentTarget.parentElement?.children[index - 1] as HTMLInputElement;
76
- prevInput?.focus();
77
- }
78
- }}
79
- />
80
- ))}
81
- </div>
82
- </div>
83
-
84
- <Button
85
- type="submit"
86
- disabled={isSubmitting || code.length !== 6}
87
- size="lg"
88
- className="mt-2 min-w-[150px] w-fit"
89
- >
90
- {isSubmitting ? t('verifying') : t('verifyCode')}
91
- </Button>
92
- </form>
93
- </>
94
- );
95
- };
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { VerifyEmailForm } from './VerifyEmailForm';
4
- import { AuthLayout } from './AuthLayout';
5
- import { IconMail } from '../../../icons';
6
- export const VerifyEmailPanel: React.FC = () => {
7
- const { t } = useTranslation(['User']);
8
- return (
9
- <AuthLayout
10
- badgeLabel={t('verifyEmail')}
11
- icon={
12
- <IconMail className="w-16 h-16 text-fill-primary" />
13
- }
14
- title={t('verifyEmail')}
15
- subtitle={t('verifyEmailPanelSubtitle')}
16
- >
17
- <VerifyEmailForm />
18
- </AuthLayout>
19
- );
20
- };
@@ -1,119 +0,0 @@
1
- import React, { useRef, useState } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { IconUpload, IconCross } from '../../../icons';
4
-
5
- interface AttachedFile {
6
- name: string;
7
- size: number;
8
- file: File;
9
- }
10
-
11
- interface EmailAttachmentProps {
12
- files: AttachedFile[];
13
- onChange: (files: AttachedFile[]) => void;
14
- }
15
-
16
- const formatFileSize = (bytes: number) => {
17
- if (bytes < 1024) return `${bytes} B`;
18
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
19
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
20
- };
21
-
22
- const EmailAttachment: React.FC<EmailAttachmentProps> = ({ files, onChange }) => {
23
- const { t } = useTranslation(['Design']);
24
- const inputRef = useRef<HTMLInputElement>(null);
25
- const [isDragging, setIsDragging] = useState(false);
26
-
27
- const addFiles = (fileList: FileList | File[]) => {
28
- const selectedFiles = Array.from(fileList);
29
- const newFiles: AttachedFile[] = selectedFiles.map(f => ({
30
- name: f.name,
31
- size: f.size,
32
- file: f,
33
- }));
34
- onChange([...files, ...newFiles]);
35
- };
36
-
37
- const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
38
- if (e.target.files) addFiles(e.target.files);
39
- if (inputRef.current) inputRef.current.value = '';
40
- };
41
-
42
- const handleDrop = (e: React.DragEvent) => {
43
- e.preventDefault();
44
- setIsDragging(false);
45
- if (e.dataTransfer.files.length) addFiles(e.dataTransfer.files);
46
- };
47
-
48
- const handleDragOver = (e: React.DragEvent) => {
49
- e.preventDefault();
50
- setIsDragging(true);
51
- };
52
-
53
- const handleDragLeave = (e: React.DragEvent) => {
54
- e.preventDefault();
55
- setIsDragging(false);
56
- };
57
-
58
- const removeFile = (index: number) => {
59
- onChange(files.filter((_, i) => i !== index));
60
- };
61
-
62
- return (
63
- <div className="flex flex-col gap-3">
64
- <h2 className="text-label-primary text-lg font-semibold">{t('attachments')}</h2>
65
-
66
- {files.length > 0 && (
67
- <div className="flex flex-col gap-2">
68
- {files.map((file, index) => (
69
- <div
70
- key={index}
71
- className="flex items-center justify-between gap-3 p-3 border border-border-primary rounded-lg"
72
- >
73
- <div className="flex flex-col gap-0.5 min-w-0">
74
- <span className="text-label-primary text-sm font-medium truncate">{file.name}</span>
75
- <span className="text-label-secondary text-xs">{formatFileSize(file.size)}</span>
76
- </div>
77
- <button
78
- type="button"
79
- onClick={() => removeFile(index)}
80
- className="flex-shrink-0 p-1 hover:bg-surface-secondary rounded transition-colors"
81
- >
82
- <IconCross size={16} className="fill-fill-secondary" />
83
- </button>
84
- </div>
85
- ))}
86
- </div>
87
- )}
88
-
89
- <input
90
- ref={inputRef}
91
- type="file"
92
- onChange={handleFileSelect}
93
- className="hidden"
94
- multiple
95
- />
96
-
97
- <div
98
- onDrop={handleDrop}
99
- onDragOver={handleDragOver}
100
- onDragLeave={handleDragLeave}
101
- onClick={() => inputRef.current?.click()}
102
- className={`flex flex-col items-center justify-center gap-2 p-8 border-2 border-dashed rounded-lg cursor-pointer transition-colors ${
103
- isDragging
104
- ? 'border-border-action bg-surface-action-soft'
105
- : 'border-border-primary hover:border-border-action hover:bg-surface-action-soft'
106
- }`}
107
- >
108
- <IconUpload size={24} className="fill-fill-secondary" />
109
- <div className="flex flex-col items-center gap-0.5">
110
- <span className="text-label-primary text-sm font-medium">{t('dragFileToUpload')}</span>
111
- <span className="text-label-action text-sm font-medium">{t('browseFilesBtn')}</span>
112
- </div>
113
- </div>
114
- </div>
115
- );
116
- };
117
-
118
- export type { AttachedFile };
119
- export default EmailAttachment;