@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,271 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ import { useForm } from "react-hook-form";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import * as z from "zod";
6
+
7
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
8
+ import { X } from "lucide-react";
9
+ import { cn } from "../utils";
10
+ import type { QuickAccessItem } from "./types";
11
+ import { iconMap } from "./constants";
12
+
13
+ const AVAILABLE_ICONS = Object.keys(iconMap);
14
+ const AVAILABLE_COLORS = [
15
+ "blue",
16
+ "green",
17
+ "purple",
18
+ "orange",
19
+ "pink",
20
+ "indigo",
21
+ "teal",
22
+ "red",
23
+ ];
24
+
25
+ const formSchema = z.object({
26
+ label: z.string().min(1, "Vui lòng nhập tên lối tắt"),
27
+ href: z.string().min(1, "Vui lòng nhập đường dẫn"),
28
+ icon: z.string(),
29
+ color: z.string(),
30
+ });
31
+
32
+ type FormValues = z.infer<typeof formSchema>;
33
+
34
+ interface QuickAccessDialogProps {
35
+ open: boolean;
36
+ onOpenChange: (open: boolean) => void;
37
+ onSubmit: (data: Omit<QuickAccessItem, "id">) => void;
38
+ initialData?: QuickAccessItem;
39
+ availableFeatures?: Array<{ label: string; href: string; icon?: string }>;
40
+ }
41
+
42
+ export function QuickAccessDialog({
43
+ open,
44
+ onOpenChange,
45
+ onSubmit,
46
+ initialData,
47
+ availableFeatures,
48
+ }: QuickAccessDialogProps) {
49
+ const form = useForm<FormValues>({
50
+ resolver: zodResolver(formSchema),
51
+ defaultValues: {
52
+ label: "",
53
+ href: "",
54
+ icon: "document-text",
55
+ color: "blue",
56
+ },
57
+ });
58
+
59
+ // Reset form when dialog opens/closes or initialData changes
60
+ useEffect(() => {
61
+ if (open) {
62
+ form.reset(
63
+ initialData
64
+ ? {
65
+ label: initialData.label,
66
+ href: initialData.href,
67
+ icon: initialData.icon,
68
+ color: initialData.color,
69
+ }
70
+ : {
71
+ label: "",
72
+ href: "",
73
+ icon: "document-text",
74
+ color: "blue",
75
+ },
76
+ );
77
+ }
78
+ }, [open, initialData, form]);
79
+
80
+ const handleSubmit = (values: FormValues) => {
81
+ onSubmit(values);
82
+ onOpenChange(false);
83
+ };
84
+
85
+ const handleFeatureChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
86
+ const selectedHref = e.target.value;
87
+ const feature = availableFeatures?.find((f) => f.href === selectedHref);
88
+
89
+ if (feature) {
90
+ form.setValue("href", feature.href);
91
+ form.setValue("label", feature.label);
92
+ if (feature.icon && iconMap[feature.icon]) {
93
+ form.setValue("icon", feature.icon);
94
+ } else if (feature.icon && iconMap[feature.icon.replace(/-/g, "")]) {
95
+ // Attempt fuzzy match or mapping if needed, theoretically icon names should match
96
+ }
97
+ }
98
+ };
99
+
100
+ return (
101
+ <DialogPrimitive.Root open={open} onOpenChange={onOpenChange}>
102
+ <DialogPrimitive.Portal>
103
+ <DialogPrimitive.Overlay className="fixed inset-0 z-50 bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" />
104
+ <DialogPrimitive.Content className="fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg">
105
+ <div className="flex flex-col space-y-1.5 text-center sm:text-left">
106
+ <DialogPrimitive.Title className="text-lg font-semibold leading-none tracking-tight">
107
+ {initialData ? "Sửa lối tắt" : "Thêm lối tắt mới"}
108
+ </DialogPrimitive.Title>
109
+ <DialogPrimitive.Description className="text-sm text-muted-foreground">
110
+ Tạo lối tắt để truy cập nhanh các tính năng thường dùng
111
+ </DialogPrimitive.Description>
112
+ </div>
113
+
114
+ <form
115
+ onSubmit={form.handleSubmit(handleSubmit)}
116
+ className="space-y-4"
117
+ >
118
+ <div className="grid gap-4 py-4">
119
+ {/* Feature Selection if available */}
120
+ {availableFeatures && availableFeatures.length > 0 && (
121
+ <div className="grid grid-cols-4 items-center gap-4">
122
+ <label
123
+ htmlFor="feature-select"
124
+ className="text-right text-sm font-medium"
125
+ >
126
+ Chức năng
127
+ </label>
128
+ <div className="col-span-3">
129
+ <select
130
+ id="feature-select"
131
+ className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
132
+ onChange={handleFeatureChange}
133
+ defaultValue={initialData?.href || ""}
134
+ >
135
+ <option value="">Chọn chức năng...</option>
136
+ {availableFeatures.map((f) => (
137
+ <option key={f.href} value={f.href}>
138
+ {f.label}
139
+ </option>
140
+ ))}
141
+ </select>
142
+ </div>
143
+ </div>
144
+ )}
145
+
146
+ <div className="grid grid-cols-4 items-center gap-4">
147
+ <label
148
+ htmlFor="label"
149
+ className="text-right text-sm font-medium"
150
+ >
151
+ Tên lối tắt
152
+ </label>
153
+ <div className="col-span-3">
154
+ <input
155
+ id="label"
156
+ className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
157
+ {...form.register("label")}
158
+ />
159
+ {form.formState.errors.label && (
160
+ <p className="text-xs text-red-500 mt-1">
161
+ {form.formState.errors.label.message}
162
+ </p>
163
+ )}
164
+ </div>
165
+ </div>
166
+
167
+ {/* Show HREF input only if NO features available (fallback) or if we want to show it as readonly?
168
+ The requirement says "only allow ... in the list".
169
+ So if list is present, HIDE the href input or make it readOnly hidden.
170
+ Let's hide it but keep it registered in form so validation passes.
171
+ */}
172
+ <div
173
+ className={cn(
174
+ "grid grid-cols-4 items-center gap-4",
175
+ availableFeatures?.length ? "hidden" : "",
176
+ )}
177
+ >
178
+ <label
179
+ htmlFor="href"
180
+ className="text-right text-sm font-medium"
181
+ >
182
+ Đường dẫn
183
+ </label>
184
+ <div className="col-span-3">
185
+ <input
186
+ id="href"
187
+ className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
188
+ {...form.register("href")}
189
+ readOnly={!!availableFeatures?.length}
190
+ />
191
+ {form.formState.errors.href && (
192
+ <p className="text-xs text-red-500 mt-1">
193
+ {form.formState.errors.href.message}
194
+ </p>
195
+ )}
196
+ </div>
197
+ </div>
198
+
199
+ <div className="grid grid-cols-4 items-start gap-4">
200
+ <label className="text-right text-sm font-medium pt-2">
201
+ Icon
202
+ </label>
203
+ <div className="col-span-3 flex flex-wrap gap-2">
204
+ {AVAILABLE_ICONS.map((icon) => (
205
+ <button
206
+ key={icon}
207
+ type="button"
208
+ onClick={() => form.setValue("icon", icon)}
209
+ className={cn(
210
+ "flex h-8 w-8 items-center justify-center rounded-md border transition-colors",
211
+ form.watch("icon") === icon
212
+ ? "border-primary bg-primary/10 text-primary"
213
+ : "border-input hover:bg-muted",
214
+ )}
215
+ >
216
+ {iconMap[icon]}
217
+ </button>
218
+ ))}
219
+ </div>
220
+ </div>
221
+
222
+ <div className="grid grid-cols-4 items-start gap-4">
223
+ <label className="text-right text-sm font-medium pt-2">
224
+ Màu sắc
225
+ </label>
226
+ <div className="col-span-3 flex flex-wrap gap-2">
227
+ {AVAILABLE_COLORS.map((color) => (
228
+ <button
229
+ key={color}
230
+ type="button"
231
+ onClick={() => form.setValue("color", color)}
232
+ className={cn(
233
+ "h-8 w-8 rounded-full border-2 transition-all",
234
+ `bg-${color}-500`,
235
+ form.watch("color") === color
236
+ ? "border-primary scale-110 shadow-sm"
237
+ : "border-transparent hover:scale-105",
238
+ )}
239
+ aria-label={color}
240
+ />
241
+ ))}
242
+ </div>
243
+ </div>
244
+ </div>
245
+
246
+ <div className="flex justify-end gap-2">
247
+ <DialogPrimitive.Close asChild>
248
+ <button
249
+ type="button"
250
+ className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-9 px-4 py-2"
251
+ >
252
+ Hủy
253
+ </button>
254
+ </DialogPrimitive.Close>
255
+ <button
256
+ type="submit"
257
+ className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-9 px-4 py-2"
258
+ >
259
+ {initialData ? "Lưu thay đổi" : "Thêm mới"}
260
+ </button>
261
+ </div>
262
+ </form>
263
+ <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
264
+ <X className="h-4 w-4" />
265
+ <span className="sr-only">Close</span>
266
+ </DialogPrimitive.Close>
267
+ </DialogPrimitive.Content>
268
+ </DialogPrimitive.Portal>
269
+ </DialogPrimitive.Root>
270
+ );
271
+ }
@@ -0,0 +1,267 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { motion, AnimatePresence } from "framer-motion";
5
+ import { Plus, X, Pencil, GripVertical } from "lucide-react";
6
+ import { cn } from "../utils";
7
+ import type { QuickAccessItem } from "./types";
8
+ import { QuickAccessDialog } from "./quick-access-dialog";
9
+
10
+ interface QuickAccessMenuProps {
11
+ items: QuickAccessItem[];
12
+ onItemClick?: (item: QuickAccessItem) => void;
13
+ onItemsChange?: (items: QuickAccessItem[]) => void;
14
+ className?: string;
15
+ editable?: boolean;
16
+ availableFeatures?: Array<{ label: string; href: string; icon?: string }>;
17
+ }
18
+
19
+ const containerVariants = {
20
+ hidden: { opacity: 0 },
21
+ visible: {
22
+ opacity: 1,
23
+ transition: {
24
+ staggerChildren: 0.05,
25
+ delayChildren: 0.1,
26
+ },
27
+ },
28
+ };
29
+
30
+ const itemVariants = {
31
+ hidden: { opacity: 0, scale: 0.9 },
32
+ visible: {
33
+ opacity: 1,
34
+ scale: 1,
35
+ transition: {
36
+ duration: 0.2,
37
+ ease: "easeOut",
38
+ },
39
+ },
40
+ };
41
+
42
+ import { iconMap, colorClasses } from "./constants";
43
+
44
+ export function QuickAccessMenu({
45
+ items,
46
+ onItemClick,
47
+ onItemsChange,
48
+ className,
49
+ editable = false,
50
+ availableFeatures,
51
+ }: QuickAccessMenuProps) {
52
+ const [isEditing, setIsEditing] = useState(false);
53
+ const [dialogOpen, setDialogOpen] = useState(false);
54
+ const [editingItem, setEditingItem] = useState<QuickAccessItem | undefined>(
55
+ undefined,
56
+ );
57
+
58
+ const handleAddStart = () => {
59
+ setEditingItem(undefined);
60
+ setDialogOpen(true);
61
+ };
62
+
63
+ const handleEditStart = (item: QuickAccessItem, e: React.MouseEvent) => {
64
+ e.stopPropagation();
65
+ setEditingItem(item);
66
+ setDialogOpen(true);
67
+ };
68
+
69
+ const handleDelete = (itemId: string, e: React.MouseEvent) => {
70
+ e.stopPropagation();
71
+ if (confirm("Bạn có chắc muốn xóa lối tắt này?")) {
72
+ onItemsChange?.(items.filter((item) => item.id !== itemId));
73
+ }
74
+ };
75
+
76
+ const handleSave = (data: Omit<QuickAccessItem, "id">) => {
77
+ // Check for duplicates
78
+ const isDuplicate = items.some(
79
+ (item) => item.href === data.href && item.id !== editingItem?.id,
80
+ );
81
+
82
+ if (isDuplicate) {
83
+ alert("Lối tắt này đã tồn tại!");
84
+ return;
85
+ }
86
+
87
+ if (editingItem) {
88
+ // Edit existing
89
+ onItemsChange?.(
90
+ items.map((item) =>
91
+ item.id === editingItem.id ? { ...item, ...data } : item,
92
+ ),
93
+ );
94
+ } else {
95
+ // Add new
96
+ const newItem: QuickAccessItem = {
97
+ ...data,
98
+ id: `custom-${Date.now()}`,
99
+ };
100
+ onItemsChange?.([...items, newItem]);
101
+ }
102
+ };
103
+
104
+ if (items.length === 0 && !editable) {
105
+ return null;
106
+ }
107
+
108
+ return (
109
+ <div className={cn("space-y-4", className)}>
110
+ <div className="flex items-center justify-between">
111
+ <h3 className="text-slate-900 dark:text-white text-lg font-bold">
112
+ Quick Shortcuts
113
+ </h3>
114
+ </div>
115
+
116
+ <motion.div
117
+ variants={containerVariants}
118
+ initial="hidden"
119
+ animate="visible"
120
+ // @ts-ignore className is valid for motion.div
121
+ className="grid grid-cols-2 gap-4 sm:grid-cols-4"
122
+ >
123
+ <AnimatePresence mode="popLayout">
124
+ {items.map((item) => (
125
+ <motion.button
126
+ key={item.id}
127
+ variants={itemVariants}
128
+ whileHover={{ scale: 1.02 }}
129
+ whileTap={{ scale: 0.98 }}
130
+ // @ts-ignore onClick and className are valid for motion.button
131
+ onClick={() => {
132
+ if (!isEditing) {
133
+ onItemClick?.(item);
134
+ }
135
+ }}
136
+ className={cn(
137
+ "group relative flex flex-col items-center justify-center gap-3 bg-white dark:bg-slate-800 p-5 rounded-xl border border-slate-200 dark:border-slate-700 shadow-sm hover:shadow-md hover:border-primary/50 transition-all text-left",
138
+ isEditing && "cursor-default opacity-90 hover:opacity-100",
139
+ )}
140
+ >
141
+ {isEditing && (
142
+ <>
143
+ <div
144
+ onClick={(e) => handleDelete(item.id, e)}
145
+ className="absolute -right-2 -top-2 z-10 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full bg-destructive text-white shadow-sm ring-2 ring-white hover:bg-destructive/90"
146
+ >
147
+ <X className="h-3 w-3" />
148
+ </div>
149
+ <div
150
+ onClick={(e) => handleEditStart(item, e)}
151
+ className="absolute -left-2 -top-2 z-10 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full bg-background text-foreground shadow-sm ring-2 ring-white hover:bg-muted"
152
+ >
153
+ <Pencil className="h-3 w-3" />
154
+ </div>
155
+ </>
156
+ )}
157
+
158
+ {editable && (
159
+ <span
160
+ onClick={() => setIsEditing(!isEditing)}
161
+ className="absolute top-2 right-2 text-slate-300 dark:text-slate-600 cursor-move opacity-100 hover:text-primary transition-colors"
162
+ >
163
+ <GripVertical size={18} />
164
+ </span>
165
+ )}
166
+
167
+ <div
168
+ className={cn(
169
+ "size-12 rounded-full flex items-center justify-center group-hover:scale-110 transition-transform",
170
+ colorClasses[item.color || "blue"] || colorClasses.blue,
171
+ )}
172
+ >
173
+ {iconMap[item.icon] || iconMap["document-text"]}
174
+ </div>
175
+ <span className="text-slate-700 dark:text-slate-200 font-semibold text-sm">
176
+ {item.label}
177
+ </span>
178
+ </motion.button>
179
+ ))}
180
+
181
+ {editable && (
182
+ <motion.button
183
+ variants={itemVariants}
184
+ // @ts-ignore
185
+ onClick={handleAddStart}
186
+ whileHover={{ scale: 1.02 }}
187
+ whileTap={{ scale: 0.98 }}
188
+ // @ts-ignore
189
+ className="flex flex-col items-center justify-center gap-2 bg-slate-50 dark:bg-slate-800/50 p-5 rounded-xl border-2 border-dashed border-slate-300 dark:border-slate-600 hover:border-primary hover:bg-slate-100 dark:hover:bg-slate-800 transition-all text-slate-500 hover:text-primary cursor-pointer group h-full min-h-[140px]"
190
+ >
191
+ <Plus className="h-8 w-8 group-hover:scale-110 transition-transform" />
192
+ <span className="text-sm font-medium">Add Shortcut</span>
193
+ </motion.button>
194
+ )}
195
+ </AnimatePresence>
196
+ </motion.div>
197
+
198
+ <QuickAccessDialog
199
+ open={dialogOpen}
200
+ onOpenChange={setDialogOpen}
201
+ onSubmit={handleSave}
202
+ initialData={editingItem}
203
+ availableFeatures={availableFeatures}
204
+ />
205
+ </div>
206
+ );
207
+ }
208
+
209
+ // Default quick access items
210
+ export const DEFAULT_QUICK_ACCESS: QuickAccessItem[] = [
211
+ {
212
+ id: "pos",
213
+ label: "Bán hàng",
214
+ href: "/sales/pos",
215
+ icon: "shopping-cart",
216
+ color: "green",
217
+ },
218
+ {
219
+ id: "orders",
220
+ label: "Đơn hàng",
221
+ href: "/sales-orders",
222
+ icon: "clipboard-list",
223
+ color: "blue",
224
+ },
225
+ {
226
+ id: "customers",
227
+ label: "Khách hàng",
228
+ href: "/customers",
229
+ icon: "users",
230
+ color: "purple",
231
+ },
232
+ {
233
+ id: "inventory",
234
+ label: "Tồn kho",
235
+ href: "/inventory",
236
+ icon: "package",
237
+ color: "orange",
238
+ },
239
+ {
240
+ id: "reports",
241
+ label: "Báo cáo",
242
+ href: "/reports",
243
+ icon: "chart-bar",
244
+ color: "teal",
245
+ },
246
+ {
247
+ id: "finance",
248
+ label: "Thu chi",
249
+ href: "/finance",
250
+ icon: "currency-dollar",
251
+ color: "pink",
252
+ },
253
+ {
254
+ id: "products",
255
+ label: "Sản phẩm",
256
+ href: "/crud/products",
257
+ icon: "package",
258
+ color: "indigo",
259
+ },
260
+ {
261
+ id: "settings",
262
+ label: "Cài đặt",
263
+ href: "/admin",
264
+ icon: "cog",
265
+ color: "red",
266
+ },
267
+ ];
@@ -0,0 +1,140 @@
1
+ // Widget System Types for Home Page
2
+
3
+ export type WidgetType = "revenue" | "orders" | "customers" | "stock";
4
+
5
+ export type WidgetSize = "small" | "medium" | "large";
6
+
7
+ export interface WidgetConfig {
8
+ id: string;
9
+ type: WidgetType;
10
+ position: number;
11
+ visible: boolean;
12
+ size: WidgetSize;
13
+ settings?: Record<string, unknown>;
14
+ }
15
+
16
+ export interface WidgetProps {
17
+ config: WidgetConfig;
18
+ onRemove?: () => void;
19
+ onSettings?: () => void;
20
+ className?: string;
21
+ }
22
+
23
+ export interface WidgetData {
24
+ value: number | string;
25
+ label: string;
26
+ change?: {
27
+ value: number;
28
+ type: "increase" | "decrease";
29
+ period: string;
30
+ };
31
+ loading?: boolean;
32
+ error?: string;
33
+ }
34
+
35
+ export interface QuickAccessItem {
36
+ id: string;
37
+ label: string;
38
+ href: string;
39
+ icon: string;
40
+ color?: string;
41
+ }
42
+
43
+ export interface UserHomePreferences {
44
+ widgets: WidgetConfig[];
45
+ quickAccess: QuickAccessItem[]; // List of quick access items
46
+ }
47
+
48
+ export const DEFAULT_WIDGETS: WidgetConfig[] = [
49
+ {
50
+ id: "revenue",
51
+ type: "revenue",
52
+ position: 0,
53
+ visible: true,
54
+ size: "medium",
55
+ },
56
+ { id: "orders", type: "orders", position: 1, visible: true, size: "medium" },
57
+ {
58
+ id: "customers",
59
+ type: "customers",
60
+ position: 2,
61
+ visible: true,
62
+ size: "medium",
63
+ },
64
+ { id: "stock", type: "stock", position: 3, visible: true, size: "medium" },
65
+ ];
66
+
67
+ export const WIDGET_LABELS: Record<WidgetType, string> = {
68
+ revenue: "Doanh thu",
69
+ orders: "Đơn hàng",
70
+ customers: "Khách hàng",
71
+ stock: "Tồn kho",
72
+ };
73
+
74
+ export interface ERPFeature {
75
+ id: string;
76
+ icon: string;
77
+ title: string;
78
+ description: string;
79
+ subFeatures: string[];
80
+ color: string;
81
+ }
82
+
83
+ export const ERP_FEATURES: ERPFeature[] = [
84
+ {
85
+ id: "inventory",
86
+ icon: "📦",
87
+ title: "Quản lý Kho",
88
+ description: "Quản lý toàn diện hàng hóa và tồn kho",
89
+ subFeatures: ["Nhập/Xuất kho", "Kiểm kê", "Điều chuyển", "Cảnh báo tồn"],
90
+ color: "from-blue-500 to-cyan-500",
91
+ },
92
+ {
93
+ id: "sales",
94
+ icon: "💰",
95
+ title: "Quản lý Bán hàng",
96
+ description: "Xử lý đơn hàng và bán hàng hiệu quả",
97
+ subFeatures: ["POS", "Đơn hàng", "Hợp đồng", "Báo giá"],
98
+ color: "from-green-500 to-emerald-500",
99
+ },
100
+ {
101
+ id: "purchasing",
102
+ icon: "🛒",
103
+ title: "Quản lý Mua hàng",
104
+ description: "Quản lý nhà cung cấp và đặt hàng",
105
+ subFeatures: ["Đặt hàng NCC", "Nhập hàng", "Công nợ phải trả"],
106
+ color: "from-orange-500 to-amber-500",
107
+ },
108
+ {
109
+ id: "finance",
110
+ icon: "💵",
111
+ title: "Tài chính",
112
+ description: "Quản lý dòng tiền và công nợ",
113
+ subFeatures: ["Thu/Chi", "Sổ quỹ", "Công nợ", "Báo cáo tài chính"],
114
+ color: "from-purple-500 to-violet-500",
115
+ },
116
+ {
117
+ id: "crm",
118
+ icon: "👥",
119
+ title: "CRM",
120
+ description: "Chăm sóc và quản lý khách hàng",
121
+ subFeatures: ["Khách hàng", "Lịch sử giao dịch", "Phân loại"],
122
+ color: "from-pink-500 to-rose-500",
123
+ },
124
+ {
125
+ id: "hr",
126
+ icon: "👨‍💼",
127
+ title: "Nhân sự",
128
+ description: "Quản lý người dùng và phân quyền",
129
+ subFeatures: ["Users", "Phân quyền", "Roles"],
130
+ color: "from-indigo-500 to-blue-500",
131
+ },
132
+ {
133
+ id: "reports",
134
+ icon: "📊",
135
+ title: "Báo cáo",
136
+ description: "Thống kê và phân tích dữ liệu",
137
+ subFeatures: ["Dashboard", "Thống kê", "Export"],
138
+ color: "from-teal-500 to-green-500",
139
+ },
140
+ ];