@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,385 @@
1
+ "use client";
2
+
3
+ import { useState, useCallback } from "react";
4
+ import { useRouter, usePathname, useSearchParams } from "next/navigation";
5
+ import { useViewMode } from "../../hooks";
6
+ import { toast } from "sonner";
7
+ import {
8
+ Table,
9
+ TableBody,
10
+ TableCell,
11
+ TableHead,
12
+ TableHeader,
13
+ TableRow,
14
+ Badge,
15
+ Button,
16
+ } from "../../ui";
17
+ import { Edit2 } from "lucide-react";
18
+ import type { EntityConfig, CrudPermissions } from "../../types";
19
+
20
+ import { UserToolbar } from "../components/user-toolbar";
21
+ import { UserStats } from "../components/user-stats";
22
+ import { UsersCardView } from "../components/users-card-view";
23
+ import { UnifiedProfileDialog } from "../components/unified-profile-dialog";
24
+
25
+ interface UserStats {
26
+ totalUsers: number;
27
+ activeUsers: number;
28
+ employees: number;
29
+ customers: number;
30
+ suppliers: number;
31
+ }
32
+
33
+ interface UsersClientPageProps {
34
+ initialData: any[];
35
+ config: EntityConfig;
36
+ permissions: CrudPermissions;
37
+ dictionary: any;
38
+ roles: any[];
39
+ stats: UserStats;
40
+ onAssignRoles?: (userId: string, roleCodes: string[]) => Promise<any>;
41
+ onResetPassword?: (userId: string, password: string) => Promise<any>;
42
+ }
43
+
44
+ export function UsersClientPage({
45
+ initialData,
46
+ config,
47
+ permissions,
48
+ dictionary,
49
+ roles,
50
+ stats,
51
+ onAssignRoles,
52
+ onResetPassword,
53
+ }: UsersClientPageProps) {
54
+ const router = useRouter();
55
+ const pathname = usePathname();
56
+
57
+ const searchParams = useSearchParams();
58
+ // View Mode
59
+ const [viewModeRaw, handleViewModeChangeRaw] = useViewMode(
60
+ "users-view-mode",
61
+ "grid",
62
+ );
63
+ const viewMode =
64
+ viewModeRaw === "table" || viewModeRaw === "grid"
65
+ ? (viewModeRaw as "table" | "grid")
66
+ : "grid";
67
+ const handleViewModeChange = (mode: "table" | "grid") =>
68
+ handleViewModeChangeRaw(mode);
69
+
70
+ // Selection for Quick View
71
+ const [selectedUser, setSelectedUser] = useState<any>(null);
72
+ const [quickViewOpen, setQuickViewOpen] = useState(false);
73
+
74
+ // Dialogs State
75
+ const [userFormOpen, setUserFormOpen] = useState(false);
76
+ const [userFormMode, setUserFormMode] = useState<"create" | "edit">("create");
77
+ const [userFormData, setUserFormData] = useState<any>(null);
78
+
79
+ // Handlers
80
+ const handleSearch = useCallback(
81
+ (value: string) => {
82
+ const params = new URLSearchParams(searchParams.toString());
83
+ if (value) params.set("search", value);
84
+ else params.delete("search");
85
+ router.push(`${pathname}?${params.toString()}`);
86
+ },
87
+ [pathname, router, searchParams],
88
+ );
89
+
90
+ const handleRoleFilter = useCallback(
91
+ (value: string) => {
92
+ const params = new URLSearchParams(searchParams.toString());
93
+ if (value && value !== "all") params.set("role", value);
94
+ else params.delete("role");
95
+ router.push(`${pathname}?${params.toString()}`);
96
+ },
97
+ [pathname, router, searchParams],
98
+ );
99
+
100
+ const handleUserTypeFilter = useCallback(
101
+ (value: string) => {
102
+ const params = new URLSearchParams(searchParams.toString());
103
+ if (value && value !== "all") params.set("type", value);
104
+ else params.delete("type");
105
+ router.push(`${pathname}?${params.toString()}`);
106
+ },
107
+ [pathname, router, searchParams],
108
+ );
109
+
110
+ const handleSelectUser = (user: any) => {
111
+ setSelectedUser(user);
112
+ setQuickViewOpen(true);
113
+ };
114
+
115
+ const handleCreateNew = () => {
116
+ setUserFormMode("create");
117
+ setUserFormData(null);
118
+ setUserFormOpen(true);
119
+ };
120
+
121
+ const handleEditUser = (user?: any) => {
122
+ const targetUser = user || selectedUser;
123
+ if (!targetUser) return;
124
+ setSelectedUser(targetUser);
125
+ setQuickViewOpen(true);
126
+ };
127
+
128
+ // Role Assignment
129
+ const handleAssignRoles = async (userId: string, roleCodes: string[]) => {
130
+ try {
131
+ if (onAssignRoles) {
132
+ await onAssignRoles(userId, roleCodes);
133
+ }
134
+ toast.success("Thành công", {
135
+ description: "Đã cập nhật vai trò người dùng",
136
+ });
137
+ router.refresh();
138
+ } catch (error) {
139
+ toast.error("Lỗi", {
140
+ description: "Không thể cập nhật vai trò",
141
+ });
142
+ }
143
+ };
144
+
145
+ // Reset Password
146
+ const handleResetPassword = async (userId: string, password: string) => {
147
+ try {
148
+ if (onResetPassword) {
149
+ await onResetPassword(userId, password);
150
+ }
151
+ toast.success("Thành công", {
152
+ description: "Đã đặt lại mật khẩu",
153
+ });
154
+ } catch (error) {
155
+ toast.error("Lỗi", {
156
+ description: "Không thể đặt lại mật khẩu",
157
+ });
158
+ }
159
+ };
160
+
161
+ // User Form Submit (Create/Edit)
162
+ const handleUserSubmit = async (data: any, id?: string) => {
163
+ const url = id ? `/api/users/${id}` : "/api/users";
164
+ const method = id ? "PUT" : "POST";
165
+
166
+ const res = await fetch(url, {
167
+ method,
168
+ headers: { "Content-Type": "application/json" },
169
+ body: JSON.stringify(data),
170
+ });
171
+
172
+ if (!res.ok) {
173
+ const resData = await res.json();
174
+ throw new Error(resData.error);
175
+ }
176
+
177
+ toast.success("Thành công", {
178
+ description: id ? "Đã cập nhật người dùng" : "Đã tạo người dùng mới",
179
+ });
180
+
181
+ router.refresh();
182
+ setUserFormOpen(false);
183
+ };
184
+
185
+ return (
186
+ <div className="flex flex-col gap-4 relative">
187
+ <UserStats stats={stats} />
188
+
189
+ <UserToolbar
190
+ viewMode={viewMode}
191
+ onViewModeChange={handleViewModeChange}
192
+ onCreateNew={handleCreateNew}
193
+ onSearchChange={handleSearch}
194
+ roles={roles}
195
+ onRoleChange={handleRoleFilter}
196
+ userType={searchParams.get("type") || "all"}
197
+ onUserTypeChange={handleUserTypeFilter}
198
+ permissions={permissions}
199
+ />
200
+
201
+ <div className="min-h-[400px]">
202
+ {viewMode === "table" ? (
203
+ <div className="border rounded-md">
204
+ <BasicUserTable
205
+ data={initialData}
206
+ onEdit={(u) => handleEditUser(u)}
207
+ />
208
+ </div>
209
+ ) : (
210
+ <UsersCardView data={initialData} onSelect={handleSelectUser} />
211
+ )}
212
+ </div>
213
+
214
+ {/* Create User Dialog */}
215
+ <UnifiedProfileDialog
216
+ open={userFormOpen}
217
+ onOpenChange={setUserFormOpen}
218
+ mode="create"
219
+ viewMode="admin"
220
+ roles={roles}
221
+ onSaveProfile={(data) => handleUserSubmit(data)}
222
+ />
223
+
224
+ {/* Quick View / Edit Dialog */}
225
+ {selectedUser && (
226
+ <UnifiedProfileDialog
227
+ open={quickViewOpen}
228
+ onOpenChange={setQuickViewOpen}
229
+ data={selectedUser}
230
+ mode="edit"
231
+ viewMode="admin"
232
+ roles={roles}
233
+ onSaveProfile={handleUserSubmit}
234
+ onSaveRoles={handleAssignRoles}
235
+ onSavePassword={handleResetPassword}
236
+ />
237
+ )}
238
+ </div>
239
+ );
240
+ }
241
+
242
+ // Simple Basic Table Component
243
+ function BasicUserTable({
244
+ data,
245
+ onEdit,
246
+ }: {
247
+ data: any[];
248
+ onEdit: (u: any) => void;
249
+ }) {
250
+ const [currentPage, setCurrentPage] = useState(1);
251
+ const pageSize = 10;
252
+
253
+ if (!data.length) return <div className="p-4 text-center">No data</div>;
254
+
255
+ const totalPages = Math.ceil(data.length / pageSize);
256
+ const paginatedData = data.slice((currentPage - 1) * pageSize, currentPage * pageSize);
257
+
258
+ return (
259
+ <div className="flex flex-col gap-4">
260
+ <div className="bg-background">
261
+ <Table>
262
+ <TableHeader>
263
+ <TableRow className="text-sm border-b">
264
+ <TableHead className="w-[50px] font-semibold text-foreground text-center h-10">STT</TableHead>
265
+ <TableHead className="w-[20%] min-w-[150px] font-semibold text-foreground h-10">Người dùng</TableHead>
266
+ <TableHead className="w-[20%] min-w-[150px] font-semibold text-foreground h-10">Liên hệ</TableHead>
267
+ <TableHead className="w-[15%] min-w-[120px] font-semibold text-foreground h-10">Trạng thái</TableHead>
268
+ <TableHead className="w-[15%] min-w-[120px] font-semibold text-foreground h-10">Phòng ban</TableHead>
269
+ <TableHead className="w-[20%] min-w-[150px] font-semibold text-foreground h-10">Vai trò</TableHead>
270
+ <TableHead className="w-[50px] text-center h-10"></TableHead>
271
+ </TableRow>
272
+ </TableHeader>
273
+ <TableBody>
274
+ {paginatedData.map((user, index) => (
275
+ <TableRow key={user.id} className="border-b group">
276
+ {/* STT */}
277
+ <TableCell className="py-3 text-center text-muted-foreground font-medium text-xs">
278
+ {(currentPage - 1) * pageSize + index + 1}
279
+ </TableCell>
280
+
281
+ {/* User Info */}
282
+ <TableCell className="py-3">
283
+ <div className="flex flex-col">
284
+ <div className="flex items-center gap-2">
285
+ <span className="font-semibold text-sm text-foreground">{user.name}</span>
286
+ {user.userType === "customer" && <span className="text-xs text-foreground bg-muted border px-2.5 py-0.5 rounded-full font-semibold whitespace-nowrap">Khách hàng</span>}
287
+ {user.userType === "supplier" && <span className="text-xs text-background bg-foreground px-2.5 py-0.5 rounded-full font-semibold whitespace-nowrap">Nhà cung cấp</span>}
288
+ {(!user.userType || user.userType === "employee") && <span className="text-xs text-foreground bg-muted border px-2.5 py-0.5 rounded-full font-semibold whitespace-nowrap">Nhân viên</span>}
289
+ </div>
290
+ </div>
291
+ </TableCell>
292
+
293
+ {/* Contact */}
294
+ <TableCell className="py-3">
295
+ <div className="flex flex-col">
296
+ <span className="text-sm text-foreground">{user.email}</span>
297
+ {user.phone && <span className="text-sm text-muted-foreground">{user.phone}</span>}
298
+ </div>
299
+ </TableCell>
300
+
301
+ {/* Status */}
302
+ <TableCell className="py-3">
303
+ <div className="flex items-center gap-1.5">
304
+ <span className={`inline-flex items-center text-xs font-semibold px-2.5 py-1 rounded-full whitespace-nowrap ${
305
+ user.isActive || user.status === "active"
306
+ ? "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400"
307
+ : "bg-muted text-muted-foreground"
308
+ }`}>
309
+ {user.isActive || user.status === "active" ? "Hoạt động" : "Đã khóa"}
310
+ </span>
311
+ </div>
312
+ </TableCell>
313
+
314
+ {/* Department */}
315
+ <TableCell className="py-3 text-sm text-foreground">
316
+ {user.departmentName || "—"}
317
+ </TableCell>
318
+
319
+ {/* Roles */}
320
+ <TableCell className="py-3">
321
+ <div className="flex flex-wrap gap-1.5">
322
+ {user.roleNames?.map((r: string, i: number) => (
323
+ <span
324
+ key={i}
325
+ className="inline-flex items-center bg-muted text-foreground border font-semibold text-xs px-2.5 py-1 rounded-full whitespace-nowrap"
326
+ >
327
+ {r}
328
+ </span>
329
+ ))}
330
+ </div>
331
+ </TableCell>
332
+
333
+ {/* Actions */}
334
+ <TableCell className="py-2.5 text-right">
335
+ <Button
336
+ variant="ghost"
337
+ size="icon"
338
+ onClick={(e: React.MouseEvent) => {
339
+ e.stopPropagation();
340
+ onEdit(user);
341
+ }}
342
+ >
343
+ <Edit2 className="h-4 w-4" />
344
+ </Button>
345
+ </TableCell>
346
+ </TableRow>
347
+ ))}
348
+ </TableBody>
349
+ </Table>
350
+ </div>
351
+
352
+ {/* Pagination */}
353
+ {totalPages > 1 && (
354
+ <div className="flex items-center justify-between px-2 pt-2">
355
+ <p className="text-sm text-muted-foreground">
356
+ Hiển thị từ {(currentPage - 1) * pageSize + 1} đến {Math.min(currentPage * pageSize, data.length)} trong tổng số {data.length}
357
+ </p>
358
+ <div className="flex items-center gap-2">
359
+ <Button
360
+ variant="outline"
361
+ size="sm"
362
+ onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
363
+ disabled={currentPage === 1}
364
+ className="h-8 rounded-full"
365
+ >
366
+ Trang trước
367
+ </Button>
368
+ <div className="text-sm font-semibold text-foreground px-2">
369
+ Trang {currentPage} / {totalPages}
370
+ </div>
371
+ <Button
372
+ variant="outline"
373
+ size="sm"
374
+ onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}
375
+ disabled={currentPage === totalPages}
376
+ className="h-8 rounded-full"
377
+ >
378
+ Trang sau
379
+ </Button>
380
+ </div>
381
+ </div>
382
+ )}
383
+ </div>
384
+ );
385
+ }
@@ -0,0 +1,19 @@
1
+ import type { UserType } from "./types";
2
+ import type { DictionaryType } from "../hooks";
3
+
4
+ import { DangerousZone } from "./components/dangerous-zone";
5
+ import { ProfileInfo } from "./components/profile-info";
6
+
7
+ export interface ProfilePageProps {
8
+ user: UserType;
9
+ dictionary?: DictionaryType;
10
+ }
11
+
12
+ export function ProfilePage({ user, dictionary }: ProfilePageProps) {
13
+ return (
14
+ <div className="grid gap-4">
15
+ <ProfileInfo user={user} dictionary={dictionary} />
16
+ <DangerousZone user={user} dictionary={dictionary} />
17
+ </div>
18
+ );
19
+ }
@@ -0,0 +1,68 @@
1
+ import { z } from "zod";
2
+
3
+ import { formatFileSize } from "../utils";
4
+
5
+ export const MAX_AVATAR_SIZE = 50000000; // 50 MB
6
+ export const fomratedAvatarSize = formatFileSize(MAX_AVATAR_SIZE);
7
+
8
+ export const ProfileInfoSchema = z.object({
9
+ firstName: z
10
+ .string()
11
+ .trim()
12
+ .min(2, { message: "First Name must contain at least 2 characters." })
13
+ .max(50, { message: "First Name must contain at most 50 characters." }),
14
+ lastName: z
15
+ .string()
16
+ .trim()
17
+ .min(2, { message: "Last Name must contain at least 2 characters." })
18
+ .max(50, { message: "Last Name must contain at most 50 characters." }),
19
+ username: z
20
+ .string()
21
+ .toLowerCase()
22
+ .trim()
23
+ .min(3, { message: "Username must contain at least 3 characters." })
24
+ .max(50, { message: "Username must contain at most 50 characters." }),
25
+ email: z
26
+ .string()
27
+ .email({ message: "Invalid email address" })
28
+ .toLowerCase()
29
+ .trim(),
30
+ phoneNumber: z
31
+ .string()
32
+ .min(10, { message: "Phone Number must contain at least 10 digits." })
33
+ .max(15, { message: "Username must contain at most 15 digits." }),
34
+ state: z
35
+ .string()
36
+ .trim()
37
+ .min(2, { message: "State must contain at least 2 characters." })
38
+ .max(50, { message: "State must contain at most 50 characters." }),
39
+ country: z
40
+ .string()
41
+ .trim()
42
+ .min(2, { message: "Country must contain at least 2 characters." })
43
+ .max(56, { message: "Country must contain at most 56 characters." }),
44
+ address: z
45
+ .string()
46
+ .trim()
47
+ .min(2, { message: "Address must contain at least 2 characters." })
48
+ .max(100, { message: "Address must contain at most 100 characters." }),
49
+ zipCode: z
50
+ .string()
51
+ .min(5, { message: "Zip Code must contain at least 5 digits." })
52
+ .max(10, { message: "Zip Code must contain at most 10 characters." }),
53
+ language: z.string(),
54
+ timeZone: z.string(),
55
+ currency: z.string(),
56
+ organization: z.string().trim().optional(),
57
+ avatar: z
58
+ .instanceof(File)
59
+ .refine((avatar) => avatar.size <= MAX_AVATAR_SIZE, {
60
+ message: `Avatar must be ${fomratedAvatarSize} or less.`,
61
+ })
62
+ // .refine((avatar) => avatar.type.startsWith("image/"), {
63
+ // message: "The file must be an image",
64
+ // })
65
+ .optional(),
66
+ });
67
+
68
+ export const DeleteAccountSchema = z.object({});
@@ -0,0 +1,34 @@
1
+ import type { z } from "zod";
2
+ import type { DeleteAccountSchema, ProfileInfoSchema } from "./schemas";
3
+
4
+
5
+ export interface UserType {
6
+ id: string
7
+ firstName: string
8
+ lastName: string
9
+ name: string
10
+ username: string
11
+ role: string
12
+ avatar: string
13
+ background: string
14
+ status: string
15
+ phoneNumber: string
16
+ email: string
17
+ state: string
18
+ country: string
19
+ address: string
20
+ zipCode: string
21
+ language: string
22
+ timeZone: string
23
+ currency: string
24
+ organization: string
25
+ twoFactorAuth: boolean
26
+ loginAlerts: boolean
27
+ accountReoveryOption?: "email" | "sms" | "codes"
28
+ connections: number
29
+ followers: number
30
+ }
31
+
32
+ export type DeleteAccountFormType = z.infer<typeof DeleteAccountSchema>
33
+
34
+ export type ProfileInfoFormType = z.infer<typeof ProfileInfoSchema>