@goplusvn/core 0.1.0 → 0.1.1

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 (369) hide show
  1. package/package.json +2 -1
  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
@@ -0,0 +1,120 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ STATUS_ACTIVE,
5
+ STATUS_INACTIVE,
6
+ STATUS_VALUES,
7
+ booleanToStatus,
8
+ } from "../configs";
9
+
10
+ /**
11
+ * Supplier Validation Schema
12
+ *
13
+ * Rules:
14
+ * - code: Required, max 50 chars
15
+ * - name: Required, max 200 chars
16
+ * - taxCode: Required, 10-13 digits
17
+ * - email: Optional but must be valid if provided
18
+ * - phone: Optional, 10 digits if provided
19
+ * - address: Optional, max 500 chars
20
+ * - description: Optional, max 1000 chars
21
+ * - status: Enum (active/inactive)
22
+ */
23
+
24
+ const supplierBaseSchema = z.object({
25
+ code: z
26
+ .string()
27
+ .min(1, "Mã nhà cung cấp là bắt buộc")
28
+ .max(50, "Mã nhà cung cấp tối đa 50 ký tự")
29
+ .trim(),
30
+
31
+ name: z
32
+ .string()
33
+ .min(1, "Tên nhà cung cấp là bắt buộc")
34
+ .max(200, "Tên nhà cung cấp tối đa 200 ký tự")
35
+ .trim(),
36
+
37
+ taxCode: z
38
+ .string()
39
+ .min(1, "Mã số thuế là bắt buộc")
40
+ .regex(/^[0-9]{10,13}$/, "Mã số thuế phải là 10-13 chữ số"),
41
+
42
+ email: z.string().email("Email không hợp lệ").optional().or(z.literal("")),
43
+
44
+ phone: z
45
+ .string()
46
+ .regex(/^[0-9]{10}$/, "Số điện thoại phải là 10 chữ số")
47
+ .optional()
48
+ .or(z.literal("")),
49
+
50
+ address: z
51
+ .string()
52
+ .max(500, "Địa chỉ tối đa 500 ký tự")
53
+ .optional()
54
+ .or(z.literal(""))
55
+ .transform((val) => val || ""),
56
+
57
+ description: z
58
+ .string()
59
+ .max(1000, "Mô tả tối đa 1000 ký tự")
60
+ .optional()
61
+ .or(z.literal(""))
62
+ .transform((val) => val || ""),
63
+
64
+ status: z.preprocess((val) => {
65
+ // Chuyển đổi boolean thành string
66
+ if (typeof val === "boolean") {
67
+ return booleanToStatus(val);
68
+ }
69
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
70
+ if (val === "Active" || val === "Inactive") {
71
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
72
+ }
73
+ return val;
74
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
75
+
76
+ contractStartDate: z
77
+ .string()
78
+ .optional()
79
+ .transform((val) => (val ? new Date(val) : null)) // Convert string to Date or null
80
+ .or(z.date().optional())
81
+ .nullable(),
82
+
83
+ contractEndDate: z
84
+ .string()
85
+ .optional()
86
+ .transform((val) => (val ? new Date(val) : null)) // Convert string to Date or null
87
+ .or(z.date().optional())
88
+ .nullable(),
89
+ });
90
+
91
+ export const supplierSchema = supplierBaseSchema.refine(
92
+ (data) => {
93
+ if (data.contractStartDate && data.contractEndDate) {
94
+ return data.contractEndDate >= data.contractStartDate;
95
+ }
96
+ return true;
97
+ },
98
+ {
99
+ message: "Ngày kết thúc hợp đồng phải sau ngày bắt đầu",
100
+ path: ["contractEndDate"],
101
+ },
102
+ );
103
+
104
+ /**
105
+ * Type inference from schema
106
+ */
107
+ export type SupplierInput = z.infer<typeof supplierSchema>;
108
+
109
+ /**
110
+ * Partial schema for updates (all fields optional)
111
+ */
112
+ export const supplierUpdateSchema = supplierBaseSchema.partial();
113
+
114
+ /**
115
+ * Schema for bulk operations
116
+ */
117
+ export const supplierBulkSchema = z.object({
118
+ ids: z.array(z.string()).min(1, "Phải chọn ít nhất 1 nhà cung cấp"),
119
+ action: z.enum(["delete", "activate", "deactivate"]),
120
+ });
@@ -0,0 +1,67 @@
1
+ import { z } from "zod";
2
+
3
+ import { STATUS_ACTIVE, STATUS_INACTIVE, STATUS_VALUES } from "../configs";
4
+
5
+ /**
6
+ * System Category Group Validation Schema
7
+ *
8
+ * Rules:
9
+ * - code: Required, max 50 chars
10
+ * - name: Required, max 200 chars
11
+ * - description: Optional, max 1000 chars
12
+ * - status: Enum (active/inactive)
13
+ */
14
+
15
+ export const systemCategoryGroupSchema = z.object({
16
+ code: z
17
+ .string()
18
+ .min(1, "Mã nhóm danh mục là bắt buộc")
19
+ .max(50, "Mã nhóm danh mục tối đa 50 ký tự")
20
+ .trim(),
21
+
22
+ name: z
23
+ .string()
24
+ .min(1, "Tên nhóm danh mục là bắt buộc")
25
+ .max(200, "Tên nhóm danh mục tối đa 200 ký tự")
26
+ .trim(),
27
+
28
+ description: z
29
+ .string()
30
+ .max(1000, "Mô tả tối đa 1000 ký tự")
31
+ .optional()
32
+ .or(z.literal(""))
33
+ .transform((val) => val || ""),
34
+
35
+ status: z.preprocess((val) => {
36
+ // Hỗ trợ boolean từ switch field (true -> active, false -> inactive)
37
+ if (typeof val === "boolean") {
38
+ return val ? STATUS_ACTIVE : STATUS_INACTIVE;
39
+ }
40
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
41
+ if (val === "Active" || val === "Inactive") {
42
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
43
+ }
44
+ return val;
45
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
46
+ });
47
+
48
+ /**
49
+ * Type inference from schema
50
+ */
51
+ export type SystemCategoryGroupInput = z.infer<
52
+ typeof systemCategoryGroupSchema
53
+ >;
54
+
55
+ /**
56
+ * Partial schema for updates (all fields optional)
57
+ */
58
+ export const systemCategoryGroupUpdateSchema =
59
+ systemCategoryGroupSchema.partial();
60
+
61
+ /**
62
+ * Schema for bulk operations
63
+ */
64
+ export const systemCategoryGroupBulkSchema = z.object({
65
+ ids: z.array(z.string()).min(1, "Phải chọn ít nhất 1 nhóm danh mục"),
66
+ action: z.enum(["delete", "activate", "deactivate"]),
67
+ });
@@ -0,0 +1,77 @@
1
+ import { z } from "zod";
2
+
3
+ import { STATUS_ACTIVE, STATUS_INACTIVE, STATUS_VALUES } from "../configs";
4
+
5
+ /**
6
+ * System Category Validation Schema
7
+ *
8
+ * Rules:
9
+ * - code: Required, max 50 chars
10
+ * - name: Required, max 200 chars
11
+ * - groupCode: Required, max 50 chars
12
+ * - description: Optional, max 1000 chars
13
+ * - status: Enum (active/inactive)
14
+ * - order: Optional, integer >= 0
15
+ */
16
+
17
+ export const systemCategorySchema = z.object({
18
+ code: z
19
+ .string()
20
+ .min(1, "Mã danh mục là bắt buộc")
21
+ .max(50, "Mã danh mục tối đa 50 ký tự")
22
+ .trim(),
23
+
24
+ name: z
25
+ .string()
26
+ .min(1, "Tên danh mục là bắt buộc")
27
+ .max(200, "Tên danh mục tối đa 200 ký tự")
28
+ .trim(),
29
+
30
+ groupCode: z
31
+ .string()
32
+ .min(1, "Mã nhóm danh mục là bắt buộc")
33
+ .max(50, "Mã nhóm danh mục tối đa 50 ký tự"),
34
+
35
+ description: z
36
+ .string()
37
+ .max(1000, "Mô tả tối đa 1000 ký tự")
38
+ .optional()
39
+ .or(z.literal(""))
40
+ .transform((val) => val || ""),
41
+
42
+ status: z.preprocess((val) => {
43
+ // Hỗ trợ boolean từ switch field (true -> active, false -> inactive)
44
+ if (typeof val === "boolean") {
45
+ return val ? STATUS_ACTIVE : STATUS_INACTIVE;
46
+ }
47
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
48
+ if (val === "Active" || val === "Inactive") {
49
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
50
+ }
51
+ return val;
52
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
53
+
54
+ order: z
55
+ .number()
56
+ .int("Thứ tự phải là số nguyên")
57
+ .min(0, "Thứ tự phải >= 0")
58
+ .optional(),
59
+ });
60
+
61
+ /**
62
+ * Type inference from schema
63
+ */
64
+ export type SystemCategoryInput = z.infer<typeof systemCategorySchema>;
65
+
66
+ /**
67
+ * Partial schema for updates (all fields optional)
68
+ */
69
+ export const systemCategoryUpdateSchema = systemCategorySchema.partial();
70
+
71
+ /**
72
+ * Schema for bulk operations
73
+ */
74
+ export const systemCategoryBulkSchema = z.object({
75
+ ids: z.array(z.string()).min(1, "Phải chọn ít nhất 1 danh mục"),
76
+ action: z.enum(["delete", "activate", "deactivate"]),
77
+ });
@@ -0,0 +1,118 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ STATUS_ACTIVE,
5
+ STATUS_INACTIVE,
6
+ STATUS_VALUES,
7
+ booleanToStatus,
8
+ } from "../configs";
9
+
10
+ /**
11
+ * SystemConfig Validation Schema
12
+ *
13
+ * Rules:
14
+ * - key: Required, unique, max 100 chars
15
+ * - value: Required, max 5000 chars
16
+ * - type: Optional, default "string", max 50 chars
17
+ * - category: Optional, default "general", max 100 chars
18
+ * - description: Optional, max 1000 chars
19
+ * - isEncrypted: Optional, default false
20
+ * - isReadOnly: Optional, default false
21
+ * - status: Enum (active/inactive), default "active"
22
+ */
23
+
24
+ export const systemConfigSchema = z.object({
25
+ key: z
26
+ .string()
27
+ .min(1, "Key là bắt buộc")
28
+ .max(100, "Key tối đa 100 ký tự")
29
+ .trim()
30
+ .regex(
31
+ /^[a-zA-Z0-9._-]+$/,
32
+ "Key chỉ được chứa chữ cái, số, dấu chấm, gạch dưới và gạch ngang",
33
+ ),
34
+
35
+ value: z
36
+ .string()
37
+ .min(1, "Value là bắt buộc")
38
+ .max(5000, "Value tối đa 5000 ký tự")
39
+ .trim(),
40
+
41
+ type: z
42
+ .string()
43
+ .max(50, "Type tối đa 50 ký tự")
44
+ .default("string")
45
+ .optional()
46
+ .or(z.literal(""))
47
+ .transform((val) => val || "string"),
48
+
49
+ category: z
50
+ .string()
51
+ .max(100, "Category tối đa 100 ký tự")
52
+ .default("general")
53
+ .optional()
54
+ .or(z.literal(""))
55
+ .transform((val) => val || "general"),
56
+
57
+ description: z
58
+ .string()
59
+ .max(1000, "Mô tả tối đa 1000 ký tự")
60
+ .optional()
61
+ .or(z.literal(""))
62
+ .transform((val) => val || undefined),
63
+
64
+ isEncrypted: z.boolean().default(false).optional(),
65
+
66
+ isReadOnly: z.boolean().default(false).optional(),
67
+
68
+ status: z.preprocess((val) => {
69
+ // Chuyển đổi boolean thành string
70
+ if (typeof val === "boolean") {
71
+ return booleanToStatus(val);
72
+ }
73
+ // Nếu là string hợp lệ, giữ nguyên (hỗ trợ cả Active/Inactive cũ)
74
+ if (
75
+ val === STATUS_ACTIVE ||
76
+ val === STATUS_INACTIVE ||
77
+ val === "Active" ||
78
+ val === "Inactive"
79
+ ) {
80
+ return val === "Active"
81
+ ? STATUS_ACTIVE
82
+ : val === "Inactive"
83
+ ? STATUS_INACTIVE
84
+ : val;
85
+ }
86
+ // Mặc định là 'active'
87
+ return STATUS_ACTIVE;
88
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
89
+ });
90
+
91
+ /**
92
+ * Type inference from schema
93
+ */
94
+ export type SystemConfigInput = z.infer<typeof systemConfigSchema>;
95
+
96
+ /**
97
+ * Partial schema for updates (all fields optional except key)
98
+ */
99
+ export const systemConfigUpdateSchema = systemConfigSchema.partial().extend({
100
+ key: z
101
+ .string()
102
+ .min(1, "Key là bắt buộc")
103
+ .max(100, "Key tối đa 100 ký tự")
104
+ .trim()
105
+ .regex(
106
+ /^[a-zA-Z0-9._-]+$/,
107
+ "Key chỉ được chứa chữ cái, số, dấu chấm, gạch dưới và gạch ngang",
108
+ )
109
+ .optional(),
110
+ });
111
+
112
+ /**
113
+ * Schema for bulk operations
114
+ */
115
+ export const systemConfigBulkSchema = z.object({
116
+ ids: z.array(z.string()).min(1, "Phải chọn ít nhất 1 cấu hình"),
117
+ action: z.enum(["delete", "activate", "deactivate"]),
118
+ });
@@ -0,0 +1,75 @@
1
+ import { z } from "zod";
2
+
3
+ import { STATUS_ACTIVE, STATUS_INACTIVE, STATUS_VALUES } from "../configs";
4
+
5
+ /**
6
+ * Unit of Measure (UOM) Validation Schema
7
+ */
8
+
9
+ // Base schema without refine for partial updates
10
+ const uomBaseSchema = z.object({
11
+ code: z
12
+ .string()
13
+ .min(1, "Mã đơn vị tính là bắt buộc")
14
+ .max(50, "Mã đơn vị tính tối đa 50 ký tự")
15
+ .trim(),
16
+
17
+ name: z
18
+ .string()
19
+ .min(1, "Tên đơn vị tính là bắt buộc")
20
+ .max(100, "Tên đơn vị tính tối đa 100 ký tự")
21
+ .trim(),
22
+
23
+ description: z
24
+ .string()
25
+ .max(500, "Mô tả tối đa 500 ký tự")
26
+ .optional()
27
+ .or(z.literal(""))
28
+ .transform((val) => val || ""),
29
+
30
+ status: z.preprocess((val) => {
31
+ // Hỗ trợ boolean từ switch field (true -> active, false -> inactive)
32
+ if (typeof val === "boolean") {
33
+ return val ? STATUS_ACTIVE : STATUS_INACTIVE;
34
+ }
35
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
36
+ if (val === "Active" || val === "Inactive") {
37
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
38
+ }
39
+ return val;
40
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
41
+
42
+ baseUomCode: z.preprocess((val) => {
43
+ // Chuyển đổi string rỗng thành null
44
+ if (val === "" || val === null || val === undefined) {
45
+ return null;
46
+ }
47
+ return val;
48
+ }, z.string().max(20, "Mã đơn vị quy đổi tối đa 20 ký tự").nullable().optional()),
49
+
50
+ conversionRate: z.preprocess(
51
+ (val) => {
52
+ // Chuyển đổi string rỗng hoặc string number thành number hoặc null
53
+ if (val === "" || val === null || val === undefined) {
54
+ return null;
55
+ }
56
+ // Nếu là string, thử parse thành number
57
+ if (typeof val === "string") {
58
+ const parsed = parseFloat(val);
59
+ return isNaN(parsed) ? null : parsed;
60
+ }
61
+ // Nếu đã là number, giữ nguyên
62
+ return val;
63
+ },
64
+ z
65
+ .union([z.number().positive("Tỷ lệ quy đổi phải lớn hơn 0"), z.null()])
66
+ .optional(),
67
+ ),
68
+ });
69
+
70
+ // Apply refine to the full schema
71
+ // Export the base schema directly
72
+ export const uomSchema = uomBaseSchema;
73
+
74
+ export type UomInput = z.infer<typeof uomSchema>;
75
+ export const uomUpdateSchema = uomBaseSchema.partial();
@@ -0,0 +1,179 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ STATUS_ACTIVE,
5
+ STATUS_INACTIVE,
6
+ STATUS_VALUES,
7
+ booleanToStatus,
8
+ } from "../configs";
9
+
10
+ /**
11
+ * UserSupplier Validation Schema
12
+ *
13
+ * Rules:
14
+ * - userId: Required, must be valid UUID (hệ thống dùng UUID)
15
+ * - supplierId: Required, must be valid UUID (hệ thống dùng UUID)
16
+ * - status: Enum (active/inactive), default active
17
+ * - startDate: Required, must be valid date
18
+ * - endDate: Optional, must be valid date, must be after startDate if provided
19
+ * - role: Optional, max 100 chars
20
+ *
21
+ * Note:
22
+ * - Hệ thống dùng UUID (crypto.randomUUID()) - đây là chuẩn
23
+ * - Tạm thời chấp nhận cả CUID để tương thích với dữ liệu seed cũ
24
+ * - TODO: Migrate dữ liệu seed cũ từ CUID sang UUID và remove CUID support
25
+ */
26
+
27
+ /**
28
+ * Validate CUID format (tạm thời cho dữ liệu seed cũ)
29
+ * CUID format: starts with 'c', followed by 20-30 alphanumeric characters
30
+ * Example: cmgf9g6ck000yju0yoa07wfzl
31
+ * TODO: Remove sau khi migrate dữ liệu seed
32
+ */
33
+ const cuidRegex = /^c[a-z0-9]{20,30}$/;
34
+
35
+ /**
36
+ * Validate UUID format (chuẩn hệ thống)
37
+ * UUID format: 8-4-4-4-12 hexadecimal digits with hyphens
38
+ * Example: 550e8400-e29b-41d4-a716-446655440000
39
+ */
40
+ const uuidRegex =
41
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
42
+
43
+ /**
44
+ * Custom validation for CUID or UUID
45
+ * TODO: Chỉ validate UUID sau khi migrate dữ liệu seed cũ
46
+ */
47
+ const cuidOrUuid = z
48
+ .string()
49
+ .refine((val) => cuidRegex.test(val) || uuidRegex.test(val), {
50
+ message:
51
+ "ID không hợp lệ (phải là UUID, tạm thời chấp nhận CUID cho dữ liệu cũ)",
52
+ });
53
+
54
+ // Base schema object (before refine) - needed for .partial()
55
+ const userSupplierBaseSchema = z.object({
56
+ userId: z.preprocess(
57
+ (val) => {
58
+ // Convert to string and handle empty values
59
+ if (val === null || val === undefined || val === "") {
60
+ return undefined;
61
+ }
62
+ return String(val).trim();
63
+ },
64
+ z
65
+ .string({
66
+ required_error: "Người dùng là bắt buộc",
67
+ })
68
+ .min(1, "Người dùng là bắt buộc")
69
+ .pipe(cuidOrUuid),
70
+ ),
71
+
72
+ supplierId: z.preprocess(
73
+ (val) => {
74
+ // Convert to string and handle empty values
75
+ if (val === null || val === undefined || val === "") {
76
+ return undefined;
77
+ }
78
+ return String(val).trim();
79
+ },
80
+ z
81
+ .string({
82
+ required_error: "Nhà cung cấp là bắt buộc",
83
+ })
84
+ .min(1, "Nhà cung cấp là bắt buộc")
85
+ .pipe(cuidOrUuid),
86
+ ),
87
+
88
+ status: z.preprocess((val) => {
89
+ // Chuyển đổi boolean thành string
90
+ if (typeof val === "boolean") {
91
+ return booleanToStatus(val);
92
+ }
93
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
94
+ if (val === "Active" || val === "Inactive") {
95
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
96
+ }
97
+ return val;
98
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
99
+
100
+ startDate: z
101
+ .string()
102
+ .optional()
103
+ .transform((val) => {
104
+ if (!val) return new Date(); // Default to now if not provided
105
+ const date = new Date(val);
106
+ if (isNaN(date.getTime())) {
107
+ throw new Error("Ngày bắt đầu không hợp lệ");
108
+ }
109
+ return date;
110
+ })
111
+ .or(z.date().default(() => new Date())),
112
+
113
+ endDate: z
114
+ .string()
115
+ .optional()
116
+ .transform((val) => {
117
+ if (!val) return undefined;
118
+ const date = new Date(val);
119
+ if (isNaN(date.getTime())) {
120
+ throw new Error("Ngày kết thúc không hợp lệ");
121
+ }
122
+ return date;
123
+ })
124
+ .or(z.date().optional())
125
+ .nullable(),
126
+
127
+ role: z
128
+ .string()
129
+ .max(100, "Vai trò tối đa 100 ký tự")
130
+ .optional()
131
+ .or(z.literal(""))
132
+ .transform((val) => val || undefined),
133
+ });
134
+
135
+ // Main schema with refine for validation
136
+ export const userSupplierSchema = userSupplierBaseSchema.refine(
137
+ (data) => {
138
+ // Nếu có endDate, phải sau startDate
139
+ if (data.endDate && data.startDate) {
140
+ return data.endDate >= data.startDate;
141
+ }
142
+ return true;
143
+ },
144
+ {
145
+ message: "Ngày kết thúc phải sau ngày bắt đầu",
146
+ path: ["endDate"],
147
+ },
148
+ );
149
+
150
+ /**
151
+ * Type inference from schema
152
+ */
153
+ export type UserSupplierInput = z.infer<typeof userSupplierSchema>;
154
+
155
+ /**
156
+ * Partial schema for updates (all fields optional)
157
+ * Create from base schema before refine to allow .partial()
158
+ */
159
+ export const userSupplierUpdateSchema = userSupplierBaseSchema.partial().refine(
160
+ (data) => {
161
+ // Nếu có endDate và startDate, phải sau startDate
162
+ if (data.endDate && data.startDate) {
163
+ return data.endDate >= data.startDate;
164
+ }
165
+ return true;
166
+ },
167
+ {
168
+ message: "Ngày kết thúc phải sau ngày bắt đầu",
169
+ path: ["endDate"],
170
+ },
171
+ );
172
+
173
+ /**
174
+ * Schema for bulk operations
175
+ */
176
+ export const userSupplierBulkSchema = z.object({
177
+ ids: z.array(z.string()).min(1, "Phải chọn ít nhất 1 bản ghi"),
178
+ action: z.enum(["delete", "activate", "deactivate"]),
179
+ });
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+
3
+ export const userSchema = z.object({
4
+ name: z.string().min(1, "Tên hiển thị là bắt buộc"),
5
+ email: z.string().email("Email không hợp lệ"),
6
+ // Support both boolean and status string, normalize to boolean
7
+ isActive: z.preprocess((val) => {
8
+ if (typeof val === "boolean") return val;
9
+ if (val === "active") return true;
10
+ if (val === "inactive") return false;
11
+ return true; // default
12
+ }, z.boolean().default(true)),
13
+ // Also accept status string from form
14
+ status: z.enum(["active", "inactive"]).optional(),
15
+ image: z.string().optional().nullable(),
16
+ });
17
+
18
+ export type UserFormValues = z.infer<typeof userSchema>;
@@ -0,0 +1,9 @@
1
+ import { z } from "zod";
2
+
3
+ export const VerifyEmailSchema = z.object({
4
+ email: z
5
+ .string()
6
+ .email({ message: "Invalid email address" })
7
+ .toLowerCase()
8
+ .trim(),
9
+ });