@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,25 @@
1
+ // Logger Types
2
+ export type LogLevel = "trace" | "debug" | "info" | "warn" | "error";
3
+
4
+ export interface LoggerOptions {
5
+ /** Logger name/context for identification */
6
+ name?: string;
7
+ /** Minimum log level */
8
+ level?: LogLevel;
9
+ /** Enable file output */
10
+ enableFile?: boolean;
11
+ /** Directory for log files */
12
+ dirname?: string;
13
+ }
14
+
15
+ export interface LogContext {
16
+ [key: string]: unknown;
17
+ }
18
+
19
+ export interface Logger {
20
+ trace(message: string, context?: LogContext): void;
21
+ debug(message: string, context?: LogContext): void;
22
+ info(message: string, context?: LogContext): void;
23
+ warn(message: string, context?: LogContext): void;
24
+ error(message: string, context?: LogContext): void;
25
+ }
@@ -0,0 +1,185 @@
1
+ // @goerp/core/layout
2
+ // Layout components for GoERP applications
3
+ //
4
+ // NOTE: This module contains basic layout shells.
5
+ // Full layout components (sidebar, header, navigation) should be migrated
6
+ // from packages/shared/layout as needed.
7
+
8
+ "use client";
9
+
10
+ import * as React from "react";
11
+ import { cn } from "../utils";
12
+
13
+ // ============================================================================
14
+ // AppShell - Main application container
15
+ // ============================================================================
16
+
17
+ export interface AppShellProps {
18
+ children: React.ReactNode;
19
+ sidebar?: React.ReactNode;
20
+ header?: React.ReactNode;
21
+ footer?: React.ReactNode;
22
+ className?: string;
23
+ }
24
+
25
+ export function AppShell({
26
+ children,
27
+ sidebar,
28
+ header,
29
+ footer,
30
+ className,
31
+ }: AppShellProps) {
32
+ return (
33
+ <div className={cn("flex min-h-screen", className)}>
34
+ {sidebar}
35
+ <div className="flex flex-1 flex-col">
36
+ {header}
37
+ <main className="flex-1">{children}</main>
38
+ {footer}
39
+ </div>
40
+ </div>
41
+ );
42
+ }
43
+
44
+ // ============================================================================
45
+ // Header
46
+ // ============================================================================
47
+
48
+ export interface HeaderProps {
49
+ children?: React.ReactNode;
50
+ className?: string;
51
+ sticky?: boolean;
52
+ }
53
+
54
+ export function Header({ children, className, sticky = true }: HeaderProps) {
55
+ return (
56
+ <header
57
+ className={cn(
58
+ "border-b bg-background",
59
+ sticky && "sticky top-0 z-50",
60
+ className,
61
+ )}
62
+ >
63
+ {children}
64
+ </header>
65
+ );
66
+ }
67
+
68
+ // ============================================================================
69
+ // Sidebar
70
+ // ============================================================================
71
+
72
+ export interface SidebarProps {
73
+ children?: React.ReactNode;
74
+ className?: string;
75
+ collapsed?: boolean;
76
+ width?: string | number;
77
+ collapsedWidth?: string | number;
78
+ }
79
+
80
+ export function Sidebar({
81
+ children,
82
+ className,
83
+ collapsed = false,
84
+ width = 280,
85
+ collapsedWidth = 68,
86
+ }: SidebarProps) {
87
+ const sidebarWidth = collapsed ? collapsedWidth : width;
88
+
89
+ return (
90
+ <aside
91
+ className={cn("border-r bg-background transition-all", className)}
92
+ style={{
93
+ width:
94
+ typeof sidebarWidth === "number" ? `${sidebarWidth}px` : sidebarWidth,
95
+ }}
96
+ >
97
+ {children}
98
+ </aside>
99
+ );
100
+ }
101
+
102
+ // ============================================================================
103
+ // Footer
104
+ // ============================================================================
105
+
106
+ export interface FooterProps {
107
+ children?: React.ReactNode;
108
+ className?: string;
109
+ }
110
+
111
+ export function Footer({ children, className }: FooterProps) {
112
+ return (
113
+ <footer className={cn("border-t bg-background", className)}>
114
+ {children}
115
+ </footer>
116
+ );
117
+ }
118
+
119
+ // ============================================================================
120
+ // PageContainer
121
+ // ============================================================================
122
+
123
+ export interface PageContainerProps {
124
+ children: React.ReactNode;
125
+ className?: string;
126
+ title?: string;
127
+ description?: string;
128
+ }
129
+
130
+ export function PageContainer({
131
+ children,
132
+ className,
133
+ title,
134
+ description,
135
+ }: PageContainerProps) {
136
+ return (
137
+ <div className={cn("w-full px-4 md:px-6 lg:px-8 py-6", className)}>
138
+ {(title || description) && (
139
+ <div className="mb-6">
140
+ {title && <h1 className="text-2xl font-bold">{title}</h1>}
141
+ {description && (
142
+ <p className="text-muted-foreground">{description}</p>
143
+ )}
144
+ </div>
145
+ )}
146
+ {children}
147
+ </div>
148
+ );
149
+ }
150
+
151
+ // ============================================================================
152
+ // Breadcrumb
153
+ // ============================================================================
154
+
155
+ export interface BreadcrumbItem {
156
+ label: string;
157
+ href?: string;
158
+ }
159
+
160
+ export interface BreadcrumbProps {
161
+ items: BreadcrumbItem[];
162
+ className?: string;
163
+ }
164
+
165
+ export function Breadcrumb({ items, className }: BreadcrumbProps) {
166
+ return (
167
+ <nav className={cn("flex items-center space-x-2 text-sm", className)}>
168
+ {items.map((item, index) => (
169
+ <React.Fragment key={index}>
170
+ {index > 0 && <span className="text-muted-foreground">/</span>}
171
+ {item.href ? (
172
+ <a
173
+ href={item.href}
174
+ className="text-muted-foreground hover:text-foreground"
175
+ >
176
+ {item.label}
177
+ </a>
178
+ ) : (
179
+ <span className="font-medium">{item.label}</span>
180
+ )}
181
+ </React.Fragment>
182
+ ))}
183
+ </nav>
184
+ );
185
+ }
@@ -0,0 +1,91 @@
1
+ // @goerp/core/navigation
2
+ // Core navigation utilities for GoERP platform
3
+ // Consolidated from packages/shared/navigation
4
+
5
+ import type {
6
+ NavigationType,
7
+ NavigationRootItem,
8
+ NavigationNestedItem,
9
+ } from "../types";
10
+
11
+ /**
12
+ * Filter navigation items based on permissions recursively
13
+ */
14
+ export function filterNavigationItems(
15
+ items: NavigationRootItem[],
16
+ accessibleCodes: Set<string>,
17
+ ): NavigationRootItem[];
18
+ export function filterNavigationItems(
19
+ items: NavigationNestedItem[],
20
+ accessibleCodes: Set<string>,
21
+ ): NavigationNestedItem[];
22
+ export function filterNavigationItems(
23
+ items: NavigationRootItem[] | NavigationNestedItem[],
24
+ accessibleCodes: Set<string>,
25
+ ): (NavigationRootItem | NavigationNestedItem)[] {
26
+ return items.reduce<(NavigationRootItem | NavigationNestedItem)[]>(
27
+ (acc, item) => {
28
+ // If admin (special wildcard), show everything
29
+ if (accessibleCodes.has("*")) {
30
+ acc.push(item);
31
+ return acc;
32
+ }
33
+
34
+ // Default Deny: If resource is defined AND resource is not accessible
35
+ // If resource is missing, we consider it public (as per comment below)
36
+ if (item.resource && !accessibleCodes.has(item.resource)) {
37
+ return acc;
38
+ }
39
+
40
+ // Handle nested items
41
+ if ("items" in item && item.items) {
42
+ const filteredChildren = filterNavigationItems(
43
+ item.items as (NavigationRootItem | NavigationNestedItem)[],
44
+ accessibleCodes,
45
+ );
46
+
47
+ // Only add parent if it has visible children
48
+ if (filteredChildren.length > 0) {
49
+ acc.push({
50
+ ...item,
51
+ items: filteredChildren,
52
+ });
53
+ }
54
+ } else {
55
+ // Leaf node (link) - already checked resource above
56
+ // If no resource defined, assume public/visible
57
+ acc.push(item);
58
+ }
59
+
60
+ return acc;
61
+ },
62
+ [],
63
+ );
64
+ }
65
+
66
+ /**
67
+ * Filter navigation tree based on permissions
68
+ */
69
+ export function filterNavigationTree(
70
+ navigation: NavigationType[],
71
+ accessibleCodes: Set<string>,
72
+ ): NavigationType[] {
73
+ if (accessibleCodes.has("*")) {
74
+ return navigation;
75
+ }
76
+
77
+ const filteredNavigation: NavigationType[] = [];
78
+
79
+ for (const group of navigation) {
80
+ const filteredItems = filterNavigationItems(group.items, accessibleCodes);
81
+
82
+ if (filteredItems.length > 0) {
83
+ filteredNavigation.push({
84
+ ...group,
85
+ items: filteredItems,
86
+ });
87
+ }
88
+ }
89
+
90
+ return filteredNavigation;
91
+ }
@@ -0,0 +1,14 @@
1
+ export {
2
+ notificationService,
3
+ NotificationServiceImpl,
4
+ } from "./notification-service";
5
+ export { InMemoryStorage } from "./storage";
6
+ export type {
7
+ Notification,
8
+ NotificationType,
9
+ NotificationChannel,
10
+ NotificationStatus,
11
+ CreateNotificationInput,
12
+ NotificationStorage,
13
+ NotificationServiceOptions,
14
+ } from "./types";
@@ -0,0 +1,120 @@
1
+ import type {
2
+ CreateNotificationInput,
3
+ Notification,
4
+ NotificationServiceOptions,
5
+ NotificationStorage,
6
+ } from "./types";
7
+ import { InMemoryStorage } from "./storage/in-memory";
8
+ import { createLogger } from "../infrastructure/logger";
9
+ import { eventBus } from "../infrastructure/event-bus";
10
+
11
+ const logger = createLogger("NotificationService");
12
+
13
+ /**
14
+ * NotificationService - sends and manages user notifications
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { notificationService } from '@goerp/core/notification';
19
+ *
20
+ * // Send notification
21
+ * await notificationService.send({
22
+ * userId: 'manager-123',
23
+ * title: 'Purchase Order cần duyệt',
24
+ * content: 'PO-001 chờ phê duyệt',
25
+ * type: 'approval',
26
+ * link: '/purchase-orders/PO-001'
27
+ * });
28
+ *
29
+ * // Get unread notifications
30
+ * const unread = await notificationService.getUnread('manager-123');
31
+ *
32
+ * // Mark as read
33
+ * await notificationService.markAsRead('notification-id');
34
+ * ```
35
+ */
36
+ class NotificationServiceImpl {
37
+ private storage: NotificationStorage;
38
+
39
+ constructor(options: NotificationServiceOptions = {}) {
40
+ this.storage = options.storage || new InMemoryStorage();
41
+ }
42
+
43
+ /** Set custom storage implementation */
44
+ setStorage(storage: NotificationStorage): void {
45
+ this.storage = storage;
46
+ }
47
+
48
+ /** Send a notification */
49
+ async send(input: CreateNotificationInput): Promise<Notification> {
50
+ const notification: Notification = {
51
+ id: crypto.randomUUID(),
52
+ userId: input.userId,
53
+ title: input.title,
54
+ content: input.content,
55
+ type: input.type || "info",
56
+ channel: input.channel || "in-app",
57
+ status: "sent",
58
+ link: input.link,
59
+ metadata: input.metadata,
60
+ createdAt: new Date(),
61
+ };
62
+
63
+ await this.storage.save(notification);
64
+
65
+ logger.debug("Notification sent", {
66
+ id: notification.id,
67
+ userId: notification.userId,
68
+ type: notification.type,
69
+ });
70
+
71
+ // Emit event for real-time updates
72
+ eventBus.emit("notification.sent", { notification });
73
+
74
+ return notification;
75
+ }
76
+
77
+ /** Get all notifications for a user */
78
+ async getAll(userId: string): Promise<Notification[]> {
79
+ return this.storage.findByUserId(userId);
80
+ }
81
+
82
+ /** Get unread notifications for a user */
83
+ async getUnread(userId: string): Promise<Notification[]> {
84
+ return this.storage.findByUserId(userId, { unreadOnly: true });
85
+ }
86
+
87
+ /** Get unread count for a user */
88
+ async getUnreadCount(userId: string): Promise<number> {
89
+ const unread = await this.getUnread(userId);
90
+ return unread.length;
91
+ }
92
+
93
+ /** Get a notification by ID */
94
+ async getById(id: string): Promise<Notification | null> {
95
+ return this.storage.findById(id);
96
+ }
97
+
98
+ /** Mark a notification as read */
99
+ async markAsRead(id: string): Promise<void> {
100
+ await this.storage.markAsRead(id);
101
+ eventBus.emit("notification.read", { id });
102
+ }
103
+
104
+ /** Mark all notifications as read for a user */
105
+ async markAllAsRead(userId: string): Promise<void> {
106
+ await this.storage.markAllAsRead(userId);
107
+ eventBus.emit("notification.allRead", { userId });
108
+ }
109
+
110
+ /** Delete a notification */
111
+ async delete(id: string): Promise<void> {
112
+ await this.storage.delete(id);
113
+ }
114
+ }
115
+
116
+ // Singleton instance
117
+ export const notificationService = new NotificationServiceImpl();
118
+
119
+ // Export class for testing
120
+ export { NotificationServiceImpl };
@@ -0,0 +1,56 @@
1
+ import type { Notification, NotificationStorage } from "../types";
2
+
3
+ /**
4
+ * In-memory notification storage for development/testing
5
+ * In production, replace with database storage
6
+ */
7
+ export class InMemoryStorage implements NotificationStorage {
8
+ private notifications = new Map<string, Notification>();
9
+
10
+ async save(notification: Notification): Promise<void> {
11
+ this.notifications.set(notification.id, notification);
12
+ }
13
+
14
+ async findByUserId(
15
+ userId: string,
16
+ options?: { unreadOnly?: boolean },
17
+ ): Promise<Notification[]> {
18
+ const result: Notification[] = [];
19
+
20
+ for (const notification of this.notifications.values()) {
21
+ if (notification.userId === userId) {
22
+ if (options?.unreadOnly && notification.status === "read") {
23
+ continue;
24
+ }
25
+ result.push(notification);
26
+ }
27
+ }
28
+
29
+ return result.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
30
+ }
31
+
32
+ async findById(id: string): Promise<Notification | null> {
33
+ return this.notifications.get(id) || null;
34
+ }
35
+
36
+ async markAsRead(id: string): Promise<void> {
37
+ const notification = this.notifications.get(id);
38
+ if (notification) {
39
+ notification.status = "read";
40
+ notification.readAt = new Date();
41
+ }
42
+ }
43
+
44
+ async markAllAsRead(userId: string): Promise<void> {
45
+ for (const notification of this.notifications.values()) {
46
+ if (notification.userId === userId && notification.status !== "read") {
47
+ notification.status = "read";
48
+ notification.readAt = new Date();
49
+ }
50
+ }
51
+ }
52
+
53
+ async delete(id: string): Promise<void> {
54
+ this.notifications.delete(id);
55
+ }
56
+ }
@@ -0,0 +1 @@
1
+ export { InMemoryStorage } from "./in-memory";
@@ -0,0 +1,51 @@
1
+ // Notification Types
2
+ export type NotificationType =
3
+ | "info"
4
+ | "warning"
5
+ | "error"
6
+ | "success"
7
+ | "approval";
8
+ export type NotificationChannel = "in-app" | "email" | "sms";
9
+ export type NotificationStatus = "pending" | "sent" | "read" | "failed";
10
+
11
+ export interface Notification {
12
+ id: string;
13
+ userId: string;
14
+ title: string;
15
+ content: string;
16
+ type: NotificationType;
17
+ channel: NotificationChannel;
18
+ status: NotificationStatus;
19
+ /** Link to navigate when clicked */
20
+ link?: string;
21
+ /** Additional metadata */
22
+ metadata?: Record<string, unknown>;
23
+ createdAt: Date;
24
+ readAt?: Date;
25
+ }
26
+
27
+ export interface CreateNotificationInput {
28
+ userId: string;
29
+ title: string;
30
+ content: string;
31
+ type?: NotificationType;
32
+ channel?: NotificationChannel;
33
+ link?: string;
34
+ metadata?: Record<string, unknown>;
35
+ }
36
+
37
+ export interface NotificationStorage {
38
+ save(notification: Notification): Promise<void>;
39
+ findByUserId(
40
+ userId: string,
41
+ options?: { unreadOnly?: boolean },
42
+ ): Promise<Notification[]>;
43
+ findById(id: string): Promise<Notification | null>;
44
+ markAsRead(id: string): Promise<void>;
45
+ markAllAsRead(userId: string): Promise<void>;
46
+ delete(id: string): Promise<void>;
47
+ }
48
+
49
+ export interface NotificationServiceOptions {
50
+ storage?: NotificationStorage;
51
+ }