@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,47 @@
1
+ "use client";
2
+
3
+ import type { DictionaryType } from "../../hooks";
4
+ import type { ReactNode } from "react";
5
+ import type { NavigationType } from "../../types";
6
+
7
+ import { SidebarProvider, SidebarInset } from "../primitives/sidebar";
8
+ import { Footer } from "./footer";
9
+ import { AppSidebar } from "./sidebar"; // Use renamed AppSidebar
10
+ import { VerticalLayoutHeader } from "./vertical-layout-header";
11
+
12
+ interface VerticalLayoutProps {
13
+ children: ReactNode;
14
+ dictionary: DictionaryType;
15
+ navigation?: NavigationType[];
16
+ onGlobalSearch?: (query: string) => void;
17
+ searchResults?: any[];
18
+ searchLoading?: boolean;
19
+ }
20
+
21
+ export function VerticalLayout({
22
+ children,
23
+ dictionary,
24
+ navigation,
25
+ onGlobalSearch,
26
+ searchResults,
27
+ searchLoading,
28
+ }: VerticalLayoutProps) {
29
+ return (
30
+ <SidebarProvider>
31
+ <AppSidebar
32
+ dictionary={dictionary}
33
+ navigation={navigation ?? []}
34
+ onGlobalSearch={onGlobalSearch}
35
+ searchResults={searchResults}
36
+ searchLoading={searchLoading}
37
+ />
38
+ <SidebarInset className="w-full min-w-0 overflow-hidden h-screen flex flex-col">
39
+ <VerticalLayoutHeader dictionary={dictionary} />
40
+ <main className="w-full mx-auto flex-1 min-h-0 px-4 md:px-8 py-4 overflow-auto">
41
+ {children}
42
+ </main>
43
+ <Footer />
44
+ </SidebarInset>
45
+ </SidebarProvider>
46
+ );
47
+ }
@@ -0,0 +1,209 @@
1
+ "use client";
2
+
3
+ import React, { useState, useEffect } from "react";
4
+ import { auditManager } from "../../audit/audit-manager";
5
+ import type { AuditLog } from "../../audit/types";
6
+
7
+ // Relative imports to core UI components
8
+ import { Badge } from "../primitives/badge";
9
+ import { Button } from "../primitives/button";
10
+ import { Card, CardHeader, CardTitle, CardContent } from "../primitives/card";
11
+ import { Input } from "../primitives/input";
12
+ import { Label } from "../primitives/label";
13
+ import {
14
+ Table,
15
+ TableBody,
16
+ TableCell,
17
+ TableHead,
18
+ TableHeader,
19
+ TableRow,
20
+ } from "../primitives/table";
21
+ import {
22
+ Select,
23
+ SelectContent,
24
+ SelectItem,
25
+ SelectTrigger,
26
+ SelectValue,
27
+ } from "../primitives/select";
28
+
29
+ export const AuditLogPage = () => {
30
+ const [logs, setLogs] = useState<AuditLog[]>([]);
31
+ const [userIdFilter, setUserIdFilter] = useState("");
32
+ const [actionFilter, setActionFilter] = useState("");
33
+ const [resourceFilter, setResourceFilter] = useState("");
34
+ const [typeFilter, setTypeFilter] = useState<string>("all");
35
+
36
+ const fetchLogs = () => {
37
+ // Safe cast as we know we added getLogs
38
+ // In real app, we would have proper interface
39
+ const manager = auditManager as any;
40
+ if (typeof manager.getLogs === "function") {
41
+ const filter: any = {};
42
+ if (userIdFilter) filter.userId = userIdFilter;
43
+ if (actionFilter) filter.action = actionFilter;
44
+ if (resourceFilter) filter.resource = resourceFilter;
45
+ if (typeFilter && typeFilter !== "all") filter.type = typeFilter;
46
+
47
+ setLogs(manager.getLogs(filter));
48
+ }
49
+ };
50
+
51
+ useEffect(() => {
52
+ fetchLogs();
53
+ // Poll for updates in demo
54
+ const interval = setInterval(fetchLogs, 5000);
55
+ return () => clearInterval(interval);
56
+ }, [userIdFilter, actionFilter, resourceFilter, typeFilter]);
57
+
58
+ // Format changes object for display
59
+ const renderChanges = (changes: any) => {
60
+ if (!changes) return <span className="text-muted-foreground">-</span>;
61
+ return (
62
+ <code
63
+ className="text-xs bg-slate-100 dark:bg-slate-800 p-1 rounded block max-w-[300px] overflow-hidden text-ellipsis whitespace-nowrap"
64
+ title={JSON.stringify(changes, null, 2)}
65
+ >
66
+ {Object.keys(changes).join(", ")}
67
+ </code>
68
+ );
69
+ };
70
+
71
+ return (
72
+ <div className="p-6 space-y-6 h-full flex flex-col">
73
+ <div className="flex justify-between items-center mb-4">
74
+ <div>
75
+ <h1 className="text-2xl font-bold tracking-tight">Audit Logs</h1>
76
+ <p className="text-muted-foreground text-sm">
77
+ Track system changes and user actions.
78
+ </p>
79
+ </div>
80
+ <Button onClick={fetchLogs} variant="outline">
81
+ Refresh
82
+ </Button>
83
+ </div>
84
+
85
+ <Card>
86
+ <CardHeader>
87
+ <CardTitle className="text-base font-medium">Filters</CardTitle>
88
+ </CardHeader>
89
+ <CardContent>
90
+ <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4">
91
+ <div className="space-y-1">
92
+ <Label htmlFor="user-filter">User ID</Label>
93
+ <Input
94
+ id="user-filter"
95
+ placeholder="Search by user..."
96
+ value={userIdFilter}
97
+ onChange={(e) => setUserIdFilter(e.target.value)}
98
+ />
99
+ </div>
100
+ <div className="space-y-1">
101
+ <Label htmlFor="action-filter">Action</Label>
102
+ <Input
103
+ id="action-filter"
104
+ placeholder="e.g. create, update"
105
+ value={actionFilter}
106
+ onChange={(e) => setActionFilter(e.target.value)}
107
+ />
108
+ </div>
109
+ <div className="space-y-1">
110
+ <Label htmlFor="resource-filter">Resource</Label>
111
+ <Input
112
+ id="resource-filter"
113
+ placeholder="e.g. product, order"
114
+ value={resourceFilter}
115
+ onChange={(e) => setResourceFilter(e.target.value)}
116
+ />
117
+ </div>
118
+ <div className="space-y-1">
119
+ <Label htmlFor="type-filter">Type</Label>
120
+ <Select value={typeFilter} onValueChange={setTypeFilter}>
121
+ <SelectTrigger>
122
+ <SelectValue placeholder="All Types" />
123
+ </SelectTrigger>
124
+ <SelectContent>
125
+ <SelectItem value="all">All Types</SelectItem>
126
+ <SelectItem value="info">Info</SelectItem>
127
+ <SelectItem value="warning">Warning</SelectItem>
128
+ <SelectItem value="error">Error</SelectItem>
129
+ </SelectContent>
130
+ </Select>
131
+ </div>
132
+ </div>
133
+ </CardContent>
134
+ </Card>
135
+
136
+ <Card className="flex-1 flex flex-col min-h-0">
137
+ <CardContent className="flex-1 overflow-auto p-0">
138
+ <Table>
139
+ <TableHeader>
140
+ <TableRow>
141
+ <TableHead className="w-[180px]">Timestamp</TableHead>
142
+ <TableHead className="w-[150px]">Action</TableHead>
143
+ <TableHead className="w-[150px]">Resource</TableHead>
144
+ <TableHead className="w-[150px]">User</TableHead>
145
+ <TableHead>Changes / Metadata</TableHead>
146
+ <TableHead className="w-[100px] text-right">Status</TableHead>
147
+ </TableRow>
148
+ </TableHeader>
149
+ <TableBody>
150
+ {logs.length === 0 && (
151
+ <TableRow>
152
+ <TableCell
153
+ colSpan={6}
154
+ className="text-center h-24 text-muted-foreground"
155
+ >
156
+ No logs found matching filters.
157
+ </TableCell>
158
+ </TableRow>
159
+ )}
160
+ {logs.map((log) => (
161
+ <TableRow key={log.id}>
162
+ <TableCell className="font-mono text-xs">
163
+ {new Date(log.createdAt).toLocaleString()}
164
+ </TableCell>
165
+ <TableCell>
166
+ <Badge variant="outline" className="font-normal">
167
+ {log.action}
168
+ </Badge>
169
+ </TableCell>
170
+ <TableCell>{log.resource}</TableCell>
171
+ <TableCell>
172
+ <div className="flex flex-col">
173
+ <span>{log.userId || "System"}</span>
174
+ {log.roleName && (
175
+ <span className="text-[10px] text-muted-foreground">
176
+ {log.roleName}
177
+ </span>
178
+ )}
179
+ </div>
180
+ </TableCell>
181
+ <TableCell>
182
+ {renderChanges(log.changes)}
183
+ {log.metadata && Object.keys(log.metadata).length > 0 && (
184
+ <div className="text-[10px] text-muted-foreground mt-1">
185
+ MD: {JSON.stringify(log.metadata).substring(0, 50)}...
186
+ </div>
187
+ )}
188
+ </TableCell>
189
+ <TableCell className="text-right">
190
+ {(log.status || 200) >= 400 ? (
191
+ <Badge variant="destructive">{log.status}</Badge>
192
+ ) : (
193
+ <Badge
194
+ variant="secondary"
195
+ className="bg-emerald-100 text-emerald-700 hover:bg-emerald-100"
196
+ >
197
+ {log.status || 200}
198
+ </Badge>
199
+ )}
200
+ </TableCell>
201
+ </TableRow>
202
+ ))}
203
+ </TableBody>
204
+ </Table>
205
+ </CardContent>
206
+ </Card>
207
+ </div>
208
+ );
209
+ };
@@ -0,0 +1,349 @@
1
+ "use client";
2
+
3
+ import React, { useState, useEffect } from "react";
4
+ // Remove direct import of server-side cacheManager
5
+ // import { cacheManager } from "../../infrastructure/cache/cache-manager";
6
+
7
+ // Relative imports to core UI components
8
+ import { Badge } from "../primitives/badge";
9
+ import { Button } from "../primitives/button";
10
+ import { Card, CardHeader, CardTitle, CardContent } from "../primitives/card";
11
+ import { Input } from "../primitives/input";
12
+ import {
13
+ Table,
14
+ TableBody,
15
+ TableCell,
16
+ TableHead,
17
+ TableHeader,
18
+ TableRow,
19
+ } from "../primitives/table";
20
+ import {
21
+ Dialog,
22
+ DialogContent,
23
+ DialogHeader,
24
+ DialogTitle,
25
+ DialogDescription,
26
+ } from "../primitives/dialog";
27
+ import { ScrollArea } from "../primitives/scroll-area"; // Assume scroll-area exists or use div
28
+
29
+ interface CacheStat {
30
+ name: string;
31
+ itemCount: number;
32
+ ttl: number;
33
+ }
34
+
35
+ interface CacheManagementPageProps {
36
+ /** Server action to fetch stats */
37
+ fetchStats?: () => Promise<CacheStat[]>;
38
+ /** Server action to clear specific cache */
39
+ clearCache?: (name: string) => Promise<boolean>;
40
+ /** Server action to clear all caches */
41
+ clearAll?: () => Promise<void>;
42
+ /** Server action to get keys of a cache */
43
+ getCacheKeys?: (name: string) => Promise<string[]>;
44
+ /** Server action to get value of a cache key */
45
+ getCacheValue?: (name: string, key: string) => Promise<any>;
46
+ }
47
+
48
+ export const CacheManagementPage = ({
49
+ fetchStats,
50
+ clearCache,
51
+ clearAll,
52
+ getCacheKeys,
53
+ getCacheValue,
54
+ }: CacheManagementPageProps) => {
55
+ const [caches, setCaches] = useState<CacheStat[]>([]);
56
+ const [searchTerm, setSearchTerm] = useState("");
57
+ const [refresh, setRefresh] = useState(0);
58
+ const [loading, setLoading] = useState(false);
59
+
60
+ // Inspection State
61
+ const [inspectCacheName, setInspectCacheName] = useState<string | null>(null);
62
+ const [cacheKeys, setCacheKeys] = useState<string[]>([]);
63
+ const [inspectKey, setInspectKey] = useState<string | null>(null);
64
+ const [keyValue, setKeyValue] = useState<any>(null);
65
+ const [inspecting, setInspecting] = useState(false);
66
+
67
+ useEffect(() => {
68
+ loadStats();
69
+ }, [refresh]);
70
+
71
+ const loadStats = async () => {
72
+ if (!fetchStats) return;
73
+ try {
74
+ setLoading(true);
75
+ const stats = await fetchStats();
76
+ setCaches(stats);
77
+ } catch (error) {
78
+ console.error("Failed to load cache stats:", error);
79
+ } finally {
80
+ setLoading(false);
81
+ }
82
+ };
83
+
84
+ const handleClearAll = async () => {
85
+ if (!clearAll) return;
86
+ if (
87
+ confirm(
88
+ "Are you sure you want to clear ALL caches? Performance may be impacted.",
89
+ )
90
+ ) {
91
+ try {
92
+ setLoading(true);
93
+ await clearAll();
94
+ setRefresh((r) => r + 1); // Trigger reload
95
+ } catch (error) {
96
+ console.error("Failed to clear all caches:", error);
97
+ } finally {
98
+ setLoading(false);
99
+ }
100
+ }
101
+ };
102
+
103
+ const handleClearCache = async (name: string) => {
104
+ if (!clearCache) return;
105
+ try {
106
+ setLoading(true);
107
+ await clearCache(name);
108
+ setRefresh((r) => r + 1); // Trigger reload
109
+ } catch (error) {
110
+ console.error(`Failed to clear cache ${name}:`, error);
111
+ } finally {
112
+ setLoading(false);
113
+ }
114
+ };
115
+
116
+ const handleInspect = async (name: string) => {
117
+ if (!getCacheKeys) return;
118
+ try {
119
+ setInspecting(true);
120
+ setInspectCacheName(name);
121
+ setCacheKeys([]);
122
+ setInspectKey(null);
123
+
124
+ const keys = await getCacheKeys(name);
125
+ setCacheKeys(keys);
126
+ } catch (error) {
127
+ console.error(`Failed to inspect cache ${name}:`, error);
128
+ } finally {
129
+ setInspecting(false);
130
+ }
131
+ };
132
+
133
+ const handleViewValue = async (key: string) => {
134
+ if (!getCacheValue || !inspectCacheName) return;
135
+ try {
136
+ setInspecting(true);
137
+ const value = await getCacheValue(inspectCacheName, key);
138
+ setKeyValue(value);
139
+ setInspectKey(key);
140
+ } catch (error) {
141
+ console.error(`Failed to get value for ${key}:`, error);
142
+ } finally {
143
+ setInspecting(false);
144
+ }
145
+ };
146
+
147
+ const filteredCaches = caches.filter((c) =>
148
+ c.name.toLowerCase().includes(searchTerm.toLowerCase()),
149
+ );
150
+
151
+ const totalItems = caches.reduce((acc, curr) => acc + curr.itemCount, 0);
152
+
153
+ if (!fetchStats) {
154
+ return (
155
+ <div className="p-6 text-red-500">
156
+ Error: fetchStats server action not provided to CacheManagementPage.
157
+ </div>
158
+ );
159
+ }
160
+
161
+ return (
162
+ <div className="p-6 space-y-6 h-full flex flex-col">
163
+ <div className="flex justify-between items-center mb-4">
164
+ <div>
165
+ <h1 className="text-2xl font-bold tracking-tight">
166
+ Cache Management
167
+ </h1>
168
+ <p className="text-muted-foreground text-sm">
169
+ Monitor cache usage and clear cached data.
170
+ </p>
171
+ </div>
172
+ <div className="flex gap-2">
173
+ <Button
174
+ onClick={() => setRefresh((r) => r + 1)}
175
+ variant="outline"
176
+ disabled={loading}
177
+ >
178
+ {loading ? "Loading..." : "Refresh"}
179
+ </Button>
180
+ <Button
181
+ onClick={handleClearAll}
182
+ variant="destructive"
183
+ disabled={!clearAll || loading}
184
+ >
185
+ Clear All Caches
186
+ </Button>
187
+ </div>
188
+ </div>
189
+
190
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
191
+ <Card>
192
+ <CardHeader className="pb-2">
193
+ <CardTitle className="text-sm font-medium text-muted-foreground">
194
+ Total Caches
195
+ </CardTitle>
196
+ </CardHeader>
197
+ <CardContent>
198
+ <div className="text-2xl font-bold">{caches.length}</div>
199
+ </CardContent>
200
+ </Card>
201
+ <Card>
202
+ <CardHeader className="pb-2">
203
+ <CardTitle className="text-sm font-medium text-muted-foreground">
204
+ Total Cached Items
205
+ </CardTitle>
206
+ </CardHeader>
207
+ <CardContent>
208
+ <div className="text-2xl font-bold">{totalItems}</div>
209
+ </CardContent>
210
+ </Card>
211
+ <Card>
212
+ <CardHeader className="pb-2">
213
+ <CardTitle className="text-sm font-medium text-muted-foreground">
214
+ System Status
215
+ </CardTitle>
216
+ </CardHeader>
217
+ <CardContent>
218
+ <div className="flex items-center gap-2">
219
+ <span className="relative flex h-3 w-3">
220
+ <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
221
+ <span className="relative inline-flex rounded-full h-3 w-3 bg-emerald-500"></span>
222
+ </span>
223
+ <span className="text-sm font-medium text-emerald-600">
224
+ Active
225
+ </span>
226
+ </div>
227
+ </CardContent>
228
+ </Card>
229
+ </div>
230
+
231
+ <Card className="flex-1 flex flex-col min-h-0">
232
+ <CardHeader>
233
+ <div className="flex items-center justify-between">
234
+ <CardTitle>Cache Instances</CardTitle>
235
+ <div className="w-[250px]">
236
+ <Input
237
+ placeholder="Filter by name..."
238
+ value={searchTerm}
239
+ onChange={(e) => setSearchTerm(e.target.value)}
240
+ />
241
+ </div>
242
+ </div>
243
+ </CardHeader>
244
+ <CardContent className="flex-1 overflow-auto p-0">
245
+ <Table>
246
+ <TableHeader>
247
+ <TableRow>
248
+ <TableHead>Cache Name</TableHead>
249
+ <TableHead>Items</TableHead>
250
+ <TableHead>TTL (Seconds)</TableHead>
251
+ <TableHead className="text-right">Actions</TableHead>
252
+ </TableRow>
253
+ </TableHeader>
254
+ <TableBody>
255
+ {filteredCaches.length === 0 && (
256
+ <TableRow>
257
+ <TableCell
258
+ colSpan={4}
259
+ className="text-center h-24 text-muted-foreground"
260
+ >
261
+ {loading ? "Loading caches..." : "No caches found."}
262
+ </TableCell>
263
+ </TableRow>
264
+ )}
265
+ {filteredCaches.map((cache) => (
266
+ <TableRow key={cache.name}>
267
+ <TableCell className="font-medium">{cache.name}</TableCell>
268
+ <TableCell>{cache.itemCount}</TableCell>
269
+ <TableCell>{cache.ttl}</TableCell>
270
+ <TableCell className="text-right">
271
+ <div className="flex items-center justify-end gap-2">
272
+ <Button
273
+ size="sm"
274
+ variant="outline"
275
+ onClick={() => handleInspect(cache.name)}
276
+ disabled={!getCacheKeys || loading}
277
+ >
278
+ Inspect
279
+ </Button>
280
+ <Button
281
+ size="sm"
282
+ variant="secondary"
283
+ onClick={() => handleClearCache(cache.name)}
284
+ disabled={!clearCache || loading}
285
+ >
286
+ Clear
287
+ </Button>
288
+ </div>
289
+ </TableCell>
290
+ </TableRow>
291
+ ))}
292
+ </TableBody>
293
+ </Table>
294
+ </CardContent>
295
+ </Card>
296
+
297
+ {/* Inspect Dialog */}
298
+ <Dialog open={!!inspectCacheName} onOpenChange={(open) => !open && setInspectCacheName(null)}>
299
+ <DialogContent className="max-w-2xl max-h-[80vh] flex flex-col">
300
+ <DialogHeader>
301
+ <DialogTitle>Inspect Cache: {inspectCacheName}</DialogTitle>
302
+ <DialogDescription>
303
+ {inspecting ? "Loading..." : `${cacheKeys.length} items found`}
304
+ </DialogDescription>
305
+ </DialogHeader>
306
+
307
+ <div className="flex-1 overflow-hidden flex gap-4 min-h-0">
308
+ {/* Keys List */}
309
+ <div className="w-1/3 border-r pr-4 overflow-y-auto">
310
+ {cacheKeys.length === 0 ? (
311
+ <div className="text-sm text-muted-foreground py-4 text-center">No keys found</div>
312
+ ) : (
313
+ <div className="space-y-1">
314
+ {cacheKeys.map(key => (
315
+ <div
316
+ key={key}
317
+ className={`text-xs p-2 rounded cursor-pointer truncate ${inspectKey === key ? 'bg-primary/10 text-primary font-medium' : 'hover:bg-muted'}`}
318
+ onClick={() => handleViewValue(key)}
319
+ title={key}
320
+ >
321
+ {key}
322
+ </div>
323
+ ))}
324
+ </div>
325
+ )}
326
+ </div>
327
+
328
+ {/* Value View */}
329
+ <div className="w-2/3 overflow-y-auto bg-muted/30 p-4 rounded-md font-mono text-xs">
330
+ {inspectKey ? (
331
+ inspecting && keyValue === null ? (
332
+ <div className="text-muted-foreground">Loading value...</div>
333
+ ) : (
334
+ <pre className="whitespace-pre-wrap break-all">
335
+ {JSON.stringify(keyValue, null, 2)}
336
+ </pre>
337
+ )
338
+ ) : (
339
+ <div className="text-muted-foreground flex items-center justify-center h-full">
340
+ Select a key to view details
341
+ </div>
342
+ )}
343
+ </div>
344
+ </div>
345
+ </DialogContent>
346
+ </Dialog>
347
+ </div>
348
+ );
349
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./job-management";
2
+ export * from "./audit-log-page";
3
+ export * from "./cache-management";