@pattern-stack/frontend-patterns 0.0.3 → 0.0.5

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 (406) hide show
  1. package/dist/frontend-patterns.css +1 -1
  2. package/dist/index.es.js +1918 -3
  3. package/dist/index.es.js.map +1 -1
  4. package/dist/index.js +1917 -1
  5. package/dist/index.js.map +1 -1
  6. package/package.json +10 -5
  7. package/src/App.css +42 -0
  8. package/src/App.tsx +64 -0
  9. package/src/__tests__/README.md +221 -0
  10. package/src/__tests__/atoms/hooks/simple-hooks.test.ts +44 -0
  11. package/src/__tests__/atoms/ui/button.test.tsx +68 -0
  12. package/src/__tests__/atoms/utils/simple.test.ts +18 -0
  13. package/src/__tests__/atoms/utils/utils.test.ts +77 -0
  14. package/src/__tests__/features/auth/simple-auth.test.tsx +40 -0
  15. package/src/__tests__/molecules/layout/simple-layout.test.tsx +81 -0
  16. package/src/__tests__/organisms/showcase/simple-showcase.test.tsx +167 -0
  17. package/src/__tests__/setup.ts +51 -0
  18. package/src/__tests__/utils.tsx +123 -0
  19. package/src/atoms/composed/Accordion/Accordion.tsx +271 -0
  20. package/{dist/atoms/composed/Accordion/index.d.ts → src/atoms/composed/Accordion/index.ts} +1 -2
  21. package/src/atoms/composed/Alert/Alert.tsx +132 -0
  22. package/src/atoms/composed/Alert/index.ts +1 -0
  23. package/src/atoms/composed/Breadcrumb/Breadcrumb.tsx +83 -0
  24. package/src/atoms/composed/Breadcrumb/index.ts +1 -0
  25. package/src/atoms/composed/Chart/Chart.tsx +425 -0
  26. package/{dist/atoms/composed/Chart/index.d.ts → src/atoms/composed/Chart/index.ts} +1 -2
  27. package/src/atoms/composed/ColorSwatch/ColorSwatch.tsx +72 -0
  28. package/{dist/atoms/composed/ColorSwatch/index.d.ts → src/atoms/composed/ColorSwatch/index.ts} +1 -2
  29. package/src/atoms/composed/DarkModeToggle.tsx +66 -0
  30. package/src/atoms/composed/DataBadge/DataBadge.tsx +81 -0
  31. package/src/atoms/composed/DataBadge/index.ts +1 -0
  32. package/src/atoms/composed/DataTable/DataTable.tsx +394 -0
  33. package/src/atoms/composed/DataTable/TableCellWithTooltip.tsx +41 -0
  34. package/src/atoms/composed/DataTable/index.ts +2 -0
  35. package/src/atoms/composed/DateTimePicker/DateTimePicker.tsx +611 -0
  36. package/src/atoms/composed/DateTimePicker/index.ts +2 -0
  37. package/src/atoms/composed/DetailedCard/DetailedCard.tsx +181 -0
  38. package/src/atoms/composed/DetailedCard/index.ts +2 -0
  39. package/src/atoms/composed/EmptyState/EmptyState.tsx +90 -0
  40. package/src/atoms/composed/EmptyState/index.ts +1 -0
  41. package/src/atoms/composed/FileUpload/FileUpload.tsx +477 -0
  42. package/{dist/atoms/composed/FileUpload/index.d.ts → src/atoms/composed/FileUpload/index.ts} +1 -2
  43. package/src/atoms/composed/FormField/FormField.tsx +92 -0
  44. package/src/atoms/composed/FormField/index.ts +1 -0
  45. package/src/atoms/composed/GlobalSearch/GlobalSearch.tsx +37 -0
  46. package/src/atoms/composed/GlobalSearch/index.ts +1 -0
  47. package/src/atoms/composed/IconBadge/IconBadge.tsx +95 -0
  48. package/src/atoms/composed/IconBadge/index.ts +2 -0
  49. package/src/atoms/composed/Modal/Modal.tsx +223 -0
  50. package/src/atoms/composed/Modal/index.ts +2 -0
  51. package/src/atoms/composed/PaletteSwitcher.tsx +386 -0
  52. package/src/atoms/composed/ProgressBar/ProgressBar.tsx +116 -0
  53. package/{dist/atoms/composed/ProgressBar/index.d.ts → src/atoms/composed/ProgressBar/index.ts} +1 -2
  54. package/src/atoms/composed/SalesPanel/SalesPanel.tsx +116 -0
  55. package/src/atoms/composed/SalesPanel/index.ts +1 -0
  56. package/src/atoms/composed/SalesPanel/mockSalesData.ts +151 -0
  57. package/src/atoms/composed/StatCard/StatCard.tsx +219 -0
  58. package/src/atoms/composed/StatCard/index.ts +1 -0
  59. package/src/atoms/composed/StyleGuide.tsx +717 -0
  60. package/src/atoms/composed/Toast/Toast.tsx +219 -0
  61. package/{dist/atoms/composed/Toast/index.d.ts → src/atoms/composed/Toast/index.ts} +1 -2
  62. package/src/atoms/composed/Tooltip/Tooltip.tsx +213 -0
  63. package/src/atoms/composed/Tooltip/index.ts +1 -0
  64. package/src/atoms/composed/UserAvatar/UserAvatar.tsx +139 -0
  65. package/src/atoms/composed/UserAvatar/index.ts +1 -0
  66. package/src/atoms/composed/UserMenu/UserMenu.tsx +16 -0
  67. package/src/atoms/composed/UserMenu/index.ts +1 -0
  68. package/{dist/atoms/composed/index.d.ts → src/atoms/composed/index.ts} +7 -2
  69. package/src/atoms/hooks/useApi.ts +80 -0
  70. package/src/atoms/hooks/useHealth.ts +17 -0
  71. package/{dist/atoms/index.d.ts → src/atoms/index.ts} +6 -2
  72. package/src/atoms/services/api/client.ts +134 -0
  73. package/src/atoms/services/auth-service.ts +248 -0
  74. package/src/atoms/services/health.ts +15 -0
  75. package/{dist/atoms/services/index.d.ts → src/atoms/services/index.ts} +1 -2
  76. package/src/atoms/shared/config/constants.ts +17 -0
  77. package/src/atoms/shared/config/dashboard-sizes.ts +111 -0
  78. package/src/atoms/shared/config/environment.ts +10 -0
  79. package/src/atoms/shared/index.ts +4 -0
  80. package/src/atoms/shared/styles/color-palettes.css +566 -0
  81. package/src/atoms/types/auth.ts +62 -0
  82. package/src/atoms/types/entity-config.ts +127 -0
  83. package/{dist/atoms/types/generated.d.ts → src/atoms/types/generated.ts} +1 -1
  84. package/{dist/atoms/types/index.d.ts → src/atoms/types/index.ts} +2 -1
  85. package/{dist/atoms/types/loading.d.ts → src/atoms/types/loading.ts} +10 -8
  86. package/src/atoms/ui/Badge.tsx +30 -0
  87. package/src/atoms/ui/ErrorBoundary.tsx +59 -0
  88. package/src/atoms/ui/Select.tsx +53 -0
  89. package/src/atoms/ui/Switch.tsx +42 -0
  90. package/src/atoms/ui/Tabs.tsx +118 -0
  91. package/src/atoms/ui/avatar.tsx +48 -0
  92. package/src/atoms/ui/button.tsx +70 -0
  93. package/src/atoms/ui/card.tsx +76 -0
  94. package/src/atoms/ui/dropdown-menu.tsx +199 -0
  95. package/{dist/atoms/ui/index.d.ts → src/atoms/ui/index.ts} +27 -3
  96. package/src/atoms/ui/input.tsx +23 -0
  97. package/src/atoms/ui/label.tsx +23 -0
  98. package/src/atoms/ui/skeleton.tsx +13 -0
  99. package/src/atoms/ui/spinner.tsx +49 -0
  100. package/src/atoms/ui/table.tsx +116 -0
  101. package/src/atoms/utils/animations.ts +135 -0
  102. package/src/atoms/utils/metric-engine.ts +236 -0
  103. package/src/atoms/utils/tooltip-helpers.ts +140 -0
  104. package/src/atoms/utils/utils.ts +10 -0
  105. package/src/features/auth/components/LoginForm.tsx +168 -0
  106. package/src/features/auth/components/LogoutButton.tsx +19 -0
  107. package/src/features/auth/components/ProtectedRoute.tsx +60 -0
  108. package/{dist/features/auth/components/index.d.ts → src/features/auth/components/index.ts} +1 -1
  109. package/src/features/auth/hooks/index.ts +2 -0
  110. package/src/features/auth/hooks/useAuth.tsx +205 -0
  111. package/src/features/auth/hooks/usePermissions.ts +35 -0
  112. package/src/features/auth/index.ts +2 -0
  113. package/src/features/index.ts +2 -0
  114. package/src/index.css +704 -0
  115. package/{dist/index.d.ts → src/index.ts} +5 -2
  116. package/src/main.tsx +48 -0
  117. package/src/molecules/.gitkeep +0 -0
  118. package/src/molecules/forms/FormGroup.tsx +75 -0
  119. package/src/molecules/forms/SearchInput.tsx +259 -0
  120. package/src/molecules/forms/index.ts +4 -0
  121. package/src/molecules/index.ts +4 -0
  122. package/src/molecules/layout/AppHeader/AppHeader.tsx +42 -0
  123. package/src/molecules/layout/AppHeader/index.ts +1 -0
  124. package/src/molecules/layout/AppLayout.tsx +29 -0
  125. package/src/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.tsx +42 -0
  126. package/src/molecules/layout/DashboardWithSidePanel/index.ts +1 -0
  127. package/src/molecules/layout/PageTemplate.tsx +87 -0
  128. package/src/molecules/layout/SectionHeader/SectionHeader.tsx +87 -0
  129. package/{dist/molecules/layout/SectionHeader/index.d.ts → src/molecules/layout/SectionHeader/index.ts} +1 -2
  130. package/src/molecules/layout/ShowcaseSection.tsx +57 -0
  131. package/src/molecules/layout/Sidebar.tsx +152 -0
  132. package/src/molecules/layout/SidebarButton/SidebarButton.tsx +99 -0
  133. package/src/molecules/layout/SidebarButton/index.ts +1 -0
  134. package/src/molecules/layout/SidebarContext.tsx +31 -0
  135. package/{dist/molecules/layout/index.d.ts → src/molecules/layout/index.ts} +2 -2
  136. package/src/molecules/navigation/NavMenu.tsx +188 -0
  137. package/src/molecules/navigation/Pagination.tsx +172 -0
  138. package/src/molecules/navigation/index.ts +4 -0
  139. package/src/organisms/entity/CategoryBreakdownPanel.tsx +427 -0
  140. package/src/organisms/entity/EntityListPanel.tsx +339 -0
  141. package/src/organisms/entity/MetricsOverviewPanel.tsx +236 -0
  142. package/src/organisms/entity/TrendAnalysisPanel.tsx +337 -0
  143. package/src/organisms/entity/index.ts +4 -0
  144. package/src/organisms/index.ts +8 -0
  145. package/src/organisms/showcase/ComponentShowcasePage.tsx +2496 -0
  146. package/src/organisms/showcase/index.ts +1 -0
  147. package/src/pages/AdminShowcase/AdminCRUDShowcase.tsx +242 -0
  148. package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +173 -0
  149. package/src/pages/AdminShowcase/AdminDetailShowcase.tsx +385 -0
  150. package/src/pages/AdminShowcase/SalesPerformanceDashboard.tsx +158 -0
  151. package/src/pages/AdminShowcase/index.tsx +4 -0
  152. package/src/pages/ComponentShowcase/BadgesShowcase.tsx +188 -0
  153. package/src/pages/ComponentShowcase/CardsShowcase.tsx +392 -0
  154. package/src/pages/ComponentShowcase/PalettesShowcase.tsx +207 -0
  155. package/src/pages/ComponentShowcase/StatesShowcase.tsx +485 -0
  156. package/src/pages/ComponentShowcase/TablesShowcase.tsx +134 -0
  157. package/src/pages/ComponentShowcase/TypographyShowcase.tsx +255 -0
  158. package/src/pages/ComponentShowcase/index.tsx +188 -0
  159. package/src/pages/EntityShowcase/EntityManagementShowcase.tsx +137 -0
  160. package/src/pages/EntityShowcase/EntityPerformanceShowcase.tsx +117 -0
  161. package/src/pages/EntityShowcase/index.ts +2 -0
  162. package/src/pages/EntityTemplateExample.tsx +229 -0
  163. package/src/pages/TestEntityTemplate.tsx +40 -0
  164. package/src/pages/index.ts +3 -0
  165. package/src/templates/AuthTemplate.tsx +216 -0
  166. package/src/templates/ComponentShowcaseTemplate.tsx +173 -0
  167. package/src/templates/DashboardTemplate.tsx +232 -0
  168. package/src/templates/DataTemplate.tsx +319 -0
  169. package/src/templates/admin/AdminCRUDTemplate.tsx +630 -0
  170. package/src/templates/admin/AdminDashboardTemplate.tsx +351 -0
  171. package/src/templates/admin/AdminDetailTemplate.tsx +563 -0
  172. package/src/templates/admin/index.ts +29 -0
  173. package/src/templates/entity/EntityManagementTemplate.tsx +430 -0
  174. package/src/templates/entity/EntityPerformanceDashboardTemplate.tsx +277 -0
  175. package/src/templates/entity/configs/financial-config.ts +141 -0
  176. package/src/templates/entity/configs/index.ts +1 -0
  177. package/src/templates/entity/index.ts +3 -0
  178. package/src/templates/factory.tsx +169 -0
  179. package/src/templates/financial/FinancialDashboardTemplate.tsx +326 -0
  180. package/src/templates/index.ts +40 -0
  181. package/src/vite-env.d.ts +1 -0
  182. package/dist/atoms/composed/Accordion/Accordion.d.ts +0 -20
  183. package/dist/atoms/composed/Accordion/Accordion.d.ts.map +0 -1
  184. package/dist/atoms/composed/Accordion/index.d.ts.map +0 -1
  185. package/dist/atoms/composed/Alert/Alert.d.ts +0 -25
  186. package/dist/atoms/composed/Alert/Alert.d.ts.map +0 -1
  187. package/dist/atoms/composed/Alert/index.d.ts +0 -2
  188. package/dist/atoms/composed/Alert/index.d.ts.map +0 -1
  189. package/dist/atoms/composed/Breadcrumb/Breadcrumb.d.ts +0 -17
  190. package/dist/atoms/composed/Breadcrumb/Breadcrumb.d.ts.map +0 -1
  191. package/dist/atoms/composed/Breadcrumb/index.d.ts +0 -2
  192. package/dist/atoms/composed/Breadcrumb/index.d.ts.map +0 -1
  193. package/dist/atoms/composed/Chart/Chart.d.ts +0 -37
  194. package/dist/atoms/composed/Chart/Chart.d.ts.map +0 -1
  195. package/dist/atoms/composed/Chart/index.d.ts.map +0 -1
  196. package/dist/atoms/composed/ColorSwatch/ColorSwatch.d.ts +0 -19
  197. package/dist/atoms/composed/ColorSwatch/ColorSwatch.d.ts.map +0 -1
  198. package/dist/atoms/composed/ColorSwatch/index.d.ts.map +0 -1
  199. package/dist/atoms/composed/DarkModeToggle.d.ts +0 -4
  200. package/dist/atoms/composed/DarkModeToggle.d.ts.map +0 -1
  201. package/dist/atoms/composed/DataBadge/DataBadge.d.ts +0 -13
  202. package/dist/atoms/composed/DataBadge/DataBadge.d.ts.map +0 -1
  203. package/dist/atoms/composed/DataBadge/index.d.ts +0 -2
  204. package/dist/atoms/composed/DataBadge/index.d.ts.map +0 -1
  205. package/dist/atoms/composed/DataTable/DataTable.d.ts +0 -28
  206. package/dist/atoms/composed/DataTable/DataTable.d.ts.map +0 -1
  207. package/dist/atoms/composed/DataTable/TableCellWithTooltip.d.ts +0 -10
  208. package/dist/atoms/composed/DataTable/TableCellWithTooltip.d.ts.map +0 -1
  209. package/dist/atoms/composed/DataTable/index.d.ts +0 -3
  210. package/dist/atoms/composed/DataTable/index.d.ts.map +0 -1
  211. package/dist/atoms/composed/DateTimePicker/DateTimePicker.d.ts +0 -45
  212. package/dist/atoms/composed/DateTimePicker/DateTimePicker.d.ts.map +0 -1
  213. package/dist/atoms/composed/DateTimePicker/index.d.ts +0 -3
  214. package/dist/atoms/composed/DateTimePicker/index.d.ts.map +0 -1
  215. package/dist/atoms/composed/DetailedCard/DetailedCard.d.ts +0 -30
  216. package/dist/atoms/composed/DetailedCard/DetailedCard.d.ts.map +0 -1
  217. package/dist/atoms/composed/DetailedCard/index.d.ts +0 -3
  218. package/dist/atoms/composed/DetailedCard/index.d.ts.map +0 -1
  219. package/dist/atoms/composed/EmptyState/EmptyState.d.ts +0 -18
  220. package/dist/atoms/composed/EmptyState/EmptyState.d.ts.map +0 -1
  221. package/dist/atoms/composed/EmptyState/index.d.ts +0 -2
  222. package/dist/atoms/composed/EmptyState/index.d.ts.map +0 -1
  223. package/dist/atoms/composed/FileUpload/FileUpload.d.ts +0 -46
  224. package/dist/atoms/composed/FileUpload/FileUpload.d.ts.map +0 -1
  225. package/dist/atoms/composed/FileUpload/index.d.ts.map +0 -1
  226. package/dist/atoms/composed/FormField/FormField.d.ts +0 -23
  227. package/dist/atoms/composed/FormField/FormField.d.ts.map +0 -1
  228. package/dist/atoms/composed/FormField/index.d.ts +0 -2
  229. package/dist/atoms/composed/FormField/index.d.ts.map +0 -1
  230. package/dist/atoms/composed/GlobalSearch/GlobalSearch.d.ts +0 -8
  231. package/dist/atoms/composed/GlobalSearch/GlobalSearch.d.ts.map +0 -1
  232. package/dist/atoms/composed/GlobalSearch/index.d.ts +0 -2
  233. package/dist/atoms/composed/GlobalSearch/index.d.ts.map +0 -1
  234. package/dist/atoms/composed/IconBadge/IconBadge.d.ts +0 -16
  235. package/dist/atoms/composed/IconBadge/IconBadge.d.ts.map +0 -1
  236. package/dist/atoms/composed/IconBadge/index.d.ts +0 -3
  237. package/dist/atoms/composed/IconBadge/index.d.ts.map +0 -1
  238. package/dist/atoms/composed/Modal/Modal.d.ts +0 -18
  239. package/dist/atoms/composed/Modal/Modal.d.ts.map +0 -1
  240. package/dist/atoms/composed/Modal/index.d.ts +0 -3
  241. package/dist/atoms/composed/Modal/index.d.ts.map +0 -1
  242. package/dist/atoms/composed/PaletteSwitcher.d.ts +0 -7
  243. package/dist/atoms/composed/PaletteSwitcher.d.ts.map +0 -1
  244. package/dist/atoms/composed/ProgressBar/ProgressBar.d.ts +0 -25
  245. package/dist/atoms/composed/ProgressBar/ProgressBar.d.ts.map +0 -1
  246. package/dist/atoms/composed/ProgressBar/index.d.ts.map +0 -1
  247. package/dist/atoms/composed/StatCard/StatCard.d.ts +0 -21
  248. package/dist/atoms/composed/StatCard/StatCard.d.ts.map +0 -1
  249. package/dist/atoms/composed/StatCard/index.d.ts +0 -2
  250. package/dist/atoms/composed/StatCard/index.d.ts.map +0 -1
  251. package/dist/atoms/composed/StyleGuide.d.ts +0 -3
  252. package/dist/atoms/composed/StyleGuide.d.ts.map +0 -1
  253. package/dist/atoms/composed/Toast/Toast.d.ts +0 -40
  254. package/dist/atoms/composed/Toast/Toast.d.ts.map +0 -1
  255. package/dist/atoms/composed/Toast/index.d.ts.map +0 -1
  256. package/dist/atoms/composed/Tooltip/Tooltip.d.ts +0 -16
  257. package/dist/atoms/composed/Tooltip/Tooltip.d.ts.map +0 -1
  258. package/dist/atoms/composed/Tooltip/index.d.ts +0 -2
  259. package/dist/atoms/composed/Tooltip/index.d.ts.map +0 -1
  260. package/dist/atoms/composed/UserAvatar/UserAvatar.d.ts +0 -8
  261. package/dist/atoms/composed/UserAvatar/UserAvatar.d.ts.map +0 -1
  262. package/dist/atoms/composed/UserAvatar/index.d.ts +0 -2
  263. package/dist/atoms/composed/UserAvatar/index.d.ts.map +0 -1
  264. package/dist/atoms/composed/UserMenu/UserMenu.d.ts +0 -8
  265. package/dist/atoms/composed/UserMenu/UserMenu.d.ts.map +0 -1
  266. package/dist/atoms/composed/UserMenu/index.d.ts +0 -2
  267. package/dist/atoms/composed/UserMenu/index.d.ts.map +0 -1
  268. package/dist/atoms/composed/index.d.ts.map +0 -1
  269. package/dist/atoms/hooks/useApi.d.ts +0 -25
  270. package/dist/atoms/hooks/useApi.d.ts.map +0 -1
  271. package/dist/atoms/hooks/useHealth.d.ts +0 -19
  272. package/dist/atoms/hooks/useHealth.d.ts.map +0 -1
  273. package/dist/atoms/index.d.ts.map +0 -1
  274. package/dist/atoms/services/api/client.d.ts +0 -20
  275. package/dist/atoms/services/api/client.d.ts.map +0 -1
  276. package/dist/atoms/services/auth-service.d.ts +0 -24
  277. package/dist/atoms/services/auth-service.d.ts.map +0 -1
  278. package/dist/atoms/services/health.d.ts +0 -7
  279. package/dist/atoms/services/health.d.ts.map +0 -1
  280. package/dist/atoms/services/index.d.ts.map +0 -1
  281. package/dist/atoms/shared/config/constants.d.ts +0 -15
  282. package/dist/atoms/shared/config/constants.d.ts.map +0 -1
  283. package/dist/atoms/shared/config/dashboard-sizes.d.ts +0 -83
  284. package/dist/atoms/shared/config/dashboard-sizes.d.ts.map +0 -1
  285. package/dist/atoms/shared/config/environment.d.ts +0 -10
  286. package/dist/atoms/shared/config/environment.d.ts.map +0 -1
  287. package/dist/atoms/shared/index.d.ts +0 -4
  288. package/dist/atoms/shared/index.d.ts.map +0 -1
  289. package/dist/atoms/types/auth.d.ts +0 -56
  290. package/dist/atoms/types/auth.d.ts.map +0 -1
  291. package/dist/atoms/types/generated.d.ts.map +0 -1
  292. package/dist/atoms/types/index.d.ts.map +0 -1
  293. package/dist/atoms/types/loading.d.ts.map +0 -1
  294. package/dist/atoms/ui/Badge.d.ts +0 -10
  295. package/dist/atoms/ui/Badge.d.ts.map +0 -1
  296. package/dist/atoms/ui/ErrorBoundary.d.ts +0 -18
  297. package/dist/atoms/ui/ErrorBoundary.d.ts.map +0 -1
  298. package/dist/atoms/ui/Select.d.ts +0 -28
  299. package/dist/atoms/ui/Select.d.ts.map +0 -1
  300. package/dist/atoms/ui/Switch.d.ts +0 -9
  301. package/dist/atoms/ui/Switch.d.ts.map +0 -1
  302. package/dist/atoms/ui/Tabs.d.ts +0 -30
  303. package/dist/atoms/ui/Tabs.d.ts.map +0 -1
  304. package/dist/atoms/ui/avatar.d.ts +0 -7
  305. package/dist/atoms/ui/avatar.d.ts.map +0 -1
  306. package/dist/atoms/ui/button.d.ts +0 -14
  307. package/dist/atoms/ui/button.d.ts.map +0 -1
  308. package/dist/atoms/ui/card.d.ts +0 -12
  309. package/dist/atoms/ui/card.d.ts.map +0 -1
  310. package/dist/atoms/ui/dropdown-menu.d.ts +0 -28
  311. package/dist/atoms/ui/dropdown-menu.d.ts.map +0 -1
  312. package/dist/atoms/ui/index.d.ts.map +0 -1
  313. package/dist/atoms/ui/input.d.ts +0 -5
  314. package/dist/atoms/ui/input.d.ts.map +0 -1
  315. package/dist/atoms/ui/label.d.ts +0 -6
  316. package/dist/atoms/ui/label.d.ts.map +0 -1
  317. package/dist/atoms/ui/skeleton.d.ts +0 -3
  318. package/dist/atoms/ui/skeleton.d.ts.map +0 -1
  319. package/dist/atoms/ui/spinner.d.ts +0 -14
  320. package/dist/atoms/ui/spinner.d.ts.map +0 -1
  321. package/dist/atoms/ui/table.d.ts +0 -11
  322. package/dist/atoms/ui/table.d.ts.map +0 -1
  323. package/dist/atoms/utils/animations.d.ts +0 -65
  324. package/dist/atoms/utils/animations.d.ts.map +0 -1
  325. package/dist/atoms/utils/tooltip-helpers.d.ts +0 -71
  326. package/dist/atoms/utils/tooltip-helpers.d.ts.map +0 -1
  327. package/dist/atoms/utils/utils.d.ts +0 -4
  328. package/dist/atoms/utils/utils.d.ts.map +0 -1
  329. package/dist/features/auth/components/LoginForm.d.ts +0 -2
  330. package/dist/features/auth/components/LoginForm.d.ts.map +0 -1
  331. package/dist/features/auth/components/LogoutButton.d.ts +0 -2
  332. package/dist/features/auth/components/LogoutButton.d.ts.map +0 -1
  333. package/dist/features/auth/components/ProtectedRoute.d.ts +0 -10
  334. package/dist/features/auth/components/ProtectedRoute.d.ts.map +0 -1
  335. package/dist/features/auth/components/index.d.ts.map +0 -1
  336. package/dist/features/auth/hooks/index.d.ts +0 -3
  337. package/dist/features/auth/hooks/index.d.ts.map +0 -1
  338. package/dist/features/auth/hooks/useAuth.d.ts +0 -10
  339. package/dist/features/auth/hooks/useAuth.d.ts.map +0 -1
  340. package/dist/features/auth/hooks/usePermissions.d.ts +0 -13
  341. package/dist/features/auth/hooks/usePermissions.d.ts.map +0 -1
  342. package/dist/features/auth/index.d.ts +0 -3
  343. package/dist/features/auth/index.d.ts.map +0 -1
  344. package/dist/features/index.d.ts +0 -2
  345. package/dist/features/index.d.ts.map +0 -1
  346. package/dist/index.d.ts.map +0 -1
  347. package/dist/molecules/forms/FormGroup.d.ts +0 -17
  348. package/dist/molecules/forms/FormGroup.d.ts.map +0 -1
  349. package/dist/molecules/forms/SearchInput.d.ts +0 -36
  350. package/dist/molecules/forms/SearchInput.d.ts.map +0 -1
  351. package/dist/molecules/forms/index.d.ts +0 -3
  352. package/dist/molecules/forms/index.d.ts.map +0 -1
  353. package/dist/molecules/index.d.ts +0 -4
  354. package/dist/molecules/index.d.ts.map +0 -1
  355. package/dist/molecules/layout/AppHeader/AppHeader.d.ts +0 -7
  356. package/dist/molecules/layout/AppHeader/AppHeader.d.ts.map +0 -1
  357. package/dist/molecules/layout/AppHeader/index.d.ts +0 -2
  358. package/dist/molecules/layout/AppHeader/index.d.ts.map +0 -1
  359. package/dist/molecules/layout/AppLayout.d.ts +0 -2
  360. package/dist/molecules/layout/AppLayout.d.ts.map +0 -1
  361. package/dist/molecules/layout/PageTemplate.d.ts +0 -19
  362. package/dist/molecules/layout/PageTemplate.d.ts.map +0 -1
  363. package/dist/molecules/layout/SectionHeader/SectionHeader.d.ts +0 -24
  364. package/dist/molecules/layout/SectionHeader/SectionHeader.d.ts.map +0 -1
  365. package/dist/molecules/layout/SectionHeader/index.d.ts.map +0 -1
  366. package/dist/molecules/layout/ShowcaseSection.d.ts +0 -22
  367. package/dist/molecules/layout/ShowcaseSection.d.ts.map +0 -1
  368. package/dist/molecules/layout/Sidebar.d.ts +0 -6
  369. package/dist/molecules/layout/Sidebar.d.ts.map +0 -1
  370. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts +0 -13
  371. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts.map +0 -1
  372. package/dist/molecules/layout/SidebarButton/index.d.ts +0 -2
  373. package/dist/molecules/layout/SidebarButton/index.d.ts.map +0 -1
  374. package/dist/molecules/layout/SidebarContext.d.ts +0 -12
  375. package/dist/molecules/layout/SidebarContext.d.ts.map +0 -1
  376. package/dist/molecules/layout/index.d.ts.map +0 -1
  377. package/dist/molecules/navigation/NavMenu.d.ts +0 -20
  378. package/dist/molecules/navigation/NavMenu.d.ts.map +0 -1
  379. package/dist/molecules/navigation/Pagination.d.ts +0 -14
  380. package/dist/molecules/navigation/Pagination.d.ts.map +0 -1
  381. package/dist/molecules/navigation/index.d.ts +0 -3
  382. package/dist/molecules/navigation/index.d.ts.map +0 -1
  383. package/dist/organisms/index.d.ts +0 -2
  384. package/dist/organisms/index.d.ts.map +0 -1
  385. package/dist/organisms/showcase/ComponentShowcasePage.d.ts +0 -3
  386. package/dist/organisms/showcase/ComponentShowcasePage.d.ts.map +0 -1
  387. package/dist/templates/AuthTemplate.d.ts +0 -68
  388. package/dist/templates/AuthTemplate.d.ts.map +0 -1
  389. package/dist/templates/ComponentShowcaseTemplate.d.ts +0 -53
  390. package/dist/templates/ComponentShowcaseTemplate.d.ts.map +0 -1
  391. package/dist/templates/DashboardTemplate.d.ts +0 -62
  392. package/dist/templates/DashboardTemplate.d.ts.map +0 -1
  393. package/dist/templates/DataTemplate.d.ts +0 -78
  394. package/dist/templates/DataTemplate.d.ts.map +0 -1
  395. package/dist/templates/admin/AdminCRUDTemplate.d.ts +0 -105
  396. package/dist/templates/admin/AdminCRUDTemplate.d.ts.map +0 -1
  397. package/dist/templates/admin/AdminDashboardTemplate.d.ts +0 -89
  398. package/dist/templates/admin/AdminDashboardTemplate.d.ts.map +0 -1
  399. package/dist/templates/admin/AdminDetailTemplate.d.ts +0 -132
  400. package/dist/templates/admin/AdminDetailTemplate.d.ts.map +0 -1
  401. package/dist/templates/admin/index.d.ts +0 -4
  402. package/dist/templates/admin/index.d.ts.map +0 -1
  403. package/dist/templates/factory.d.ts +0 -28
  404. package/dist/templates/factory.d.ts.map +0 -1
  405. package/dist/templates/index.d.ts +0 -7
  406. package/dist/templates/index.d.ts.map +0 -1
@@ -0,0 +1,430 @@
1
+ import React, { useState } from 'react';
2
+ import { AppLayout } from '../../molecules/layout/AppLayout';
3
+ import { PageTemplate } from '../../molecules/layout/PageTemplate';
4
+ import { SectionHeader } from '../../molecules/layout/SectionHeader';
5
+ import { EntityListPanel } from '../../organisms/entity';
6
+ import { Modal } from '../../atoms/composed/Modal';
7
+ import { Button } from '../../atoms/ui/button';
8
+ import { Card } from '../../atoms/ui/card';
9
+ import { Badge } from '../../atoms/ui/Badge';
10
+ import type { EntityTemplateConfig, EntityData, ActionConfig } from '../../atoms/types';
11
+ import { cn } from '../../atoms/utils/utils';
12
+ import { Plus, Trash2, Filter, Download } from 'lucide-react';
13
+
14
+ export interface EntityManagementTemplateProps<T extends EntityData> {
15
+ config: EntityTemplateConfig<T>;
16
+ data: T[];
17
+ isLoading?: boolean;
18
+ className?: string;
19
+
20
+ // View configuration
21
+ defaultView?: 'list' | 'grid' | 'cards';
22
+ enableViews?: boolean;
23
+ enableSearch?: boolean;
24
+ enableFiltering?: boolean;
25
+ enableBulkActions?: boolean;
26
+ enableExport?: boolean;
27
+ pageSize?: number;
28
+
29
+ // CRUD operations
30
+ onCreate?: (item: Partial<T>) => Promise<T> | T;
31
+ onUpdate?: (id: string | number, item: Partial<T>) => Promise<T> | T;
32
+ onDelete?: (id: string | number) => Promise<void> | void;
33
+ onBulkDelete?: (ids: (string | number)[]) => Promise<void> | void;
34
+ onView?: (item: T) => void;
35
+
36
+ // Extension points - Render Props
37
+ renderCreateForm?: (onSubmit: (item: Partial<T>) => void, onCancel: () => void) => React.ReactNode;
38
+ renderEditForm?: (item: T, onSubmit: (item: Partial<T>) => void, onCancel: () => void) => React.ReactNode;
39
+ renderDetailView?: (item: T, onEdit: () => void, onClose: () => void) => React.ReactNode;
40
+ renderCustomActions?: (item?: T) => React.ReactNode;
41
+ renderEmptyState?: () => React.ReactNode;
42
+ renderFilterPanel?: (onFilter: (filters: Record<string, unknown>) => void) => React.ReactNode;
43
+
44
+ // Extension points - Slots
45
+ headerSlot?: React.ReactNode;
46
+ footerSlot?: React.ReactNode;
47
+ toolbarSlot?: React.ReactNode;
48
+ listHeaderSlot?: React.ReactNode;
49
+ listFooterSlot?: React.ReactNode;
50
+
51
+ // Event handlers
52
+ onRefresh?: () => void;
53
+ onFilter?: (filters: Record<string, unknown>) => void;
54
+ onExport?: (data: T[], format: 'csv' | 'json') => void;
55
+ onSelectionChange?: (selectedItems: T[]) => void;
56
+ }
57
+
58
+ export const EntityManagementTemplate = <T extends EntityData>({
59
+ config,
60
+ data,
61
+ isLoading = false,
62
+ className,
63
+ enableSearch = true,
64
+ enableFiltering = true,
65
+ enableBulkActions = true,
66
+ enableExport = true,
67
+ pageSize = 10,
68
+ onCreate,
69
+ onUpdate,
70
+ onDelete,
71
+ onBulkDelete,
72
+ onView,
73
+ renderCreateForm,
74
+ renderEditForm,
75
+ renderDetailView,
76
+ renderCustomActions,
77
+ renderEmptyState,
78
+ renderFilterPanel,
79
+ headerSlot,
80
+ footerSlot,
81
+ toolbarSlot,
82
+ listHeaderSlot,
83
+ listFooterSlot,
84
+ onRefresh,
85
+ onFilter,
86
+ onExport
87
+ }: EntityManagementTemplateProps<T>) => {
88
+
89
+ const [showCreateModal, setShowCreateModal] = useState(false);
90
+ const [showEditModal, setShowEditModal] = useState(false);
91
+ const [showDetailModal, setShowDetailModal] = useState(false);
92
+ const [showFilterPanel, setShowFilterPanel] = useState(false);
93
+ const [selectedItem, setSelectedItem] = useState<T | null>(null);
94
+ const [selectedItems, setSelectedItems] = useState<T[]>([]);
95
+
96
+ const handleCreate = async (item: Partial<T>) => {
97
+ if (onCreate) {
98
+ try {
99
+ await onCreate(item);
100
+ setShowCreateModal(false);
101
+ onRefresh?.();
102
+ } catch (error) {
103
+ console.error('Create failed:', error);
104
+ }
105
+ }
106
+ };
107
+
108
+ const handleUpdate = async (item: Partial<T>) => {
109
+ if (onUpdate && selectedItem) {
110
+ try {
111
+ await onUpdate(selectedItem.id, item);
112
+ setShowEditModal(false);
113
+ setSelectedItem(null);
114
+ onRefresh?.();
115
+ } catch (error) {
116
+ console.error('Update failed:', error);
117
+ }
118
+ }
119
+ };
120
+
121
+
122
+ const handleBulkDelete = async () => {
123
+ if (onBulkDelete && selectedItems.length > 0 && confirm(`Are you sure you want to delete ${selectedItems.length} ${config.display.title.toLowerCase()}?`)) {
124
+ try {
125
+ const ids = selectedItems.map(item => item.id);
126
+ await onBulkDelete(ids);
127
+ setSelectedItems([]);
128
+ onRefresh?.();
129
+ } catch (error) {
130
+ console.error('Bulk delete failed:', error);
131
+ }
132
+ }
133
+ };
134
+
135
+ const handleView = (item: T) => {
136
+ if (onView) {
137
+ onView(item);
138
+ } else {
139
+ setSelectedItem(item);
140
+ setShowDetailModal(true);
141
+ }
142
+ };
143
+
144
+ const handleEdit = (item: T) => {
145
+ setSelectedItem(item);
146
+ setShowEditModal(true);
147
+ };
148
+
149
+ const handleRowClick = (item: T) => {
150
+ handleView(item);
151
+ };
152
+
153
+ const handleAction = (action: ActionConfig, selectedItems: T[]) => {
154
+ action.onClick({ selectedItems, config });
155
+ };
156
+
157
+ const generateDefaultActions = (): ActionConfig[] => {
158
+ const actions: ActionConfig[] = [];
159
+
160
+ if (onCreate) {
161
+ actions.push({
162
+ label: `Add ${config.display.title.slice(0, -1)}`,
163
+ type: 'primary',
164
+ icon: Plus,
165
+ onClick: () => setShowCreateModal(true)
166
+ });
167
+ }
168
+
169
+ return actions;
170
+ };
171
+
172
+
173
+ const renderPageHeader = () => {
174
+ const actions = [
175
+ ...generateDefaultActions(),
176
+ ...(config.actions || [])
177
+ ];
178
+
179
+ return (
180
+ <SectionHeader
181
+ title={config.display.title}
182
+ description={config.display.description}
183
+ category={config.display.category}
184
+ actions={
185
+ <div className="flex items-center gap-2">
186
+ {renderCustomActions && renderCustomActions()}
187
+
188
+ {enableFiltering && (
189
+ <Button
190
+ variant="outline"
191
+ size="sm"
192
+ onClick={() => setShowFilterPanel(!showFilterPanel)}
193
+ className={cn(showFilterPanel && "bg-muted")}
194
+ >
195
+ <Filter className="w-4 h-4 mr-2" />
196
+ Filters
197
+ </Button>
198
+ )}
199
+
200
+ {enableExport && (
201
+ <Button
202
+ variant="outline"
203
+ size="sm"
204
+ onClick={() => onExport?.(selectedItems.length > 0 ? selectedItems : data, 'csv')}
205
+ disabled={data.length === 0}
206
+ >
207
+ <Download className="w-4 h-4 mr-2" />
208
+ Export
209
+ </Button>
210
+ )}
211
+
212
+ {actions.map(action => (
213
+ <Button
214
+ key={action.label}
215
+ variant={action.type === 'primary' ? 'default' : 'outline'}
216
+ size="sm"
217
+ onClick={() => action.onClick({ data, config })}
218
+ >
219
+ {action.icon && <action.icon className="w-4 h-4 mr-2" />}
220
+ {action.label}
221
+ </Button>
222
+ ))}
223
+ </div>
224
+ }
225
+ />
226
+ );
227
+ };
228
+
229
+ const renderToolbar = () => {
230
+ if (selectedItems.length === 0) return null;
231
+
232
+ return (
233
+ <div className="bg-muted/50 p-4 rounded-lg mb-4">
234
+ <div className="flex items-center justify-between">
235
+ <div className="flex items-center gap-2">
236
+ <Badge variant="secondary">
237
+ {selectedItems.length} selected
238
+ </Badge>
239
+ <Button
240
+ variant="ghost"
241
+ size="sm"
242
+ onClick={() => setSelectedItems([])}
243
+ >
244
+ Clear selection
245
+ </Button>
246
+ </div>
247
+
248
+ <div className="flex items-center gap-2">
249
+ {onBulkDelete && (
250
+ <Button
251
+ variant="destructive"
252
+ size="sm"
253
+ onClick={handleBulkDelete}
254
+ >
255
+ <Trash2 className="w-4 h-4 mr-2" />
256
+ Delete Selected
257
+ </Button>
258
+ )}
259
+
260
+ {enableExport && (
261
+ <Button
262
+ variant="outline"
263
+ size="sm"
264
+ onClick={() => onExport?.(selectedItems, 'csv')}
265
+ >
266
+ <Download className="w-4 h-4 mr-2" />
267
+ Export Selected
268
+ </Button>
269
+ )}
270
+ </div>
271
+ </div>
272
+ </div>
273
+ );
274
+ };
275
+
276
+ const renderFilterPanelSection = () => {
277
+ if (!showFilterPanel) return null;
278
+
279
+ return (
280
+ <Card className="p-4 mb-4">
281
+ {renderFilterPanel ? (
282
+ renderFilterPanel(onFilter || (() => {}))
283
+ ) : (
284
+ <div className="text-center text-muted-foreground py-4">
285
+ Filter functionality not implemented yet
286
+ </div>
287
+ )}
288
+ </Card>
289
+ );
290
+ };
291
+
292
+ const renderCreateModal = () => {
293
+ if (!showCreateModal) return null;
294
+
295
+ return (
296
+ <Modal
297
+ isOpen={showCreateModal}
298
+ onClose={() => setShowCreateModal(false)}
299
+ title={`Create ${config.display.title.slice(0, -1)}`}
300
+ category={config.display.category}
301
+ >
302
+ {renderCreateForm ? (
303
+ renderCreateForm(handleCreate, () => setShowCreateModal(false))
304
+ ) : (
305
+ <div className="p-6 text-center text-muted-foreground">
306
+ Create form not implemented yet
307
+ </div>
308
+ )}
309
+ </Modal>
310
+ );
311
+ };
312
+
313
+ const renderEditModal = () => {
314
+ if (!showEditModal || !selectedItem) return null;
315
+
316
+ return (
317
+ <Modal
318
+ isOpen={showEditModal}
319
+ onClose={() => {
320
+ setShowEditModal(false);
321
+ setSelectedItem(null);
322
+ }}
323
+ title={`Edit ${config.display.title.slice(0, -1)}`}
324
+ category={config.display.category}
325
+ >
326
+ {renderEditForm ? (
327
+ renderEditForm(
328
+ selectedItem,
329
+ handleUpdate,
330
+ () => {
331
+ setShowEditModal(false);
332
+ setSelectedItem(null);
333
+ }
334
+ )
335
+ ) : (
336
+ <div className="p-6 text-center text-muted-foreground">
337
+ Edit form not implemented yet
338
+ </div>
339
+ )}
340
+ </Modal>
341
+ );
342
+ };
343
+
344
+ const renderDetailModal = () => {
345
+ if (!showDetailModal || !selectedItem) return null;
346
+
347
+ return (
348
+ <Modal
349
+ isOpen={showDetailModal}
350
+ onClose={() => {
351
+ setShowDetailModal(false);
352
+ setSelectedItem(null);
353
+ }}
354
+ title={`${config.display.title.slice(0, -1)} Details`}
355
+ category={config.display.category}
356
+ size="large"
357
+ >
358
+ {renderDetailView ? (
359
+ renderDetailView(
360
+ selectedItem,
361
+ () => {
362
+ setShowDetailModal(false);
363
+ handleEdit(selectedItem);
364
+ },
365
+ () => {
366
+ setShowDetailModal(false);
367
+ setSelectedItem(null);
368
+ }
369
+ )
370
+ ) : (
371
+ <div className="p-6">
372
+ <div className="space-y-4">
373
+ {Object.entries(selectedItem).map(([key, value]) => (
374
+ <div key={key} className="flex justify-between">
375
+ <span className="font-medium capitalize">{key}:</span>
376
+ <span>{value?.toString() || '-'}</span>
377
+ </div>
378
+ ))}
379
+ </div>
380
+ </div>
381
+ )}
382
+ </Modal>
383
+ );
384
+ };
385
+
386
+ return (
387
+ <AppLayout>
388
+ <PageTemplate
389
+ className={cn('container mx-auto px-4 py-6', className)}
390
+ data-component-name="EntityManagementTemplate"
391
+ >
392
+ {headerSlot}
393
+ {renderPageHeader()}
394
+ {toolbarSlot}
395
+ {renderFilterPanelSection()}
396
+ {renderToolbar()}
397
+
398
+ <div className="space-y-4">
399
+ {listHeaderSlot}
400
+
401
+ <EntityListPanel
402
+ config={config}
403
+ data={data}
404
+ isLoading={isLoading}
405
+ onRowClick={handleRowClick}
406
+ onAction={handleAction}
407
+ enableSelection={enableBulkActions}
408
+ enableBulkActions={enableBulkActions}
409
+ enableExport={enableExport}
410
+ enableRefresh={!!onRefresh}
411
+ showSearch={enableSearch}
412
+ showPagination={true}
413
+ pageSize={pageSize}
414
+ renderEmptyState={renderEmptyState}
415
+ onExport={onExport}
416
+ onRefresh={onRefresh}
417
+ />
418
+
419
+ {listFooterSlot}
420
+ </div>
421
+
422
+ {renderCreateModal()}
423
+ {renderEditModal()}
424
+ {renderDetailModal()}
425
+
426
+ {footerSlot}
427
+ </PageTemplate>
428
+ </AppLayout>
429
+ );
430
+ };
@@ -0,0 +1,277 @@
1
+ import React from 'react';
2
+ import { AppLayout } from '../../molecules/layout/AppLayout';
3
+ import { PageTemplate } from '../../molecules/layout/PageTemplate';
4
+ import { SectionHeader } from '../../molecules/layout/SectionHeader';
5
+ import {
6
+ MetricsOverviewPanel,
7
+ MetricsOverviewWithInsightsPanel,
8
+ TrendAnalysisPanel,
9
+ CategoryBreakdownPanel
10
+ } from '../../organisms/entity';
11
+ import type { EntityTemplateConfig, EntityData, MetricValue, ActionConfig, MetricConfig } from '../../atoms/types';
12
+ import { cn } from '../../atoms/utils/utils';
13
+
14
+ export interface EntityPerformanceDashboardTemplateProps<T extends EntityData> {
15
+ config: EntityTemplateConfig<T>;
16
+ data: T[];
17
+ previousData?: T[];
18
+ isLoading?: boolean;
19
+ className?: string;
20
+
21
+ // Layout configuration
22
+ layout?: 'standard' | 'compact' | 'detailed';
23
+ showInsights?: boolean;
24
+ showTrends?: boolean;
25
+ showCategories?: boolean;
26
+
27
+ // Extension points - Render Props
28
+ renderCustomActions?: () => React.ReactNode;
29
+ renderAdditionalMetrics?: () => React.ReactNode;
30
+ renderCustomTrendChart?: (config: EntityTemplateConfig<T>, data: T[]) => React.ReactNode;
31
+ renderCustomCategoryView?: (config: EntityTemplateConfig<T>, data: T[]) => React.ReactNode;
32
+
33
+ // Extension points - Slots
34
+ headerSlot?: React.ReactNode;
35
+ footerSlot?: React.ReactNode;
36
+ metricsHeaderSlot?: React.ReactNode;
37
+ metricsFooterSlot?: React.ReactNode;
38
+ trendsHeaderSlot?: React.ReactNode;
39
+ trendsFooterSlot?: React.ReactNode;
40
+ categoriesHeaderSlot?: React.ReactNode;
41
+ categoriesFooterSlot?: React.ReactNode;
42
+
43
+ // Event handlers
44
+ onMetricClick?: (metric: MetricConfig, value: MetricValue) => void;
45
+ onCategoryClick?: (category: unknown) => void;
46
+ onTrendPeriodChange?: (period: string) => void;
47
+ onActionClick?: (action: ActionConfig, context: T[]) => void;
48
+ onRefresh?: () => void;
49
+ onExport?: (type: 'metrics' | 'trends' | 'categories', data: unknown) => void;
50
+ }
51
+
52
+ export const EntityPerformanceDashboardTemplate = <T extends EntityData>({
53
+ config,
54
+ data,
55
+ previousData,
56
+ isLoading = false,
57
+ className,
58
+ layout = 'standard',
59
+ showInsights = true,
60
+ showTrends = true,
61
+ showCategories = true,
62
+ renderCustomActions,
63
+ renderAdditionalMetrics,
64
+ renderCustomTrendChart,
65
+ renderCustomCategoryView,
66
+ headerSlot,
67
+ footerSlot,
68
+ metricsHeaderSlot,
69
+ metricsFooterSlot,
70
+ trendsHeaderSlot,
71
+ trendsFooterSlot,
72
+ categoriesHeaderSlot,
73
+ categoriesFooterSlot,
74
+ onMetricClick,
75
+ onCategoryClick,
76
+ onTrendPeriodChange,
77
+ onExport
78
+ }: EntityPerformanceDashboardTemplateProps<T>) => {
79
+
80
+ const getLayoutClasses = () => {
81
+ switch (layout) {
82
+ case 'compact':
83
+ return 'space-y-4';
84
+ case 'detailed':
85
+ return 'space-y-8';
86
+ case 'standard':
87
+ default:
88
+ return 'space-y-6';
89
+ }
90
+ };
91
+
92
+ const renderPageHeader = () => {
93
+ return (
94
+ <SectionHeader
95
+ title={config.display.title}
96
+ description={config.display.description}
97
+ category={config.display.category}
98
+ actions={renderCustomActions ? renderCustomActions() : undefined}
99
+ />
100
+ );
101
+ };
102
+
103
+ const renderMetricsSection = () => {
104
+ if (!config.metrics.length) return null;
105
+
106
+ const MetricsComponent = showInsights ? MetricsOverviewWithInsightsPanel : MetricsOverviewPanel;
107
+
108
+ return (
109
+ <section className="space-y-4">
110
+ {metricsHeaderSlot}
111
+ <MetricsComponent
112
+ metrics={config.metrics}
113
+ data={data}
114
+ previousData={previousData}
115
+ isLoading={isLoading}
116
+ onMetricClick={onMetricClick}
117
+ category={config.display.category}
118
+ columns={layout === 'compact' ? 2 : layout === 'detailed' ? 4 : 3}
119
+ headerSlot={renderAdditionalMetrics ? renderAdditionalMetrics() : undefined}
120
+ />
121
+ {metricsFooterSlot}
122
+ </section>
123
+ );
124
+ };
125
+
126
+ const renderTrendsSection = () => {
127
+ if (!showTrends || !config.temporal || !config.metrics.length) return null;
128
+
129
+ if (renderCustomTrendChart) {
130
+ const customChart = renderCustomTrendChart(config, data);
131
+ if (customChart) {
132
+ return (
133
+ <section className="space-y-4">
134
+ {trendsHeaderSlot}
135
+ {customChart}
136
+ {trendsFooterSlot}
137
+ </section>
138
+ );
139
+ }
140
+ }
141
+
142
+ return (
143
+ <section className="space-y-4">
144
+ {trendsHeaderSlot}
145
+ <TrendAnalysisPanel
146
+ metrics={config.metrics}
147
+ data={data}
148
+ temporal={config.temporal}
149
+ isLoading={isLoading}
150
+ category={config.display.category}
151
+ enablePeriodSelection={true}
152
+ enableChartTypeSelection={layout === 'detailed'}
153
+ showComparisons={layout !== 'compact'}
154
+ onPeriodChange={onTrendPeriodChange}
155
+ onExport={(chartData, metric) => onExport?.('trends', { chartData, metric })}
156
+ />
157
+ {trendsFooterSlot}
158
+ </section>
159
+ );
160
+ };
161
+
162
+ const renderCategoriesSection = () => {
163
+ if (!showCategories || !config.categories || !data.length) return null;
164
+
165
+ // Find a suitable value field from metrics or use first numeric field
166
+ const valueField = config.metrics.find(m => m.type === 'currency' || m.type === 'count')?.key ||
167
+ Object.keys(data[0]).find(key => typeof data[0][key] === 'number') ||
168
+ 'value';
169
+
170
+ if (renderCustomCategoryView) {
171
+ const customView = renderCustomCategoryView(config, data);
172
+ if (customView) {
173
+ return (
174
+ <section className="space-y-4">
175
+ {categoriesHeaderSlot}
176
+ {customView}
177
+ {categoriesFooterSlot}
178
+ </section>
179
+ );
180
+ }
181
+ }
182
+
183
+ return (
184
+ <section className="space-y-4">
185
+ {categoriesHeaderSlot}
186
+ <CategoryBreakdownPanel
187
+ data={data}
188
+ categoryConfig={config.categories}
189
+ valueField={valueField}
190
+ isLoading={isLoading}
191
+ category={config.display.category}
192
+ title={`${config.display.title} by ${config.categories.defaultGroupBy}`}
193
+ defaultView={layout === 'compact' ? 'list' : 'both'}
194
+ enableDrillDown={config.categories.enableDrillDown}
195
+ onCategoryClick={onCategoryClick}
196
+ onExport={(categoryData) => onExport?.('categories', categoryData)}
197
+ />
198
+ {categoriesFooterSlot}
199
+ </section>
200
+ );
201
+ };
202
+
203
+ const renderLayoutContent = () => {
204
+ const sections = [
205
+ renderMetricsSection(),
206
+ renderTrendsSection(),
207
+ renderCategoriesSection()
208
+ ].filter(Boolean);
209
+
210
+ if (layout === 'detailed' && sections.length > 1) {
211
+ // For detailed layout, use a grid for trends and categories
212
+ const [metricsSection, ...otherSections] = sections;
213
+
214
+ return (
215
+ <div className={getLayoutClasses()}>
216
+ {metricsSection}
217
+
218
+ {otherSections.length > 0 && (
219
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
220
+ {otherSections}
221
+ </div>
222
+ )}
223
+ </div>
224
+ );
225
+ }
226
+
227
+ return (
228
+ <div className={getLayoutClasses()}>
229
+ {sections}
230
+ </div>
231
+ );
232
+ };
233
+
234
+ return (
235
+ <AppLayout>
236
+ <PageTemplate
237
+ className={cn('container mx-auto px-4 py-6', className)}
238
+ data-component-name="EntityPerformanceDashboardTemplate"
239
+ >
240
+ {headerSlot}
241
+ {renderPageHeader()}
242
+ {renderLayoutContent()}
243
+ {footerSlot}
244
+ </PageTemplate>
245
+ </AppLayout>
246
+ );
247
+ };
248
+
249
+ // Enhanced version with real-time updates
250
+ export interface EntityPerformanceDashboardTemplateWithRealTimeProps<T extends EntityData>
251
+ extends EntityPerformanceDashboardTemplateProps<T> {
252
+ enableRealTime?: boolean;
253
+ refreshInterval?: number;
254
+ onDataUpdate?: (newData: T[]) => void;
255
+ }
256
+
257
+ export const EntityPerformanceDashboardTemplateWithRealTime = <T extends EntityData>({
258
+ enableRealTime = false,
259
+ refreshInterval = 30000, // 30 seconds
260
+ onDataUpdate,
261
+ ...props
262
+ }: EntityPerformanceDashboardTemplateWithRealTimeProps<T>) => {
263
+ React.useEffect(() => {
264
+ if (!enableRealTime) return;
265
+
266
+ const interval = setInterval(() => {
267
+ if (onDataUpdate) {
268
+ // This would typically fetch new data from an API
269
+ onDataUpdate(props.data);
270
+ }
271
+ }, refreshInterval);
272
+
273
+ return () => clearInterval(interval);
274
+ }, [enableRealTime, refreshInterval, onDataUpdate, props.data]);
275
+
276
+ return <EntityPerformanceDashboardTemplate {...props} />;
277
+ };