@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,43 @@
1
+ import { z } from "zod";
2
+
3
+ import { STATUS_ACTIVE, STATUS_INACTIVE, STATUS_VALUES } from "../configs";
4
+
5
+ /**
6
+ * Material Category Validation Schema
7
+ */
8
+
9
+ export const materialCategorySchema = z.object({
10
+ code: z
11
+ .string()
12
+ .min(1, "Mã danh mục là bắt buộc")
13
+ .max(50, "Mã danh mục tối đa 50 ký tự")
14
+ .trim(),
15
+
16
+ name: z
17
+ .string()
18
+ .min(1, "Tên danh mục là bắt buộc")
19
+ .max(200, "Tên danh mục tối đa 200 ký tự")
20
+ .trim(),
21
+
22
+ description: z
23
+ .string()
24
+ .max(1000, "Mô tả tối đa 1000 ký tự")
25
+ .optional()
26
+ .or(z.literal(""))
27
+ .transform((val) => val || ""),
28
+
29
+ status: z.preprocess((val) => {
30
+ // Hỗ trợ boolean từ switch field (true -> active, false -> inactive)
31
+ if (typeof val === "boolean") {
32
+ return val ? STATUS_ACTIVE : STATUS_INACTIVE;
33
+ }
34
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
35
+ if (val === "Active" || val === "Inactive") {
36
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
37
+ }
38
+ return val;
39
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
40
+ });
41
+
42
+ export type MaterialCategoryInput = z.infer<typeof materialCategorySchema>;
43
+ export const materialCategoryUpdateSchema = materialCategorySchema.partial();
@@ -0,0 +1,74 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Material Pricing Validation Schema
5
+ *
6
+ * Rules:
7
+ * - supplierId: Required
8
+ * - materialId: Required
9
+ * - price: Required, > 0
10
+ * - effectiveDate: Required, valid date
11
+ * - applicableWarehouseIds: Optional, array of warehouse IDs
12
+ * - status: Optional, enum (pending/approved/rejected)
13
+ */
14
+
15
+ export const materialPricingSchema = z.object({
16
+ supplierId: z.string().min(1, "Nhà cung cấp là bắt buộc"),
17
+
18
+ materialId: z.string().min(1, "Nguyên vật liệu là bắt buộc"),
19
+
20
+ price: z
21
+ .number()
22
+ .positive("Giá phải lớn hơn 0")
23
+ .min(0.01, "Giá tối thiểu là 0.01"),
24
+
25
+ effectiveDate: z
26
+ .string()
27
+ .min(1, "Ngày hiệu lực là bắt buộc")
28
+ .refine((val) => {
29
+ const date = new Date(val);
30
+ return !isNaN(date.getTime());
31
+ }, "Ngày hiệu lực không hợp lệ"),
32
+
33
+ applicableWarehouseIds: z.array(z.string()).optional().default([]),
34
+
35
+ status: z
36
+ .enum(["pending", "approved", "rejected"])
37
+ .optional()
38
+ .default("pending"),
39
+ });
40
+
41
+ /**
42
+ * Type inference from schema
43
+ */
44
+ export type MaterialPricingInput = z.infer<typeof materialPricingSchema>;
45
+
46
+ /**
47
+ * Partial schema for updates (all fields optional)
48
+ */
49
+ export const materialPricingUpdateSchema = materialPricingSchema.partial();
50
+
51
+ /**
52
+ * Schema for set default supplier
53
+ */
54
+ export const setDefaultSupplierSchema = z.object({
55
+ materialId: z.string().min(1, "Nguyên vật liệu là bắt buộc"),
56
+ supplierId: z.string().min(1, "Nhà cung cấp là bắt buộc"),
57
+ });
58
+
59
+ /**
60
+ * Schema for approval
61
+ */
62
+ export const approvalSchema = z.object({
63
+ id: z.string().min(1, "ID là bắt buộc"),
64
+ action: z.enum(["approve", "reject"]),
65
+ notes: z.string().optional(),
66
+ effectiveDate: z
67
+ .string()
68
+ .optional()
69
+ .refine((val) => {
70
+ if (!val) return true; // Optional
71
+ const date = new Date(val);
72
+ return !isNaN(date.getTime());
73
+ }, "Ngày hiệu lực không hợp lệ"),
74
+ });
@@ -0,0 +1,76 @@
1
+ import { z } from "zod";
2
+
3
+ import { STATUS_ACTIVE, STATUS_INACTIVE, STATUS_VALUES } from "../configs";
4
+
5
+ /**
6
+ * Material Validation Schema
7
+ *
8
+ * Rules:
9
+ * - code: Required, max 50 chars
10
+ * - name: Required, max 200 chars
11
+ * - uom: Required, must be a valid UOM code
12
+ * - category: Required, must be a valid category code
13
+ * - description: Optional, max 1000 chars
14
+ * - status: Enum (active/inactive)
15
+ */
16
+
17
+ export const materialSchema = z.object({
18
+ code: z
19
+ .string()
20
+ .min(1, "Mã nguyên vật liệu là bắt buộc")
21
+ .max(50, "Mã nguyên vật liệu tối đa 50 ký tự")
22
+ .trim(),
23
+
24
+ item_name: z
25
+ .string()
26
+ .min(1, "Tên nguyên vật liệu là bắt buộc")
27
+ .max(200, "Tên nguyên vật liệu tối đa 200 ký tự")
28
+ .trim(),
29
+
30
+ stock_uom: z
31
+ .string()
32
+ .min(1, "Đơn vị tính là bắt buộc")
33
+ .max(20, "Đơn vị tính tối đa 20 ký tự"),
34
+
35
+ item_group: z
36
+ .string()
37
+ .min(1, "Danh mục là bắt buộc")
38
+ .max(50, "Danh mục tối đa 50 ký tự"),
39
+
40
+ description: z
41
+ .string()
42
+ .max(1000, "Mô tả tối đa 1000 ký tự")
43
+ .optional()
44
+ .or(z.literal(""))
45
+ .transform((val) => val || ""),
46
+
47
+ status: z.preprocess((val) => {
48
+ // Hỗ trợ boolean từ switch field (true -> active, false -> inactive)
49
+ if (typeof val === "boolean") {
50
+ return val ? STATUS_ACTIVE : STATUS_INACTIVE;
51
+ }
52
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
53
+ if (val === "Active" || val === "Inactive") {
54
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
55
+ }
56
+ return val;
57
+ }, z.enum(STATUS_VALUES).optional()),
58
+ });
59
+
60
+ /**
61
+ * Type inference from schema
62
+ */
63
+ export type MaterialInput = z.infer<typeof materialSchema>;
64
+
65
+ /**
66
+ * Partial schema for updates
67
+ */
68
+ export const materialUpdateSchema = materialSchema.partial();
69
+
70
+ /**
71
+ * Schema for bulk operations
72
+ */
73
+ export const materialBulkSchema = z.object({
74
+ ids: z.array(z.string()).min(1, "Phải chọn ít nhất 1 nguyên vật liệu"),
75
+ action: z.enum(["delete", "activate", "deactivate"]),
76
+ });
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+
3
+ export const MaterialBaseSchema = z.object({
4
+ code: z.string().min(1).max(64),
5
+ item_name: z.string().min(1).max(255),
6
+ item_group: z.string().min(1).max(128),
7
+ stock_uom: z.string().min(1).max(64),
8
+ description: z.string().max(2000).optional().nullable(),
9
+ status: z.string().optional(),
10
+ // General Info fields
11
+ conversion_uom: z.string().optional().nullable(),
12
+ conversion_rate: z.number().optional().nullable(),
13
+ // Inventory fields
14
+ default_stock_uom: z.string().optional().nullable(),
15
+ valuation_rate: z.number().optional().nullable(),
16
+ over_delivery_allowance: z.number().optional().nullable(),
17
+ over_billing_allowance: z.number().optional().nullable(),
18
+ stock_quantity: z.number().optional().nullable(),
19
+ safety_stock: z.number().optional().nullable(),
20
+ reorder_level: z.number().optional().nullable(),
21
+ lead_time_days: z.number().optional().nullable(),
22
+ allow_alternative_item: z.boolean().optional(),
23
+ is_fixed_asset: z.boolean().optional(),
24
+ // Purchasing fields
25
+ purchase_uom: z.string().optional().nullable(),
26
+ purchase_price: z.number().optional().nullable(),
27
+ supplier_id: z.string().optional().nullable(),
28
+ min_order_qty: z.number().optional().nullable(),
29
+ // Sales fields
30
+ sales_uom: z.string().optional().nullable(),
31
+ sales_price: z.number().optional().nullable(),
32
+ tax_category: z.string().optional().nullable(),
33
+ is_sales_item: z.boolean().optional(),
34
+ has_variants: z.boolean().optional(),
35
+ });
36
+
37
+ export const MaterialCreateSchema = MaterialBaseSchema;
38
+
39
+ export const MaterialUpdateSchema = MaterialBaseSchema.partial().extend({
40
+ id: z.string().min(1),
41
+ });
42
+
43
+ export type MaterialCreateInput = z.infer<typeof MaterialCreateSchema>;
44
+ export type MaterialUpdateInput = z.infer<typeof MaterialUpdateSchema>;
45
+
46
+ export const SupplierDefaultSchema = z.object({
47
+ supplierId: z.string().min(1),
48
+ priceListId: z.string().min(1),
49
+ isDefault: z.boolean().default(true),
50
+ });
51
+
52
+ export type SupplierDefaultInput = z.infer<typeof SupplierDefaultSchema>;
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+
3
+ export const NewPasswordSchema = z
4
+ .object({
5
+ password: z.string().min(8, {
6
+ message: "Password must contain at least 8 characters",
7
+ }),
8
+ confirmPassword: z.string().min(8, {
9
+ message: "Confirm password must contain at least 8 characters",
10
+ }),
11
+ })
12
+ .refine((data) => data.password === data.confirmPassword, {
13
+ message: "Passwords must match",
14
+ path: ["confirmPassword"],
15
+ });
@@ -0,0 +1,149 @@
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
+ * Partner Company Validation Schema
12
+ *
13
+ * Validates partner company form submissions on both client & server.
14
+ */
15
+
16
+ const dateStringSchema = (fieldLabel: string) =>
17
+ z
18
+ .string()
19
+ .min(1, `${fieldLabel} là bắt buộc`)
20
+ .refine(
21
+ (value) => {
22
+ const date = new Date(value);
23
+ return !Number.isNaN(date.getTime());
24
+ },
25
+ {
26
+ message: `${fieldLabel} không hợp lệ`,
27
+ },
28
+ );
29
+
30
+ // Base schema without refine for partial updates
31
+ const partnerCompanyBaseSchema = z.object({
32
+ code: z
33
+ .string()
34
+ .min(1, "Mã công ty đối tác là bắt buộc")
35
+ .max(50, "Mã công ty đối tác tối đa 50 ký tự")
36
+ .trim(),
37
+
38
+ name: z
39
+ .string()
40
+ .min(1, "Tên công ty là bắt buộc")
41
+ .max(200, "Tên công ty tối đa 200 ký tự")
42
+ .trim(),
43
+
44
+ taxCode: z
45
+ .string()
46
+ .min(1, "Mã số thuế là bắt buộc")
47
+ .regex(/^[0-9]{10,13}$/, "Mã số thuế phải là 10-13 chữ số"),
48
+
49
+ email: z
50
+ .string()
51
+ .email("Email không hợp lệ")
52
+ .optional()
53
+ .or(z.literal(""))
54
+ .transform((val) => val || ""),
55
+
56
+ phone: z
57
+ .string()
58
+ .regex(/^[0-9]{10}$/, "Số điện thoại phải là 10 chữ số")
59
+ .optional()
60
+ .or(z.literal(""))
61
+ .transform((val) => val || ""),
62
+
63
+ address: z
64
+ .string()
65
+ .max(500, "Địa chỉ tối đa 500 ký tự")
66
+ .optional()
67
+ .or(z.literal(""))
68
+ .transform((val) => val || ""),
69
+
70
+ description: z
71
+ .string()
72
+ .max(1000, "Mô tả tối đa 1000 ký tự")
73
+ .optional()
74
+ .or(z.literal(""))
75
+ .transform((val) => val || ""),
76
+
77
+ warehouseIds: z.preprocess((val) => {
78
+ // Nếu là mảng, trả về nguyên vẹn
79
+ if (Array.isArray(val)) {
80
+ return val;
81
+ }
82
+ // Nếu là string rỗng hoặc null/undefined, trả về mảng rỗng
83
+ if (!val || val === "") {
84
+ return [];
85
+ }
86
+ // Nếu là string, thử parse JSON hoặc split bằng dấu phẩy
87
+ if (typeof val === "string") {
88
+ try {
89
+ const parsed = JSON.parse(val);
90
+ return Array.isArray(parsed) ? parsed : [];
91
+ } catch {
92
+ // Nếu không parse được JSON, thử split bằng dấu phẩy
93
+ return val
94
+ .split(",")
95
+ .map((v) => v.trim())
96
+ .filter(Boolean);
97
+ }
98
+ }
99
+ return [];
100
+ }, z.array(z.string()).optional().default([])),
101
+
102
+ status: z.preprocess((val) => {
103
+ // Chuyển đổi boolean thành string
104
+ if (typeof val === "boolean") {
105
+ return booleanToStatus(val);
106
+ }
107
+ // Hỗ trợ cả Active/Inactive cũ và chuyển về lowercase
108
+ if (val === "Active" || val === "Inactive") {
109
+ return val === "Active" ? STATUS_ACTIVE : STATUS_INACTIVE;
110
+ }
111
+ return val;
112
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
113
+
114
+ contractStartDate: dateStringSchema("Ngày bắt đầu hợp đồng"),
115
+ contractEndDate: dateStringSchema("Ngày kết thúc hợp đồng"),
116
+ });
117
+
118
+ // Apply refine to the full schema
119
+ export const partnerCompanySchema = partnerCompanyBaseSchema.refine(
120
+ ({ contractStartDate, contractEndDate }) => {
121
+ const start = new Date(contractStartDate);
122
+ const end = new Date(contractEndDate);
123
+ return end.getTime() >= start.getTime();
124
+ },
125
+ {
126
+ message: "Ngày kết thúc hợp đồng phải sau hoặc bằng ngày bắt đầu",
127
+ path: ["contractEndDate"],
128
+ },
129
+ );
130
+
131
+ export type PartnerCompanyInput = z.infer<typeof partnerCompanySchema>;
132
+
133
+ // Create update schema from base schema (partial) with refine
134
+ export const partnerCompanyUpdateSchema = partnerCompanyBaseSchema
135
+ .partial()
136
+ .refine(
137
+ (data) => {
138
+ if (!data.contractStartDate || !data.contractEndDate) {
139
+ return true;
140
+ }
141
+ const start = new Date(data.contractStartDate);
142
+ const end = new Date(data.contractEndDate);
143
+ return end.getTime() >= start.getTime();
144
+ },
145
+ {
146
+ message: "Ngày kết thúc hợp đồng phải sau hoặc bằng ngày bắt đầu",
147
+ path: ["contractEndDate"],
148
+ },
149
+ );
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+
3
+ export const RegisterSchema = z.object({
4
+ firstName: z
5
+ .string()
6
+ .trim()
7
+ .min(2, { message: "First Name must contain at least 2 characters." })
8
+ .max(50, { message: "First Name must contain at most 50 characters." }),
9
+ lastName: z
10
+ .string()
11
+ .trim()
12
+ .min(2, { message: "Last Name must contain at least 2 characters." })
13
+ .max(50, { message: "Last Name must contain at most 50 characters." }),
14
+ username: z
15
+ .string()
16
+ .toLowerCase()
17
+ .trim()
18
+ .min(3, { message: "Username must contain at least 3 characters." })
19
+ .max(50, { message: "Username must contain at most 50 characters." }),
20
+ email: z
21
+ .string()
22
+ .email({ message: "Invalid email address" })
23
+ .toLowerCase()
24
+ .trim(),
25
+ password: z
26
+ .string()
27
+ .min(8, {
28
+ message: "Password must contain at least 8 characters",
29
+ })
30
+ .regex(/(?=.*[a-zA-Z])/, {
31
+ message: "Password must contain at least one letter.",
32
+ })
33
+ .regex(/(?=.*[0-9])/, {
34
+ message: "Password must contain at least one number.",
35
+ }),
36
+ });
@@ -0,0 +1,133 @@
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
+ * Resource Validation Schema
12
+ *
13
+ * Rules:
14
+ * - code: Required, max 50 chars
15
+ * - name: Required, max 200 chars
16
+ * - group: Optional, max 100 chars
17
+ * - description: Optional, max 1000 chars
18
+ * - status: Enum (active/inactive)
19
+ * - parentCode: Optional, max 50 chars
20
+ * - order: Optional, integer >= 0
21
+ * - type: Optional, max 50 chars
22
+ * - icon: Optional, max 100 chars
23
+ * - path: Optional, max 500 chars
24
+ * - config: Optional, JSON string
25
+ */
26
+
27
+ export const resourceSchema = z.object({
28
+ code: z
29
+ .string()
30
+ .min(1, "Mã tài nguyên là bắt buộc")
31
+ .max(50, "Mã tài nguyên tối đa 50 ký tự")
32
+ .trim(),
33
+
34
+ name: z
35
+ .string()
36
+ .min(1, "Tên tài nguyên là bắt buộc")
37
+ .max(200, "Tên tài nguyên tối đa 200 ký tự")
38
+ .trim(),
39
+
40
+ group: z
41
+ .string()
42
+ .max(100, "Nhóm tối đa 100 ký tự")
43
+ .optional()
44
+ .or(z.literal(""))
45
+ .transform((val) => val || undefined),
46
+
47
+ description: z
48
+ .string()
49
+ .max(1000, "Mô tả tối đa 1000 ký tự")
50
+ .optional()
51
+ .or(z.literal(""))
52
+ .transform((val) => val || undefined),
53
+
54
+ status: z.preprocess((val) => {
55
+ // Chuyển đổi boolean thành string
56
+ if (typeof val === "boolean") {
57
+ return booleanToStatus(val);
58
+ }
59
+ // Nếu là string hợp lệ, giữ nguyên (hỗ trợ cả Active/Inactive cũ)
60
+ if (
61
+ val === STATUS_ACTIVE ||
62
+ val === STATUS_INACTIVE ||
63
+ val === "Active" ||
64
+ val === "Inactive"
65
+ ) {
66
+ return val === "Active"
67
+ ? STATUS_ACTIVE
68
+ : val === "Inactive"
69
+ ? STATUS_INACTIVE
70
+ : val;
71
+ }
72
+ // Mặc định là 'active'
73
+ return STATUS_ACTIVE;
74
+ }, z.enum(STATUS_VALUES).default(STATUS_ACTIVE)),
75
+
76
+ parentCode: z
77
+ .string()
78
+ .max(50, "Mã cha tối đa 50 ký tự")
79
+ .optional()
80
+ .or(z.literal(""))
81
+ .transform((val) => val || undefined),
82
+
83
+ order: z
84
+ .number()
85
+ .int("Thứ tự phải là số nguyên")
86
+ .min(0, "Thứ tự phải >= 0")
87
+ .optional(),
88
+
89
+ type: z
90
+ .string()
91
+ .max(50, "Loại tối đa 50 ký tự")
92
+ .optional()
93
+ .or(z.literal(""))
94
+ .transform((val) => val || undefined),
95
+
96
+ icon: z
97
+ .string()
98
+ .max(100, "Icon tối đa 100 ký tự")
99
+ .optional()
100
+ .or(z.literal(""))
101
+ .transform((val) => val || undefined),
102
+
103
+ path: z
104
+ .string()
105
+ .max(500, "Đường dẫn tối đa 500 ký tự")
106
+ .optional()
107
+ .or(z.literal(""))
108
+ .transform((val) => val || undefined),
109
+
110
+ config: z
111
+ .string()
112
+ .optional()
113
+ .or(z.literal(""))
114
+ .transform((val) => val || undefined),
115
+ });
116
+
117
+ /**
118
+ * Type inference from schema
119
+ */
120
+ export type ResourceInput = z.infer<typeof resourceSchema>;
121
+
122
+ /**
123
+ * Partial schema for updates (all fields optional)
124
+ */
125
+ export const resourceUpdateSchema = resourceSchema.partial();
126
+
127
+ /**
128
+ * Schema for bulk operations
129
+ */
130
+ export const resourceBulkSchema = z.object({
131
+ ids: z.array(z.string()).min(1, "Phải chọn ít nhất 1 tài nguyên"),
132
+ action: z.enum(["delete", "activate", "deactivate"]),
133
+ });
@@ -0,0 +1,11 @@
1
+ import { z } from "zod";
2
+
3
+ export const roleSchema = z.object({
4
+ name: z.string().min(1, "Name is required"),
5
+ code: z.string().min(1, "Code is required"),
6
+ description: z.string().optional(),
7
+ status: z.enum(["active", "inactive"]).default("active"),
8
+ permissions: z.array(z.string()).optional(),
9
+ });
10
+
11
+ export type RoleFormData = z.infer<typeof roleSchema>;
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+
3
+ export const SignInSchema = z.object({
4
+ email: z
5
+ .string()
6
+ .email({ message: "Invalid email address" })
7
+ .toLowerCase()
8
+ .trim(),
9
+ password: z
10
+ .string()
11
+ .min(8, {
12
+ message: "Password must contain at least 8 characters",
13
+ })
14
+ .max(250, {
15
+ message: "Password must contain at most 250 characters",
16
+ })
17
+ .regex(/(?=.*[a-zA-Z])/, {
18
+ message: "Password must contain at least one letter.",
19
+ })
20
+ .regex(/(?=.*[0-9])/, {
21
+ message: "Password must contain at least one number.",
22
+ }),
23
+ rememberMe: z.boolean().optional(),
24
+ });
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+
3
+ export const supplierPricingSchema = z.object({
4
+ materialId: z.string().min(1, "Material ID is required"),
5
+ supplierId: z.string().min(1, "Supplier ID is required"),
6
+ isDefault: z.boolean().default(false),
7
+ priceListId: z.string().optional().nullable(),
8
+ });
9
+
10
+ export const updateSupplierPricingSchema = supplierPricingSchema.partial();
11
+
12
+ export type SupplierPricingInput = z.infer<typeof supplierPricingSchema>;
13
+ export type UpdateSupplierPricingInput = z.infer<
14
+ typeof updateSupplierPricingSchema
15
+ >;