@goplusvn/core 0.1.0 → 0.1.2

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 (591) hide show
  1. package/package.json +31 -175
  2. package/src/assets/erp_wallpaper.png +0 -0
  3. package/src/assets/goeat_logo.png +0 -0
  4. package/src/audit/audit-manager.ts +139 -0
  5. package/src/audit/index.ts +11 -0
  6. package/src/audit/memory-audit-logger.ts +86 -0
  7. package/src/audit/types.ts +50 -0
  8. package/src/auth/auth-service.ts +97 -0
  9. package/src/auth/index.ts +266 -0
  10. package/src/code-generation/index.ts +69 -0
  11. package/src/configs/auth-routes.ts +17 -0
  12. package/src/configs/crud.ts +136 -0
  13. package/src/configs/data/navigations.ts +781 -0
  14. package/src/configs/data/oauth-links.ts +10 -0
  15. package/src/configs/entities/material-categories.config.ts +125 -0
  16. package/src/configs/i18n.ts +12 -0
  17. package/src/configs/index.ts +26 -0
  18. package/src/configs/status.ts +25 -0
  19. package/src/configs/themes.ts +100 -0
  20. package/src/crud/components/crud-bulk-actions.tsx +91 -0
  21. package/src/crud/components/crud-card-view.tsx +241 -0
  22. package/src/crud/components/crud-context.tsx +122 -0
  23. package/src/crud/components/crud-delete-dialog.tsx +145 -0
  24. package/src/crud/components/crud-dialog.tsx +406 -0
  25. package/src/crud/components/crud-empty-state.tsx +104 -0
  26. package/src/crud/components/crud-export-button.tsx +170 -0
  27. package/src/crud/components/crud-field-renderer.tsx +653 -0
  28. package/src/crud/components/crud-filter-chips.tsx +102 -0
  29. package/src/crud/components/crud-filters/checkbox-filter.tsx +97 -0
  30. package/src/crud/components/crud-filters/datetime-filter.tsx +83 -0
  31. package/src/crud/components/crud-filters/filter-builder.tsx +66 -0
  32. package/src/crud/components/crud-filters/index.tsx +76 -0
  33. package/src/crud/components/crud-filters/radio-filter.tsx +86 -0
  34. package/src/crud/components/crud-filters/select-filter.tsx +141 -0
  35. package/src/crud/components/crud-filters/text-filter.tsx +86 -0
  36. package/src/crud/components/crud-form.tsx +642 -0
  37. package/src/crud/components/crud-import-dialog.tsx +440 -0
  38. package/src/crud/components/crud-infinite-scroll.tsx +116 -0
  39. package/src/crud/components/crud-page.tsx +1017 -0
  40. package/src/crud/components/crud-provider.tsx +277 -0
  41. package/src/crud/components/crud-row-actions.tsx +189 -0
  42. package/src/crud/components/crud-search.tsx +82 -0
  43. package/src/crud/components/crud-sheet.tsx +336 -0
  44. package/src/crud/components/crud-table-skeleton.tsx +26 -0
  45. package/src/crud/components/crud-table-toolbar.tsx +91 -0
  46. package/src/crud/components/crud-table.tsx +352 -0
  47. package/src/crud/components/crud-virtual-table.tsx +55 -0
  48. package/src/crud/components/index.tsx +20 -0
  49. package/src/crud/crud-filters/checkbox-filter.tsx +87 -0
  50. package/src/crud/crud-filters/datetime-filter.tsx +82 -0
  51. package/src/crud/crud-filters/filter-builder.tsx +64 -0
  52. package/src/crud/crud-filters/index.tsx +78 -0
  53. package/src/crud/crud-filters/radio-filter.tsx +79 -0
  54. package/src/crud/crud-filters/select-filter.tsx +148 -0
  55. package/src/crud/crud-filters/text-filter.tsx +81 -0
  56. package/src/crud/index.ts +43 -0
  57. package/src/crud/lib/crud-service.test.ts +334 -0
  58. package/src/crud/lib/crud-service.ts +358 -0
  59. package/src/crud/lib/crud-utils.test.ts +354 -0
  60. package/src/crud/lib/crud-utils.ts +299 -0
  61. package/src/crud/lib/crud-validator.ts +247 -0
  62. package/src/crud/lib/data-loader.ts +234 -0
  63. package/src/crud/lib/field-calculator.ts +241 -0
  64. package/src/crud/lib/field-formatter.ts +240 -0
  65. package/src/crud/lib/import-export-service.test.ts +290 -0
  66. package/src/crud/lib/import-export-service.ts +352 -0
  67. package/src/crud/lib/import-server-utils.ts +109 -0
  68. package/src/crud/lib/lazy-loader.ts +241 -0
  69. package/src/crud/lib/parse-filters.ts +85 -0
  70. package/src/crud/lib/permissions.ts +52 -0
  71. package/src/crud/lib/serialize-config.ts +60 -0
  72. package/src/crud/lib/stream-loader.ts +145 -0
  73. package/src/crud/lib/translate-config.ts +335 -0
  74. package/src/crud/lib/types.ts +11 -0
  75. package/src/crud/pages/entity-crud-page.tsx +144 -0
  76. package/src/crud/server.ts +8 -0
  77. package/src/home/constants.tsx +142 -0
  78. package/src/home/feature-showcase.tsx +171 -0
  79. package/src/home/home-page.tsx +191 -0
  80. package/src/home/hooks/index.ts +1 -0
  81. package/src/home/hooks/useWidgetPreferences.ts +167 -0
  82. package/src/home/index.ts +33 -0
  83. package/src/home/quick-access-dialog.tsx +271 -0
  84. package/src/home/quick-access-menu.tsx +267 -0
  85. package/src/home/types.ts +140 -0
  86. package/src/home/welcome-card.tsx +92 -0
  87. package/src/home/widget-container.tsx +258 -0
  88. package/src/home/widgets/base-widget.tsx +200 -0
  89. package/src/home/widgets/customers-widget.tsx +74 -0
  90. package/src/home/widgets/index.ts +6 -0
  91. package/src/home/widgets/orders-widget.tsx +87 -0
  92. package/src/home/widgets/revenue-widget.tsx +71 -0
  93. package/src/home/widgets/stock-widget.tsx +109 -0
  94. package/src/hooks/index.tsx +598 -0
  95. package/src/hooks/use-tenant.test.tsx +30 -0
  96. package/src/hooks/use-tenant.ts +5 -0
  97. package/src/index.ts +17 -0
  98. package/src/infrastructure/__tests__/architecture-verification.spec.ts +103 -0
  99. package/src/infrastructure/api-service.ts +317 -0
  100. package/src/infrastructure/cache/cache-manager.ts +107 -0
  101. package/src/infrastructure/cache/cache.ts +120 -0
  102. package/src/infrastructure/cache/index.ts +8 -0
  103. package/src/infrastructure/cache/types.ts +48 -0
  104. package/src/infrastructure/cron/cron-manager.ts +239 -0
  105. package/src/infrastructure/cron/index.ts +6 -0
  106. package/src/infrastructure/cron/types.ts +41 -0
  107. package/src/infrastructure/event-bus/event-bus.ts +145 -0
  108. package/src/infrastructure/event-bus/index.ts +2 -0
  109. package/src/infrastructure/event-bus/types.ts +22 -0
  110. package/src/infrastructure/index.ts +32 -0
  111. package/src/infrastructure/lock/decorators.ts +67 -0
  112. package/src/infrastructure/lock/index.ts +2 -0
  113. package/src/infrastructure/lock/lock-manager.ts +33 -0
  114. package/src/infrastructure/logger/index.ts +2 -0
  115. package/src/infrastructure/logger/logger.ts +96 -0
  116. package/src/infrastructure/logger/types.ts +25 -0
  117. package/src/layout/index.tsx +185 -0
  118. package/src/navigation/index.ts +91 -0
  119. package/src/notification/index.ts +14 -0
  120. package/src/notification/notification-service.ts +120 -0
  121. package/src/notification/storage/in-memory.ts +56 -0
  122. package/src/notification/storage/index.ts +1 -0
  123. package/src/notification/types.ts +51 -0
  124. package/src/organization/branch-service.ts +299 -0
  125. package/src/organization/branches.config.ts +154 -0
  126. package/src/organization/index.ts +5 -0
  127. package/src/plugin/apps-registry.ts +97 -0
  128. package/src/plugin/index.ts +5 -0
  129. package/src/plugin/types.ts +41 -0
  130. package/src/providers/index.tsx +109 -0
  131. package/src/providers/tenant-provider.tsx +45 -0
  132. package/src/rbac/components/roles/role-card.tsx +158 -0
  133. package/src/rbac/components/roles/role-stats-cards.tsx +29 -0
  134. package/src/rbac/components/roles/role-toolbar.tsx +123 -0
  135. package/src/rbac/hooks/use-role-operations.ts +159 -0
  136. package/src/rbac/hooks/use-roles-data.ts +59 -0
  137. package/src/rbac/index.ts +297 -0
  138. package/src/rbac/lib/permission-helpers.ts +63 -0
  139. package/src/rbac/pages/action-list-page.tsx +25 -0
  140. package/src/rbac/pages/resource-list-page.tsx +25 -0
  141. package/src/rbac/pages/role-list-page.tsx +378 -0
  142. package/src/rbac/permission-service.ts +140 -0
  143. package/src/rbac/permissions.ts +135 -0
  144. package/src/rbac/resource-service.ts +115 -0
  145. package/src/rbac/resource-validator.ts +119 -0
  146. package/src/rbac/role-service.ts +165 -0
  147. package/src/rbac/server.ts +16 -0
  148. package/src/rbac/types.ts +38 -0
  149. package/src/schemas/action.schema.ts +66 -0
  150. package/src/schemas/branch.schema.ts +52 -0
  151. package/src/schemas/coming-soon-schema.ts +9 -0
  152. package/src/schemas/company.schema.ts +44 -0
  153. package/src/schemas/forgot-passward-schema.ts +9 -0
  154. package/src/schemas/index.ts +30 -0
  155. package/src/schemas/material-category.schema.ts +43 -0
  156. package/src/schemas/material-pricing.schema.ts +74 -0
  157. package/src/schemas/material.schema.ts +76 -0
  158. package/src/schemas/materials.ts +52 -0
  159. package/src/schemas/new-passward-schema.ts +15 -0
  160. package/src/schemas/partner-company.schema.ts +149 -0
  161. package/src/schemas/register-schema.ts +36 -0
  162. package/src/schemas/resource.schema.ts +133 -0
  163. package/src/schemas/role.schema.ts +11 -0
  164. package/src/schemas/sign-in-schema.ts +24 -0
  165. package/src/schemas/supplier-pricing.schema.ts +15 -0
  166. package/src/schemas/supplier.schema.ts +120 -0
  167. package/src/schemas/system-category-group.schema.ts +67 -0
  168. package/src/schemas/system-category.schema.ts +77 -0
  169. package/src/schemas/system-config.schema.ts +118 -0
  170. package/src/schemas/uom.schema.ts +75 -0
  171. package/src/schemas/user-supplier.schema.ts +179 -0
  172. package/src/schemas/user.schema.ts +18 -0
  173. package/src/schemas/verify-email-schema.ts +9 -0
  174. package/src/schemas/warehouse.schema.ts +49 -0
  175. package/src/system/components/categories/category-list.tsx +529 -0
  176. package/src/system/components/categories/category-manager.tsx +89 -0
  177. package/src/system/components/categories/group-sidebar.tsx +308 -0
  178. package/src/system/components/settings/setting-dialogs.tsx +197 -0
  179. package/src/system/components/settings/setting-field.tsx +291 -0
  180. package/src/system/components/settings/setting-form-dialog.tsx +308 -0
  181. package/src/system/components/settings/settings-groups.ts +80 -0
  182. package/src/system/components/settings/settings-search.tsx +71 -0
  183. package/src/system/components/settings/settings-section.tsx +74 -0
  184. package/src/system/components/settings/settings-sidebar.tsx +81 -0
  185. package/src/system/constants.ts +3 -0
  186. package/src/system/index.ts +150 -0
  187. package/src/system/job-manager.ts +176 -0
  188. package/src/system/pages/components/categories/category-list.tsx +537 -0
  189. package/src/system/pages/components/categories/category-manager.tsx +90 -0
  190. package/src/system/pages/components/categories/group-sidebar.tsx +311 -0
  191. package/src/system/pages/components/settings/sales-rules-settings.tsx +222 -0
  192. package/src/system/pages/components/settings/setting-dialogs.tsx +197 -0
  193. package/src/system/pages/components/settings/setting-field.tsx +292 -0
  194. package/src/system/pages/components/settings/setting-form-dialog.tsx +308 -0
  195. package/src/system/pages/components/settings/settings-groups.ts +87 -0
  196. package/src/system/pages/components/settings/settings-page.tsx +372 -0
  197. package/src/system/pages/components/settings/settings-search.tsx +71 -0
  198. package/src/system/pages/components/settings/settings-section.tsx +74 -0
  199. package/src/system/pages/components/settings/settings-sidebar.tsx +81 -0
  200. package/src/system/pages/components/settings/system-settings.tsx +244 -0
  201. package/src/system/pages/system-category-page.tsx +15 -0
  202. package/src/system/pages/system-settings-page.tsx +380 -0
  203. package/src/system/schemas/system-category-group.schema.ts +46 -0
  204. package/src/system/schemas/system-category.schema.ts +56 -0
  205. package/src/system/services/settings-service.ts +127 -0
  206. package/src/system/services/system-category-service.ts +63 -0
  207. package/src/system/types.ts +45 -0
  208. package/src/types/index.ts +703 -0
  209. package/src/ui/auth/auth-layout.tsx +135 -0
  210. package/src/ui/auth/forgot-password-form.tsx +98 -0
  211. package/src/ui/auth/index.tsx +7 -0
  212. package/src/ui/auth/new-password-form.tsx +107 -0
  213. package/src/ui/auth/oauth-links.tsx +30 -0
  214. package/src/ui/auth/register-form.tsx +202 -0
  215. package/src/ui/auth/sign-in-form.tsx +238 -0
  216. package/src/ui/auth/verify-email-form.tsx +104 -0
  217. package/src/ui/crud/index.tsx +10 -0
  218. package/src/ui/data-display/accordion.tsx +65 -0
  219. package/src/ui/data-display/aspect-ratio.tsx +11 -0
  220. package/src/ui/data-display/avatar.tsx +163 -0
  221. package/src/ui/data-display/bento-grid.tsx +77 -0
  222. package/src/ui/data-display/carousel.tsx +249 -0
  223. package/src/ui/data-display/chart.tsx +363 -0
  224. package/src/ui/data-display/code-block-highlight.tsx +54 -0
  225. package/src/ui/data-display/collapsible.tsx +42 -0
  226. package/src/ui/data-display/compact-stat-bar.tsx +149 -0
  227. package/src/ui/data-display/data-table/data-table-context.tsx +255 -0
  228. package/src/ui/data-display/data-table/data-table-empty-state.tsx +133 -0
  229. package/src/ui/data-display/data-table/data-table-skeleton.tsx +145 -0
  230. package/src/ui/data-display/data-table/data-table-toolbar.tsx +353 -0
  231. package/src/ui/data-display/data-table/data-table.tsx +597 -0
  232. package/src/ui/data-display/data-table/index.ts +44 -0
  233. package/src/ui/data-display/data-table-column-header.tsx +75 -0
  234. package/src/ui/data-display/data-table-pagination.tsx +130 -0
  235. package/src/ui/data-display/data-table-view-options.tsx +59 -0
  236. package/src/ui/data-display/formatted-number-input.tsx +210 -0
  237. package/src/ui/data-display/highlight.tsx +20 -0
  238. package/src/ui/data-display/hover-card.tsx +48 -0
  239. package/src/ui/data-display/index.tsx +50 -0
  240. package/src/ui/data-display/iphone-15-pro.tsx +114 -0
  241. package/src/ui/data-display/kanban/index.ts +4 -0
  242. package/src/ui/data-display/kanban/kanban-board.tsx +192 -0
  243. package/src/ui/data-display/kanban/kanban-column.tsx +74 -0
  244. package/src/ui/data-display/kanban/kanban-item.tsx +50 -0
  245. package/src/ui/data-display/kanban/kanban-types.ts +21 -0
  246. package/src/ui/data-display/kpi-card.tsx +68 -0
  247. package/src/ui/data-display/media-grid.tsx +110 -0
  248. package/src/ui/data-display/safari.tsx +175 -0
  249. package/src/ui/data-display/show-more-text.tsx +55 -0
  250. package/src/ui/data-display/tabs.tsx +68 -0
  251. package/src/ui/data-display/timeline.tsx +256 -0
  252. package/src/ui/feedback/alert.tsx +60 -0
  253. package/src/ui/feedback/context-menu.tsx +245 -0
  254. package/src/ui/feedback/drawer.tsx +132 -0
  255. package/src/ui/feedback/error-dialog.tsx +273 -0
  256. package/src/ui/feedback/index.tsx +183 -0
  257. package/src/ui/feedback/progress.tsx +32 -0
  258. package/src/ui/feedback/sheet.tsx +148 -0
  259. package/src/ui/feedback/sonner.tsx +36 -0
  260. package/src/ui/forms/command.tsx +157 -0
  261. package/src/ui/forms/date-picker.tsx +73 -0
  262. package/src/ui/forms/date-range-picker.tsx +76 -0
  263. package/src/ui/forms/date-time-picker.tsx +109 -0
  264. package/src/ui/forms/editor/editor-menu-bar.tsx +394 -0
  265. package/src/ui/forms/editor/index.tsx +130 -0
  266. package/src/ui/forms/editor/multi-select-example.tsx +1234 -0
  267. package/src/ui/forms/emoji-picker.tsx +109 -0
  268. package/src/ui/forms/file-dropzone.tsx +169 -0
  269. package/src/ui/forms/file-thumbnail.tsx +29 -0
  270. package/src/ui/forms/index.tsx +201 -0
  271. package/src/ui/forms/input-file.tsx +99 -0
  272. package/src/ui/forms/input-group.tsx +46 -0
  273. package/src/ui/forms/input-otp.tsx +81 -0
  274. package/src/ui/forms/input-phone.tsx +172 -0
  275. package/src/ui/forms/input-spin.tsx +116 -0
  276. package/src/ui/forms/input-tags.tsx +219 -0
  277. package/src/ui/forms/input-time.tsx +42 -0
  278. package/src/ui/forms/multi-select.tsx +629 -0
  279. package/src/ui/forms/multiple-date-picker.tsx +74 -0
  280. package/src/ui/forms/radio-group.tsx +42 -0
  281. package/src/ui/forms/rating.tsx +158 -0
  282. package/src/ui/forms/time-picker.tsx +57 -0
  283. package/src/ui/index.tsx +17 -0
  284. package/src/ui/layout/animated-list.tsx +77 -0
  285. package/src/ui/layout/animated-sidebar.tsx +294 -0
  286. package/src/ui/layout/command-menu.tsx +355 -0
  287. package/src/ui/layout/customizer.tsx +324 -0
  288. package/src/ui/layout/footer.tsx +43 -0
  289. package/src/ui/layout/full-screen-toggle.tsx +52 -0
  290. package/src/ui/layout/header-breadcrumb.tsx +77 -0
  291. package/src/ui/layout/horizontal-layout-header.tsx +83 -0
  292. package/src/ui/layout/horizontal-layout.tsx +50 -0
  293. package/src/ui/layout/index.tsx +25 -0
  294. package/src/ui/layout/language-dropdown.tsx +103 -0
  295. package/src/ui/layout/logo.tsx +63 -0
  296. package/src/ui/layout/main-layout.tsx +57 -0
  297. package/src/ui/layout/mode-dropdown.tsx +58 -0
  298. package/src/ui/layout/notification-dropdown.tsx +127 -0
  299. package/src/ui/layout/page-tabs.tsx +306 -0
  300. package/src/ui/layout/route-cache.tsx +214 -0
  301. package/src/ui/layout/sidebar-group-icon-menu.tsx +195 -0
  302. package/src/ui/layout/sidebar.tsx +279 -0
  303. package/src/ui/layout/tab-content-cache.tsx +201 -0
  304. package/src/ui/layout/tab-navigation-provider.tsx +536 -0
  305. package/src/ui/layout/toggle-mobile-sidebar.tsx +33 -0
  306. package/src/ui/layout/top-bar-header-menubar.tsx +412 -0
  307. package/src/ui/layout/user-dropdown.tsx +188 -0
  308. package/src/ui/layout/vertical-layout-header.tsx +65 -0
  309. package/src/ui/layout/vertical-layout.tsx +47 -0
  310. package/src/ui/management/audit-log-page.tsx +209 -0
  311. package/src/ui/management/cache-management.tsx +349 -0
  312. package/src/ui/management/index.ts +3 -0
  313. package/src/ui/management/job-management.tsx +308 -0
  314. package/src/ui/pages/not-found.tsx +30 -0
  315. package/src/ui/primitives/badge.tsx +66 -0
  316. package/src/ui/primitives/breadcrumb.tsx +103 -0
  317. package/src/ui/primitives/button.tsx +129 -0
  318. package/src/ui/primitives/calendar.tsx +74 -0
  319. package/src/ui/primitives/card.tsx +86 -0
  320. package/src/ui/primitives/checkbox.tsx +31 -0
  321. package/src/ui/primitives/client.ts +30 -0
  322. package/src/ui/primitives/combobox.tsx +290 -0
  323. package/src/ui/primitives/dialog.tsx +121 -0
  324. package/src/ui/primitives/dropdown-menu.tsx +239 -0
  325. package/src/ui/primitives/dynamic-icon.tsx +24 -0
  326. package/src/ui/primitives/index.tsx +134 -0
  327. package/src/ui/primitives/input-number.tsx +131 -0
  328. package/src/ui/primitives/input.tsx +22 -0
  329. package/src/ui/primitives/keyboard.tsx +23 -0
  330. package/src/ui/primitives/label.tsx +24 -0
  331. package/src/ui/primitives/menubar.tsx +262 -0
  332. package/src/ui/primitives/navigation-menu.tsx +157 -0
  333. package/src/ui/primitives/pagination.tsx +118 -0
  334. package/src/ui/primitives/popover.tsx +56 -0
  335. package/src/ui/primitives/prefetch-link.tsx +60 -0
  336. package/src/ui/primitives/resizable.tsx +59 -0
  337. package/src/ui/primitives/scroll-area.tsx +63 -0
  338. package/src/ui/primitives/select.tsx +172 -0
  339. package/src/ui/primitives/separator.tsx +51 -0
  340. package/src/ui/primitives/sidebar.tsx +844 -0
  341. package/src/ui/primitives/slider.tsx +27 -0
  342. package/src/ui/primitives/status-badge.tsx +47 -0
  343. package/src/ui/primitives/sticky-layout.tsx +50 -0
  344. package/src/ui/primitives/switch.tsx +29 -0
  345. package/src/ui/primitives/table.tsx +116 -0
  346. package/src/ui/primitives/tabs.tsx +55 -0
  347. package/src/ui/primitives/toggle-group.tsx +70 -0
  348. package/src/ui/primitives/toggle.tsx +47 -0
  349. package/src/ui/primitives/tooltip.tsx +59 -0
  350. package/src/user/components/dangerous-zone.tsx +34 -0
  351. package/src/user/components/delete-account-form.tsx +40 -0
  352. package/src/user/components/index.ts +4 -0
  353. package/src/user/components/profile-info-form.tsx +390 -0
  354. package/src/user/components/profile-info.tsx +32 -0
  355. package/src/user/components/unified-profile-dialog.tsx +1019 -0
  356. package/src/user/components/user-stats.tsx +27 -0
  357. package/src/user/components/user-toolbar.tsx +137 -0
  358. package/src/user/components/users-card-view.tsx +253 -0
  359. package/src/user/index.ts +11 -0
  360. package/src/user/pages/user-list-page.tsx +234 -0
  361. package/src/user/pages/users-client-page.tsx +385 -0
  362. package/src/user/profile-page.tsx +19 -0
  363. package/src/user/schemas.ts +68 -0
  364. package/src/user/types.ts +34 -0
  365. package/src/user/user-service.ts +538 -0
  366. package/src/utils/index.ts +906 -0
  367. package/src/workflow/activity-timeline.tsx +412 -0
  368. package/src/workflow/approval-workflow.tsx +31 -0
  369. package/src/workflow/index.ts +2 -0
  370. package/dist/audit/index.d.mts +0 -115
  371. package/dist/audit/index.d.ts +0 -115
  372. package/dist/audit/index.js +0 -204
  373. package/dist/audit/index.js.map +0 -1
  374. package/dist/audit/index.mjs +0 -200
  375. package/dist/audit/index.mjs.map +0 -1
  376. package/dist/auth/index.d.mts +0 -86
  377. package/dist/auth/index.d.ts +0 -86
  378. package/dist/auth/index.js +0 -210
  379. package/dist/auth/index.js.map +0 -1
  380. package/dist/auth/index.mjs +0 -198
  381. package/dist/auth/index.mjs.map +0 -1
  382. package/dist/button-1dWvP9Ib.d.mts +0 -30
  383. package/dist/button-1dWvP9Ib.d.ts +0 -30
  384. package/dist/calendar-2QzdEo1z.d.mts +0 -20
  385. package/dist/calendar-2QzdEo1z.d.ts +0 -20
  386. package/dist/code-generation/index.d.mts +0 -30
  387. package/dist/code-generation/index.d.ts +0 -30
  388. package/dist/code-generation/index.js +0 -31
  389. package/dist/code-generation/index.js.map +0 -1
  390. package/dist/code-generation/index.mjs +0 -28
  391. package/dist/code-generation/index.mjs.map +0 -1
  392. package/dist/configs/index.d.mts +0 -175
  393. package/dist/configs/index.d.ts +0 -175
  394. package/dist/configs/index.js +0 -254
  395. package/dist/configs/index.js.map +0 -1
  396. package/dist/configs/index.mjs +0 -233
  397. package/dist/configs/index.mjs.map +0 -1
  398. package/dist/crud/index.d.mts +0 -646
  399. package/dist/crud/index.d.ts +0 -646
  400. package/dist/crud/index.js +0 -11772
  401. package/dist/crud/index.js.map +0 -1
  402. package/dist/crud/index.mjs +0 -11665
  403. package/dist/crud/index.mjs.map +0 -1
  404. package/dist/crud/server.d.mts +0 -20
  405. package/dist/crud/server.d.ts +0 -20
  406. package/dist/crud/server.js +0 -123
  407. package/dist/crud/server.js.map +0 -1
  408. package/dist/crud/server.mjs +0 -120
  409. package/dist/crud/server.mjs.map +0 -1
  410. package/dist/data-table-skeleton-12NA8Mjx.d.mts +0 -39
  411. package/dist/data-table-skeleton-12NA8Mjx.d.ts +0 -39
  412. package/dist/dialog-bKfjZMTd.d.mts +0 -22
  413. package/dist/dialog-bKfjZMTd.d.ts +0 -22
  414. package/dist/dynamic-icon-DrGIiu2N.d.mts +0 -10
  415. package/dist/dynamic-icon-DrGIiu2N.d.ts +0 -10
  416. package/dist/home/index.d.mts +0 -269
  417. package/dist/home/index.d.ts +0 -269
  418. package/dist/home/index.js +0 -1678
  419. package/dist/home/index.js.map +0 -1
  420. package/dist/home/index.mjs +0 -1635
  421. package/dist/home/index.mjs.map +0 -1
  422. package/dist/hooks/index.d.mts +0 -7
  423. package/dist/hooks/index.d.ts +0 -7
  424. package/dist/hooks/index.js +0 -8316
  425. package/dist/hooks/index.js.map +0 -1
  426. package/dist/hooks/index.mjs +0 -8255
  427. package/dist/hooks/index.mjs.map +0 -1
  428. package/dist/index-50hpiPrV.d.ts +0 -116
  429. package/dist/index-B9zQVEVi.d.mts +0 -116
  430. package/dist/index.d.mts +0 -5
  431. package/dist/index.d.ts +0 -5
  432. package/dist/index.js +0 -123
  433. package/dist/index.js.map +0 -1
  434. package/dist/index.mjs +0 -118
  435. package/dist/index.mjs.map +0 -1
  436. package/dist/infrastructure/index.d.mts +0 -423
  437. package/dist/infrastructure/index.d.ts +0 -423
  438. package/dist/infrastructure/index.js +0 -633
  439. package/dist/infrastructure/index.js.map +0 -1
  440. package/dist/infrastructure/index.mjs +0 -619
  441. package/dist/infrastructure/index.mjs.map +0 -1
  442. package/dist/label-DWTEkNPo.d.ts +0 -226
  443. package/dist/label-LPpdcoBx.d.mts +0 -226
  444. package/dist/layout/index.d.mts +0 -48
  445. package/dist/layout/index.d.ts +0 -48
  446. package/dist/layout/index.js +0 -117
  447. package/dist/layout/index.js.map +0 -1
  448. package/dist/layout/index.mjs +0 -90
  449. package/dist/layout/index.mjs.map +0 -1
  450. package/dist/navigation/index.d.mts +0 -16
  451. package/dist/navigation/index.d.ts +0 -16
  452. package/dist/navigation/index.js +0 -53
  453. package/dist/navigation/index.js.map +0 -1
  454. package/dist/navigation/index.mjs +0 -50
  455. package/dist/navigation/index.mjs.map +0 -1
  456. package/dist/notification/index.d.mts +0 -105
  457. package/dist/notification/index.d.ts +0 -105
  458. package/dist/notification/index.js +0 -278
  459. package/dist/notification/index.js.map +0 -1
  460. package/dist/notification/index.mjs +0 -274
  461. package/dist/notification/index.mjs.map +0 -1
  462. package/dist/organization/index.d.mts +0 -99
  463. package/dist/organization/index.d.ts +0 -99
  464. package/dist/organization/index.js +0 -360
  465. package/dist/organization/index.js.map +0 -1
  466. package/dist/organization/index.mjs +0 -352
  467. package/dist/organization/index.mjs.map +0 -1
  468. package/dist/plugin/index.d.mts +0 -83
  469. package/dist/plugin/index.d.ts +0 -83
  470. package/dist/plugin/index.js +0 -86
  471. package/dist/plugin/index.js.map +0 -1
  472. package/dist/plugin/index.mjs +0 -84
  473. package/dist/plugin/index.mjs.map +0 -1
  474. package/dist/providers/index.d.mts +0 -25
  475. package/dist/providers/index.d.ts +0 -25
  476. package/dist/providers/index.js +0 -84
  477. package/dist/providers/index.js.map +0 -1
  478. package/dist/providers/index.mjs +0 -77
  479. package/dist/providers/index.mjs.map +0 -1
  480. package/dist/rbac/index.d.mts +0 -226
  481. package/dist/rbac/index.d.ts +0 -226
  482. package/dist/rbac/index.js +0 -4784
  483. package/dist/rbac/index.js.map +0 -1
  484. package/dist/rbac/index.mjs +0 -4722
  485. package/dist/rbac/index.mjs.map +0 -1
  486. package/dist/rbac/permissions.d.mts +0 -26
  487. package/dist/rbac/permissions.d.ts +0 -26
  488. package/dist/rbac/permissions.js +0 -94
  489. package/dist/rbac/permissions.js.map +0 -1
  490. package/dist/rbac/permissions.mjs +0 -90
  491. package/dist/rbac/permissions.mjs.map +0 -1
  492. package/dist/rbac/server.d.mts +0 -1
  493. package/dist/rbac/server.d.ts +0 -1
  494. package/dist/rbac/server.js +0 -128
  495. package/dist/rbac/server.js.map +0 -1
  496. package/dist/rbac/server.mjs +0 -124
  497. package/dist/rbac/server.mjs.map +0 -1
  498. package/dist/schemas/index.d.mts +0 -1257
  499. package/dist/schemas/index.d.ts +0 -1257
  500. package/dist/schemas/index.js +0 -572
  501. package/dist/schemas/index.js.map +0 -1
  502. package/dist/schemas/index.mjs +0 -523
  503. package/dist/schemas/index.mjs.map +0 -1
  504. package/dist/server-QuYCTa89.d.mts +0 -83
  505. package/dist/server-QuYCTa89.d.ts +0 -83
  506. package/dist/sonner-C74GlRDQ.d.mts +0 -71
  507. package/dist/sonner-C74GlRDQ.d.ts +0 -71
  508. package/dist/status-BOXZgIqX.d.mts +0 -12
  509. package/dist/status-BOXZgIqX.d.ts +0 -12
  510. package/dist/system/index.d.mts +0 -77
  511. package/dist/system/index.d.ts +0 -77
  512. package/dist/system/index.js +0 -102
  513. package/dist/system/index.js.map +0 -1
  514. package/dist/system/index.mjs +0 -100
  515. package/dist/system/index.mjs.map +0 -1
  516. package/dist/tabs-C6FfBwPY.d.mts +0 -18
  517. package/dist/tabs-C6FfBwPY.d.ts +0 -18
  518. package/dist/tenant-provider-B8eC_Wpb.d.mts +0 -27
  519. package/dist/tenant-provider-B8eC_Wpb.d.ts +0 -27
  520. package/dist/types/index.d.mts +0 -469
  521. package/dist/types/index.d.ts +0 -469
  522. package/dist/types/index.js +0 -25
  523. package/dist/types/index.js.map +0 -1
  524. package/dist/types/index.mjs +0 -21
  525. package/dist/types/index.mjs.map +0 -1
  526. package/dist/ui/auth.d.mts +0 -39
  527. package/dist/ui/auth.d.ts +0 -39
  528. package/dist/ui/auth.js +0 -4941
  529. package/dist/ui/auth.js.map +0 -1
  530. package/dist/ui/auth.mjs +0 -4896
  531. package/dist/ui/auth.mjs.map +0 -1
  532. package/dist/ui/crud.d.mts +0 -2
  533. package/dist/ui/crud.d.ts +0 -2
  534. package/dist/ui/crud.js +0 -4
  535. package/dist/ui/crud.js.map +0 -1
  536. package/dist/ui/crud.mjs +0 -3
  537. package/dist/ui/crud.mjs.map +0 -1
  538. package/dist/ui/data-display.d.mts +0 -596
  539. package/dist/ui/data-display.d.ts +0 -596
  540. package/dist/ui/data-display.js +0 -5307
  541. package/dist/ui/data-display.js.map +0 -1
  542. package/dist/ui/data-display.mjs +0 -5212
  543. package/dist/ui/data-display.mjs.map +0 -1
  544. package/dist/ui/feedback.d.mts +0 -55
  545. package/dist/ui/feedback.d.ts +0 -55
  546. package/dist/ui/feedback.js +0 -2608
  547. package/dist/ui/feedback.js.map +0 -1
  548. package/dist/ui/feedback.mjs +0 -2526
  549. package/dist/ui/feedback.mjs.map +0 -1
  550. package/dist/ui/forms.d.mts +0 -309
  551. package/dist/ui/forms.d.ts +0 -309
  552. package/dist/ui/forms.js +0 -4656
  553. package/dist/ui/forms.js.map +0 -1
  554. package/dist/ui/forms.mjs +0 -4571
  555. package/dist/ui/forms.mjs.map +0 -1
  556. package/dist/ui/index.d.mts +0 -331
  557. package/dist/ui/index.d.ts +0 -331
  558. package/dist/ui/index.js +0 -16953
  559. package/dist/ui/index.js.map +0 -1
  560. package/dist/ui/index.mjs +0 -16598
  561. package/dist/ui/index.mjs.map +0 -1
  562. package/dist/ui/primitives/client.d.mts +0 -61
  563. package/dist/ui/primitives/client.d.ts +0 -61
  564. package/dist/ui/primitives/client.js +0 -3408
  565. package/dist/ui/primitives/client.js.map +0 -1
  566. package/dist/ui/primitives/client.mjs +0 -3256
  567. package/dist/ui/primitives/client.mjs.map +0 -1
  568. package/dist/ui/primitives.d.mts +0 -113
  569. package/dist/ui/primitives.d.ts +0 -113
  570. package/dist/ui/primitives.js +0 -3356
  571. package/dist/ui/primitives.js.map +0 -1
  572. package/dist/ui/primitives.mjs +0 -3227
  573. package/dist/ui/primitives.mjs.map +0 -1
  574. package/dist/user/index.d.mts +0 -228
  575. package/dist/user/index.d.ts +0 -228
  576. package/dist/user/index.js +0 -4306
  577. package/dist/user/index.js.map +0 -1
  578. package/dist/user/index.mjs +0 -4260
  579. package/dist/user/index.mjs.map +0 -1
  580. package/dist/utils/index.d.mts +0 -205
  581. package/dist/utils/index.d.ts +0 -205
  582. package/dist/utils/index.js +0 -574
  583. package/dist/utils/index.js.map +0 -1
  584. package/dist/utils/index.mjs +0 -514
  585. package/dist/utils/index.mjs.map +0 -1
  586. package/dist/workflow/index.d.mts +0 -40
  587. package/dist/workflow/index.d.ts +0 -40
  588. package/dist/workflow/index.js +0 -3710
  589. package/dist/workflow/index.js.map +0 -1
  590. package/dist/workflow/index.mjs +0 -3677
  591. package/dist/workflow/index.mjs.map +0 -1
@@ -0,0 +1,171 @@
1
+ "use client";
2
+
3
+ import React, { useCallback, useEffect, useState } from "react";
4
+ import useEmblaCarousel from "embla-carousel-react";
5
+ import Autoplay from "embla-carousel-autoplay";
6
+ import { ChevronLeft, ChevronRight } from "lucide-react";
7
+ import { cn } from "../utils";
8
+ import { ERP_FEATURES } from "./types";
9
+ import type { ERPFeature } from "./types";
10
+
11
+ interface FeatureShowcaseProps {
12
+ className?: string;
13
+ }
14
+
15
+ export function FeatureShowcase({ className }: FeatureShowcaseProps) {
16
+ const [emblaRef, emblaApi] = useEmblaCarousel(
17
+ { loop: true, align: "start" },
18
+ [Autoplay({ delay: 5000, stopOnInteraction: true })],
19
+ );
20
+ const [prevBtnEnabled, setPrevBtnEnabled] = useState(false);
21
+ const [nextBtnEnabled, setNextBtnEnabled] = useState(false);
22
+ const [selectedIndex, setSelectedIndex] = useState(0);
23
+ const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);
24
+
25
+ const scrollPrev = useCallback(
26
+ () => emblaApi && emblaApi.scrollPrev(),
27
+ [emblaApi],
28
+ );
29
+ const scrollNext = useCallback(
30
+ () => emblaApi && emblaApi.scrollNext(),
31
+ [emblaApi],
32
+ );
33
+ const scrollTo = useCallback(
34
+ (index: number) => emblaApi && emblaApi.scrollTo(index),
35
+ [emblaApi],
36
+ );
37
+
38
+ const onSelect = useCallback(() => {
39
+ if (!emblaApi) return;
40
+ setSelectedIndex(emblaApi.selectedScrollSnap());
41
+ setPrevBtnEnabled(emblaApi.canScrollPrev());
42
+ setNextBtnEnabled(emblaApi.canScrollNext());
43
+ }, [emblaApi]);
44
+
45
+ useEffect(() => {
46
+ if (!emblaApi) return;
47
+ onSelect();
48
+ setScrollSnaps(emblaApi.scrollSnapList());
49
+ emblaApi.on("select", onSelect);
50
+ emblaApi.on("reInit", onSelect);
51
+ return () => {
52
+ emblaApi.off("select", onSelect);
53
+ emblaApi.off("reInit", onSelect);
54
+ };
55
+ }, [emblaApi, onSelect]);
56
+
57
+ return (
58
+ <div
59
+ className={cn(
60
+ "bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 shadow-sm relative overflow-hidden flex flex-col h-full",
61
+ className,
62
+ )}
63
+ >
64
+ {/* Header */}
65
+ <div className="flex items-center justify-between px-6 py-4 border-b border-slate-100 dark:border-slate-700/50 bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm z-20">
66
+ <div className="flex items-center gap-2">
67
+ <div className="bg-blue-100 dark:bg-blue-900/30 text-primary p-1 rounded-md">
68
+ <svg
69
+ className="w-[18px] h-[18px]"
70
+ viewBox="0 0 24 24"
71
+ fill="none"
72
+ stroke="currentColor"
73
+ strokeWidth="2"
74
+ >
75
+ <path d="M12 2v20M2 12h20M12 2a10 10 0 0 1 10 10 10 10 0 0 1-10 10 10 10 0 0 1-10-10 10 10 0 0 1 10-10z" />
76
+ </svg>
77
+ </div>
78
+ <span className="text-sm font-bold text-slate-700 dark:text-slate-200">
79
+ Feature Tour
80
+ </span>
81
+ </div>
82
+ <button className="text-xs font-medium text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-slate-200 px-3 py-1.5 rounded hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors">
83
+ Skip Tour
84
+ </button>
85
+ </div>
86
+
87
+ {/* Carousel Content */}
88
+ <div
89
+ className="flex-1 relative overflow-hidden bg-slate-50/50 dark:bg-slate-800/50"
90
+ ref={emblaRef}
91
+ >
92
+ <div className="flex touch-pan-y h-full">
93
+ {ERP_FEATURES.map((feature, index) => (
94
+ <div key={feature.id} className="flex-[0_0_100%] min-w-0">
95
+ <div className="p-6 sm:p-8 flex flex-col items-center text-center gap-6 h-full justify-center">
96
+ <div className="mb-2 text-xs font-semibold text-primary uppercase tracking-wider">
97
+ Step {index + 1} of {ERP_FEATURES.length}
98
+ </div>
99
+
100
+ <div
101
+ className={cn(
102
+ "flex h-16 w-16 shrink-0 items-center justify-center rounded-2xl bg-gradient-to-br text-3xl shadow-md",
103
+ feature.color,
104
+ )}
105
+ >
106
+ {feature.icon}
107
+ </div>
108
+
109
+ <h2 className="text-2xl md:text-3xl font-bold text-slate-900 dark:text-white">
110
+ {feature.title}
111
+ </h2>
112
+
113
+ <p className="text-slate-500 dark:text-slate-400 text-sm md:text-base leading-relaxed max-w-md">
114
+ {feature.description}
115
+ </p>
116
+
117
+ <div className="flex gap-2 justify-center flex-wrap">
118
+ {feature.subFeatures.map((sub) => (
119
+ <span
120
+ key={sub}
121
+ className="px-2 py-1 bg-white dark:bg-slate-700 border border-slate-200 dark:border-slate-600 rounded-md text-xs font-medium text-slate-600 dark:text-slate-300"
122
+ >
123
+ {sub}
124
+ </span>
125
+ ))}
126
+ </div>
127
+ </div>
128
+ </div>
129
+ ))}
130
+ </div>
131
+ </div>
132
+
133
+ {/* Footer Navigation */}
134
+ <div className="px-6 py-4 bg-white dark:bg-slate-800 border-t border-slate-100 dark:border-slate-700 flex items-center justify-between z-20">
135
+ {/* Dots */}
136
+ <div className="flex gap-1.5">
137
+ {scrollSnaps.map((_, index) => (
138
+ <button
139
+ key={index}
140
+ className={cn(
141
+ "h-1.5 rounded-full transition-all duration-300",
142
+ index === selectedIndex
143
+ ? "w-6 bg-primary"
144
+ : "w-1.5 bg-slate-300 dark:bg-slate-600",
145
+ )}
146
+ onClick={() => scrollTo(index)}
147
+ />
148
+ ))}
149
+ </div>
150
+
151
+ {/* Buttons */}
152
+ <div className="flex gap-3">
153
+ <button
154
+ onClick={scrollPrev}
155
+ disabled={!prevBtnEnabled}
156
+ className="w-9 h-9 flex items-center justify-center rounded-lg border border-slate-200 dark:border-slate-700 text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
157
+ >
158
+ <ChevronLeft className="w-4 h-4" />
159
+ </button>
160
+ <button
161
+ onClick={scrollNext}
162
+ className="h-9 px-4 rounded-lg bg-primary text-white text-sm font-medium flex items-center gap-2 hover:bg-primary/90 transition-colors shadow-sm"
163
+ >
164
+ Next
165
+ <ChevronRight className="w-4 h-4" />
166
+ </button>
167
+ </div>
168
+ </div>
169
+ </div>
170
+ );
171
+ }
@@ -0,0 +1,191 @@
1
+ "use client";
2
+
3
+ import { useRouter } from "next/navigation";
4
+ import useSWR from "swr";
5
+ import { LayoutDashboard, Settings } from "lucide-react";
6
+ import { cn } from "../utils";
7
+ import { WelcomeCard } from "./welcome-card";
8
+ import { WidgetContainer } from "./widget-container";
9
+ import { FeatureShowcase } from "./feature-showcase";
10
+ import { QuickAccessMenu, DEFAULT_QUICK_ACCESS } from "./quick-access-menu";
11
+ import { useWidgetPreferences } from "./hooks/useWidgetPreferences";
12
+ import type { QuickAccessItem, WidgetConfig } from "./types";
13
+
14
+ interface HomePageProps {
15
+ userName?: string;
16
+ userId?: string;
17
+ widgetData?: {
18
+ revenue?: { total: number; change?: number };
19
+ orders?: {
20
+ total: number;
21
+ pending?: number;
22
+ completed?: number;
23
+ change?: number;
24
+ };
25
+ customers?: { total: number; newToday?: number; change?: number };
26
+ stock?: {
27
+ totalItems: number;
28
+ lowStockCount: number;
29
+ lowStockItems?: Array<{
30
+ id: string;
31
+ name: string;
32
+ quantity: number;
33
+ minStock: number;
34
+ }>;
35
+ };
36
+ };
37
+ availableFeatures?: Array<{ label: string; href: string; icon?: string }>;
38
+ widgetDataLoading?: boolean;
39
+ showFeatureShowcase?: boolean;
40
+ className?: string;
41
+ basePath?: string;
42
+ dashboardApiUrl?: string;
43
+ }
44
+
45
+ export function HomePage({
46
+ userName = "Bạn",
47
+ userId,
48
+ widgetData: initialWidgetData,
49
+ availableFeatures,
50
+ widgetDataLoading = false,
51
+ showFeatureShowcase = false,
52
+ className,
53
+ basePath = "",
54
+ dashboardApiUrl,
55
+ }: HomePageProps & { dashboardApiUrl?: string }) {
56
+ const router = useRouter();
57
+
58
+ // ... hook logic remains ...
59
+ const { data: fetchedWidgetData, isLoading: isFetching } = useSWR(
60
+ initialWidgetData ? null : dashboardApiUrl,
61
+ async (url) => {
62
+ const res = await fetch(url);
63
+ if (!res.ok) throw new Error("Failed to fetch widget data");
64
+ return res.json();
65
+ },
66
+ {
67
+ revalidateOnFocus: false,
68
+ dedupingInterval: 60000, // 1 minute
69
+ },
70
+ );
71
+
72
+ const widgetData = initialWidgetData || fetchedWidgetData;
73
+ const isLoading =
74
+ widgetDataLoading || (dashboardApiUrl && !initialWidgetData && isFetching);
75
+
76
+ const {
77
+ widgets,
78
+ quickAccess,
79
+ loading: prefsLoading,
80
+ updateWidgets,
81
+ updateQuickAccess,
82
+ } = useWidgetPreferences({
83
+ userId,
84
+ });
85
+
86
+ // Filter out Home from available features to prevent adding it as a shortcut
87
+ // and to exclude it from defaults
88
+ const filteredFeatures = availableFeatures?.filter(
89
+ (f) =>
90
+ f.href !== "/home" && f.href !== basePath + "/home" && f.href !== "/",
91
+ );
92
+
93
+ const handleQuickAccessClick = (item: QuickAccessItem) => {
94
+ router.push(`${basePath}${item.href}`);
95
+ };
96
+
97
+ const handleWidgetsChange = async (newWidgets: WidgetConfig[]) => {
98
+ await updateWidgets(newWidgets);
99
+ };
100
+
101
+ // Calculate effective quick access items
102
+ // If user has saved preferences (length > 0), use them.
103
+ // Otherwise, if availableFeatures are provided, generate a default list from them (up to 5 items).
104
+ // Finally, fallback to DEFAULT_QUICK_ACCESS.
105
+ const getAuthorizedDefaults = (): QuickAccessItem[] => {
106
+ if (filteredFeatures && filteredFeatures.length > 0) {
107
+ const colors = [
108
+ "blue",
109
+ "green",
110
+ "purple",
111
+ "orange",
112
+ "teal",
113
+ "pink",
114
+ "indigo",
115
+ "red",
116
+ ];
117
+ return filteredFeatures.slice(0, 5).map((feature, index) => ({
118
+ id: `default-${index}`,
119
+ label: feature.label,
120
+ href: feature.href,
121
+ icon: feature.icon || "document-text",
122
+ color: colors[index % colors.length],
123
+ }));
124
+ }
125
+ // If no authorized features, return empty to avoid showing unauthorized default items
126
+ return [];
127
+ };
128
+
129
+ const displayQuickAccess =
130
+ quickAccess && quickAccess.length > 0
131
+ ? quickAccess
132
+ : getAuthorizedDefaults();
133
+
134
+ return (
135
+ <div
136
+ className={cn(
137
+ "min-h-screen bg-slate-50/50 dark:bg-slate-900/50",
138
+ className,
139
+ )}
140
+ >
141
+ <div className="w-full mx-auto px-4 md:px-6 lg:px-8 py-6 space-y-8">
142
+ {/* Header Section */}
143
+ <WelcomeCard userName={userName} />
144
+
145
+ {/* My Workspace Section - Temporarily Hidden via separate prop or conditional */}
146
+ {/* Added explicit check to hide widgets if requested */}
147
+ {false && (
148
+ <div className="flex flex-col gap-4 animate-in fade-in slide-in-from-bottom-4 duration-500 delay-150">
149
+ <div className="flex items-center justify-between px-1">
150
+ <div className="flex items-center gap-2">
151
+ <LayoutDashboard className="w-5 h-5 text-primary" />
152
+ <h3 className="text-lg font-bold text-slate-900 dark:text-white">
153
+ My Workspace
154
+ </h3>
155
+ </div>
156
+ <button className="text-xs font-medium text-slate-500 hover:text-primary transition-colors flex items-center gap-1 group">
157
+ <Settings className="w-4 h-4 group-hover:rotate-180 transition-transform duration-500" />
158
+ Configure Widgets
159
+ </button>
160
+ </div>
161
+
162
+ <WidgetContainer
163
+ widgets={widgets}
164
+ onWidgetsChange={handleWidgetsChange}
165
+ widgetData={widgetData}
166
+ loading={isLoading || prefsLoading}
167
+ />
168
+ </div>
169
+ )}
170
+
171
+ {/* Quick Access Section */}
172
+ <div className="animate-in fade-in slide-in-from-bottom-4 duration-500 delay-300">
173
+ <QuickAccessMenu
174
+ items={displayQuickAccess}
175
+ onItemClick={handleQuickAccessClick}
176
+ editable={true}
177
+ onItemsChange={updateQuickAccess}
178
+ availableFeatures={filteredFeatures}
179
+ />
180
+ </div>
181
+
182
+ {/* Feature Tour Section - Hidden by default prop or explicit false */}
183
+ {showFeatureShowcase && (
184
+ <div className="animate-in fade-in slide-in-from-bottom-4 duration-500 delay-500 min-h-[400px]">
185
+ <FeatureShowcase />
186
+ </div>
187
+ )}
188
+ </div>
189
+ </div>
190
+ );
191
+ }
@@ -0,0 +1 @@
1
+ export { useWidgetPreferences } from "./useWidgetPreferences";
@@ -0,0 +1,167 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect, useCallback } from "react";
4
+ import useSWR from "swr";
5
+ import type {
6
+ WidgetConfig,
7
+ UserHomePreferences,
8
+ QuickAccessItem,
9
+ } from "../types";
10
+ import { DEFAULT_WIDGETS } from "../types";
11
+
12
+ interface UseWidgetPreferencesOptions {
13
+ userId?: string;
14
+ apiEndpoint?: string;
15
+ fallbackToLocalStorage?: boolean;
16
+ }
17
+
18
+ interface UseWidgetPreferencesReturn {
19
+ widgets: WidgetConfig[];
20
+ quickAccess: QuickAccessItem[];
21
+ loading: boolean;
22
+ error: string | null;
23
+ updateWidgets: (widgets: WidgetConfig[]) => Promise<void>;
24
+ updateQuickAccess: (items: QuickAccessItem[]) => Promise<void>;
25
+ resetToDefaults: () => Promise<void>;
26
+ }
27
+
28
+ const LOCAL_STORAGE_KEY = "goerp_home_preferences";
29
+
30
+ async function fetchPreferences(url: string): Promise<UserHomePreferences> {
31
+ const res = await fetch(url);
32
+ if (!res.ok) {
33
+ throw new Error("Failed to fetch preferences");
34
+ }
35
+ return res.json();
36
+ }
37
+
38
+ export function useWidgetPreferences({
39
+ userId,
40
+ apiEndpoint = "/api/user/preferences",
41
+ fallbackToLocalStorage = false,
42
+ }: UseWidgetPreferencesOptions = {}): UseWidgetPreferencesReturn {
43
+ const [localPreferences, setLocalPreferences] =
44
+ useState<UserHomePreferences | null>(null);
45
+
46
+ // Use SWR for API fetching when userId is provided
47
+ const { data, error, isLoading, mutate } = useSWR<UserHomePreferences>(
48
+ userId ? `${apiEndpoint}?userId=${userId}` : null,
49
+ fetchPreferences,
50
+ {
51
+ revalidateOnFocus: false,
52
+ // Only use localPreferences as fallback if explicitly enabled
53
+ fallbackData: fallbackToLocalStorage
54
+ ? localPreferences || undefined
55
+ : undefined,
56
+ },
57
+ );
58
+
59
+ // Use a user-specific key for localStorage to prevent data leakage between users
60
+ const storageKey = userId
61
+ ? `${LOCAL_STORAGE_KEY}_${userId}`
62
+ : LOCAL_STORAGE_KEY;
63
+
64
+ // Load from localStorage ONLY if fallback is enabled
65
+ useEffect(() => {
66
+ if (fallbackToLocalStorage && typeof window !== "undefined") {
67
+ try {
68
+ const stored = localStorage.getItem(storageKey);
69
+ if (stored) {
70
+ setLocalPreferences(JSON.parse(stored));
71
+ } else {
72
+ setLocalPreferences(null);
73
+ }
74
+ } catch {
75
+ // console.warn("Failed to load preferences from localStorage");
76
+ }
77
+ }
78
+ }, [fallbackToLocalStorage, storageKey]);
79
+
80
+ // Get the current preferences
81
+ const preferences = data ||
82
+ localPreferences || {
83
+ widgets: DEFAULT_WIDGETS,
84
+ quickAccess: [],
85
+ };
86
+
87
+ // Save preferences
88
+ const savePreferences = useCallback(
89
+ async (newPreferences: UserHomePreferences) => {
90
+ // Optimistic update
91
+ mutate(newPreferences, false);
92
+
93
+ // Save to localStorage (only if enabled)
94
+ if (fallbackToLocalStorage && typeof window !== "undefined") {
95
+ try {
96
+ localStorage.setItem(storageKey, JSON.stringify(newPreferences));
97
+ setLocalPreferences(newPreferences);
98
+ } catch {
99
+ // console.warn("Failed to save preferences to localStorage");
100
+ }
101
+ }
102
+
103
+ // Save to API if userId is provided
104
+ if (userId) {
105
+ try {
106
+ const res = await fetch(apiEndpoint, {
107
+ method: "PUT",
108
+ headers: { "Content-Type": "application/json" },
109
+ body: JSON.stringify({
110
+ userId,
111
+ ...newPreferences,
112
+ }),
113
+ });
114
+
115
+ if (!res.ok) {
116
+ throw new Error("Failed to save preferences");
117
+ }
118
+
119
+ // Revalidate from server
120
+ mutate();
121
+ } catch (err) {
122
+ console.error("Failed to save preferences to API:", err);
123
+ // Rollback optimistic update
124
+ mutate();
125
+ }
126
+ }
127
+ },
128
+ [userId, apiEndpoint, fallbackToLocalStorage, mutate, storageKey],
129
+ );
130
+
131
+ const updateWidgets = useCallback(
132
+ async (widgets: WidgetConfig[]) => {
133
+ await savePreferences({
134
+ ...preferences,
135
+ widgets,
136
+ });
137
+ },
138
+ [preferences, savePreferences],
139
+ );
140
+
141
+ const updateQuickAccess = useCallback(
142
+ async (quickAccess: QuickAccessItem[]) => {
143
+ await savePreferences({
144
+ ...preferences,
145
+ quickAccess,
146
+ });
147
+ },
148
+ [preferences, savePreferences],
149
+ );
150
+
151
+ const resetToDefaults = useCallback(async () => {
152
+ await savePreferences({
153
+ widgets: DEFAULT_WIDGETS,
154
+ quickAccess: [],
155
+ });
156
+ }, [savePreferences]);
157
+
158
+ return {
159
+ widgets: preferences.widgets,
160
+ quickAccess: preferences.quickAccess,
161
+ loading: isLoading,
162
+ error: error?.message || null,
163
+ updateWidgets,
164
+ updateQuickAccess,
165
+ resetToDefaults,
166
+ };
167
+ }
@@ -0,0 +1,33 @@
1
+ // Home Module - Main exports
2
+ export { HomePage } from "./home-page";
3
+ export { WelcomeCard } from "./welcome-card";
4
+ export { FeatureShowcase } from "./feature-showcase";
5
+ export { WidgetContainer } from "./widget-container";
6
+ export { QuickAccessMenu, DEFAULT_QUICK_ACCESS } from "./quick-access-menu";
7
+
8
+ // Widget exports
9
+ export {
10
+ BaseWidget,
11
+ WidgetStat,
12
+ RevenueWidget,
13
+ OrdersWidget,
14
+ CustomersWidget,
15
+ StockWidget,
16
+ } from "./widgets";
17
+
18
+ // Hook exports
19
+ export { useWidgetPreferences } from "./hooks";
20
+
21
+ // Type exports
22
+ export type {
23
+ WidgetConfig,
24
+ WidgetType,
25
+ WidgetSize,
26
+ WidgetProps,
27
+ WidgetData,
28
+ QuickAccessItem,
29
+ UserHomePreferences,
30
+ ERPFeature,
31
+ } from "./types";
32
+
33
+ export { DEFAULT_WIDGETS, WIDGET_LABELS, ERP_FEATURES } from "./types";