@pattern-stack/frontend-patterns 0.0.4 → 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 (283) hide show
  1. package/dist/frontend-patterns.css +1 -1
  2. package/dist/index.es.js +1917 -2
  3. package/dist/index.es.js.map +1 -1
  4. package/dist/index.js +1916 -1
  5. package/dist/index.js.map +1 -1
  6. package/package.json +6 -3
  7. package/src/App.tsx +11 -1
  8. package/src/atoms/composed/SalesPanel/SalesPanel.tsx +116 -0
  9. package/src/atoms/composed/SalesPanel/index.ts +1 -0
  10. package/src/atoms/composed/SalesPanel/mockSalesData.ts +151 -0
  11. package/src/atoms/composed/index.ts +1 -0
  12. package/src/atoms/types/entity-config.ts +127 -0
  13. package/src/atoms/types/index.ts +2 -1
  14. package/src/atoms/utils/metric-engine.ts +236 -0
  15. package/src/atoms/utils/utils.ts +2 -1
  16. package/src/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.tsx +42 -0
  17. package/src/molecules/layout/DashboardWithSidePanel/index.ts +1 -0
  18. package/src/molecules/layout/Sidebar.tsx +10 -2
  19. package/src/molecules/layout/index.ts +1 -0
  20. package/src/organisms/entity/CategoryBreakdownPanel.tsx +427 -0
  21. package/src/organisms/entity/EntityListPanel.tsx +339 -0
  22. package/src/organisms/entity/MetricsOverviewPanel.tsx +236 -0
  23. package/src/organisms/entity/TrendAnalysisPanel.tsx +337 -0
  24. package/src/organisms/entity/index.ts +4 -0
  25. package/src/organisms/index.ts +4 -1
  26. package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +77 -75
  27. package/src/pages/AdminShowcase/SalesPerformanceDashboard.tsx +158 -0
  28. package/src/pages/AdminShowcase/index.tsx +2 -1
  29. package/src/pages/EntityShowcase/EntityManagementShowcase.tsx +137 -0
  30. package/src/pages/EntityShowcase/EntityPerformanceShowcase.tsx +117 -0
  31. package/src/pages/EntityShowcase/index.ts +2 -0
  32. package/src/pages/EntityTemplateExample.tsx +229 -0
  33. package/src/pages/TestEntityTemplate.tsx +40 -0
  34. package/src/pages/index.ts +2 -1
  35. package/src/templates/entity/EntityManagementTemplate.tsx +430 -0
  36. package/src/templates/entity/EntityPerformanceDashboardTemplate.tsx +277 -0
  37. package/src/templates/entity/configs/financial-config.ts +141 -0
  38. package/src/templates/entity/configs/index.ts +1 -0
  39. package/src/templates/entity/index.ts +3 -0
  40. package/src/templates/financial/FinancialDashboardTemplate.tsx +326 -0
  41. package/src/templates/index.ts +3 -0
  42. package/dist/atoms/composed/Accordion/Accordion.d.ts +0 -20
  43. package/dist/atoms/composed/Accordion/Accordion.d.ts.map +0 -1
  44. package/dist/atoms/composed/Accordion/index.d.ts +0 -2
  45. package/dist/atoms/composed/Accordion/index.d.ts.map +0 -1
  46. package/dist/atoms/composed/Alert/Alert.d.ts +0 -25
  47. package/dist/atoms/composed/Alert/Alert.d.ts.map +0 -1
  48. package/dist/atoms/composed/Alert/index.d.ts +0 -2
  49. package/dist/atoms/composed/Alert/index.d.ts.map +0 -1
  50. package/dist/atoms/composed/Breadcrumb/Breadcrumb.d.ts +0 -17
  51. package/dist/atoms/composed/Breadcrumb/Breadcrumb.d.ts.map +0 -1
  52. package/dist/atoms/composed/Breadcrumb/index.d.ts +0 -2
  53. package/dist/atoms/composed/Breadcrumb/index.d.ts.map +0 -1
  54. package/dist/atoms/composed/Chart/Chart.d.ts +0 -37
  55. package/dist/atoms/composed/Chart/Chart.d.ts.map +0 -1
  56. package/dist/atoms/composed/Chart/index.d.ts +0 -3
  57. package/dist/atoms/composed/Chart/index.d.ts.map +0 -1
  58. package/dist/atoms/composed/ColorSwatch/ColorSwatch.d.ts +0 -19
  59. package/dist/atoms/composed/ColorSwatch/ColorSwatch.d.ts.map +0 -1
  60. package/dist/atoms/composed/ColorSwatch/index.d.ts +0 -2
  61. package/dist/atoms/composed/ColorSwatch/index.d.ts.map +0 -1
  62. package/dist/atoms/composed/DarkModeToggle.d.ts +0 -4
  63. package/dist/atoms/composed/DarkModeToggle.d.ts.map +0 -1
  64. package/dist/atoms/composed/DataBadge/DataBadge.d.ts +0 -13
  65. package/dist/atoms/composed/DataBadge/DataBadge.d.ts.map +0 -1
  66. package/dist/atoms/composed/DataBadge/index.d.ts +0 -2
  67. package/dist/atoms/composed/DataBadge/index.d.ts.map +0 -1
  68. package/dist/atoms/composed/DataTable/DataTable.d.ts +0 -28
  69. package/dist/atoms/composed/DataTable/DataTable.d.ts.map +0 -1
  70. package/dist/atoms/composed/DataTable/TableCellWithTooltip.d.ts +0 -10
  71. package/dist/atoms/composed/DataTable/TableCellWithTooltip.d.ts.map +0 -1
  72. package/dist/atoms/composed/DataTable/index.d.ts +0 -3
  73. package/dist/atoms/composed/DataTable/index.d.ts.map +0 -1
  74. package/dist/atoms/composed/DateTimePicker/DateTimePicker.d.ts +0 -45
  75. package/dist/atoms/composed/DateTimePicker/DateTimePicker.d.ts.map +0 -1
  76. package/dist/atoms/composed/DateTimePicker/index.d.ts +0 -3
  77. package/dist/atoms/composed/DateTimePicker/index.d.ts.map +0 -1
  78. package/dist/atoms/composed/DetailedCard/DetailedCard.d.ts +0 -30
  79. package/dist/atoms/composed/DetailedCard/DetailedCard.d.ts.map +0 -1
  80. package/dist/atoms/composed/DetailedCard/index.d.ts +0 -3
  81. package/dist/atoms/composed/DetailedCard/index.d.ts.map +0 -1
  82. package/dist/atoms/composed/EmptyState/EmptyState.d.ts +0 -18
  83. package/dist/atoms/composed/EmptyState/EmptyState.d.ts.map +0 -1
  84. package/dist/atoms/composed/EmptyState/index.d.ts +0 -2
  85. package/dist/atoms/composed/EmptyState/index.d.ts.map +0 -1
  86. package/dist/atoms/composed/FileUpload/FileUpload.d.ts +0 -46
  87. package/dist/atoms/composed/FileUpload/FileUpload.d.ts.map +0 -1
  88. package/dist/atoms/composed/FileUpload/index.d.ts +0 -3
  89. package/dist/atoms/composed/FileUpload/index.d.ts.map +0 -1
  90. package/dist/atoms/composed/FormField/FormField.d.ts +0 -23
  91. package/dist/atoms/composed/FormField/FormField.d.ts.map +0 -1
  92. package/dist/atoms/composed/FormField/index.d.ts +0 -2
  93. package/dist/atoms/composed/FormField/index.d.ts.map +0 -1
  94. package/dist/atoms/composed/GlobalSearch/GlobalSearch.d.ts +0 -8
  95. package/dist/atoms/composed/GlobalSearch/GlobalSearch.d.ts.map +0 -1
  96. package/dist/atoms/composed/GlobalSearch/index.d.ts +0 -2
  97. package/dist/atoms/composed/GlobalSearch/index.d.ts.map +0 -1
  98. package/dist/atoms/composed/IconBadge/IconBadge.d.ts +0 -16
  99. package/dist/atoms/composed/IconBadge/IconBadge.d.ts.map +0 -1
  100. package/dist/atoms/composed/IconBadge/index.d.ts +0 -3
  101. package/dist/atoms/composed/IconBadge/index.d.ts.map +0 -1
  102. package/dist/atoms/composed/Modal/Modal.d.ts +0 -18
  103. package/dist/atoms/composed/Modal/Modal.d.ts.map +0 -1
  104. package/dist/atoms/composed/Modal/index.d.ts +0 -3
  105. package/dist/atoms/composed/Modal/index.d.ts.map +0 -1
  106. package/dist/atoms/composed/PaletteSwitcher.d.ts +0 -7
  107. package/dist/atoms/composed/PaletteSwitcher.d.ts.map +0 -1
  108. package/dist/atoms/composed/ProgressBar/ProgressBar.d.ts +0 -25
  109. package/dist/atoms/composed/ProgressBar/ProgressBar.d.ts.map +0 -1
  110. package/dist/atoms/composed/ProgressBar/index.d.ts +0 -2
  111. package/dist/atoms/composed/ProgressBar/index.d.ts.map +0 -1
  112. package/dist/atoms/composed/StatCard/StatCard.d.ts +0 -21
  113. package/dist/atoms/composed/StatCard/StatCard.d.ts.map +0 -1
  114. package/dist/atoms/composed/StatCard/index.d.ts +0 -2
  115. package/dist/atoms/composed/StatCard/index.d.ts.map +0 -1
  116. package/dist/atoms/composed/StyleGuide.d.ts +0 -3
  117. package/dist/atoms/composed/StyleGuide.d.ts.map +0 -1
  118. package/dist/atoms/composed/Toast/Toast.d.ts +0 -40
  119. package/dist/atoms/composed/Toast/Toast.d.ts.map +0 -1
  120. package/dist/atoms/composed/Toast/index.d.ts +0 -2
  121. package/dist/atoms/composed/Toast/index.d.ts.map +0 -1
  122. package/dist/atoms/composed/Tooltip/Tooltip.d.ts +0 -16
  123. package/dist/atoms/composed/Tooltip/Tooltip.d.ts.map +0 -1
  124. package/dist/atoms/composed/Tooltip/index.d.ts +0 -2
  125. package/dist/atoms/composed/Tooltip/index.d.ts.map +0 -1
  126. package/dist/atoms/composed/UserAvatar/UserAvatar.d.ts +0 -8
  127. package/dist/atoms/composed/UserAvatar/UserAvatar.d.ts.map +0 -1
  128. package/dist/atoms/composed/UserAvatar/index.d.ts +0 -2
  129. package/dist/atoms/composed/UserAvatar/index.d.ts.map +0 -1
  130. package/dist/atoms/composed/UserMenu/UserMenu.d.ts +0 -8
  131. package/dist/atoms/composed/UserMenu/UserMenu.d.ts.map +0 -1
  132. package/dist/atoms/composed/UserMenu/index.d.ts +0 -2
  133. package/dist/atoms/composed/UserMenu/index.d.ts.map +0 -1
  134. package/dist/atoms/composed/index.d.ts +0 -25
  135. package/dist/atoms/composed/index.d.ts.map +0 -1
  136. package/dist/atoms/hooks/useApi.d.ts +0 -25
  137. package/dist/atoms/hooks/useApi.d.ts.map +0 -1
  138. package/dist/atoms/hooks/useHealth.d.ts +0 -19
  139. package/dist/atoms/hooks/useHealth.d.ts.map +0 -1
  140. package/dist/atoms/index.d.ts +0 -9
  141. package/dist/atoms/index.d.ts.map +0 -1
  142. package/dist/atoms/services/api/client.d.ts +0 -20
  143. package/dist/atoms/services/api/client.d.ts.map +0 -1
  144. package/dist/atoms/services/auth-service.d.ts +0 -24
  145. package/dist/atoms/services/auth-service.d.ts.map +0 -1
  146. package/dist/atoms/services/health.d.ts +0 -7
  147. package/dist/atoms/services/health.d.ts.map +0 -1
  148. package/dist/atoms/services/index.d.ts +0 -4
  149. package/dist/atoms/services/index.d.ts.map +0 -1
  150. package/dist/atoms/shared/config/constants.d.ts +0 -15
  151. package/dist/atoms/shared/config/constants.d.ts.map +0 -1
  152. package/dist/atoms/shared/config/dashboard-sizes.d.ts +0 -83
  153. package/dist/atoms/shared/config/dashboard-sizes.d.ts.map +0 -1
  154. package/dist/atoms/shared/config/environment.d.ts +0 -10
  155. package/dist/atoms/shared/config/environment.d.ts.map +0 -1
  156. package/dist/atoms/shared/index.d.ts +0 -4
  157. package/dist/atoms/shared/index.d.ts.map +0 -1
  158. package/dist/atoms/types/auth.d.ts +0 -56
  159. package/dist/atoms/types/auth.d.ts.map +0 -1
  160. package/dist/atoms/types/generated.d.ts +0 -1469
  161. package/dist/atoms/types/generated.d.ts.map +0 -1
  162. package/dist/atoms/types/index.d.ts +0 -4
  163. package/dist/atoms/types/index.d.ts.map +0 -1
  164. package/dist/atoms/types/loading.d.ts +0 -26
  165. package/dist/atoms/types/loading.d.ts.map +0 -1
  166. package/dist/atoms/ui/Badge.d.ts +0 -10
  167. package/dist/atoms/ui/Badge.d.ts.map +0 -1
  168. package/dist/atoms/ui/ErrorBoundary.d.ts +0 -18
  169. package/dist/atoms/ui/ErrorBoundary.d.ts.map +0 -1
  170. package/dist/atoms/ui/Select.d.ts +0 -28
  171. package/dist/atoms/ui/Select.d.ts.map +0 -1
  172. package/dist/atoms/ui/Switch.d.ts +0 -9
  173. package/dist/atoms/ui/Switch.d.ts.map +0 -1
  174. package/dist/atoms/ui/Tabs.d.ts +0 -30
  175. package/dist/atoms/ui/Tabs.d.ts.map +0 -1
  176. package/dist/atoms/ui/avatar.d.ts +0 -7
  177. package/dist/atoms/ui/avatar.d.ts.map +0 -1
  178. package/dist/atoms/ui/button.d.ts +0 -14
  179. package/dist/atoms/ui/button.d.ts.map +0 -1
  180. package/dist/atoms/ui/card.d.ts +0 -12
  181. package/dist/atoms/ui/card.d.ts.map +0 -1
  182. package/dist/atoms/ui/dropdown-menu.d.ts +0 -28
  183. package/dist/atoms/ui/dropdown-menu.d.ts.map +0 -1
  184. package/dist/atoms/ui/index.d.ts +0 -15
  185. package/dist/atoms/ui/index.d.ts.map +0 -1
  186. package/dist/atoms/ui/input.d.ts +0 -5
  187. package/dist/atoms/ui/input.d.ts.map +0 -1
  188. package/dist/atoms/ui/label.d.ts +0 -6
  189. package/dist/atoms/ui/label.d.ts.map +0 -1
  190. package/dist/atoms/ui/skeleton.d.ts +0 -3
  191. package/dist/atoms/ui/skeleton.d.ts.map +0 -1
  192. package/dist/atoms/ui/spinner.d.ts +0 -14
  193. package/dist/atoms/ui/spinner.d.ts.map +0 -1
  194. package/dist/atoms/ui/table.d.ts +0 -11
  195. package/dist/atoms/ui/table.d.ts.map +0 -1
  196. package/dist/atoms/utils/animations.d.ts +0 -65
  197. package/dist/atoms/utils/animations.d.ts.map +0 -1
  198. package/dist/atoms/utils/tooltip-helpers.d.ts +0 -71
  199. package/dist/atoms/utils/tooltip-helpers.d.ts.map +0 -1
  200. package/dist/atoms/utils/utils.d.ts +0 -4
  201. package/dist/atoms/utils/utils.d.ts.map +0 -1
  202. package/dist/features/auth/components/LoginForm.d.ts +0 -2
  203. package/dist/features/auth/components/LoginForm.d.ts.map +0 -1
  204. package/dist/features/auth/components/LogoutButton.d.ts +0 -2
  205. package/dist/features/auth/components/LogoutButton.d.ts.map +0 -1
  206. package/dist/features/auth/components/ProtectedRoute.d.ts +0 -10
  207. package/dist/features/auth/components/ProtectedRoute.d.ts.map +0 -1
  208. package/dist/features/auth/components/index.d.ts +0 -4
  209. package/dist/features/auth/components/index.d.ts.map +0 -1
  210. package/dist/features/auth/hooks/index.d.ts +0 -3
  211. package/dist/features/auth/hooks/index.d.ts.map +0 -1
  212. package/dist/features/auth/hooks/useAuth.d.ts +0 -10
  213. package/dist/features/auth/hooks/useAuth.d.ts.map +0 -1
  214. package/dist/features/auth/hooks/usePermissions.d.ts +0 -13
  215. package/dist/features/auth/hooks/usePermissions.d.ts.map +0 -1
  216. package/dist/features/auth/index.d.ts +0 -3
  217. package/dist/features/auth/index.d.ts.map +0 -1
  218. package/dist/features/index.d.ts +0 -2
  219. package/dist/features/index.d.ts.map +0 -1
  220. package/dist/index.d.ts +0 -10
  221. package/dist/index.d.ts.map +0 -1
  222. package/dist/molecules/forms/FormGroup.d.ts +0 -17
  223. package/dist/molecules/forms/FormGroup.d.ts.map +0 -1
  224. package/dist/molecules/forms/SearchInput.d.ts +0 -36
  225. package/dist/molecules/forms/SearchInput.d.ts.map +0 -1
  226. package/dist/molecules/forms/index.d.ts +0 -3
  227. package/dist/molecules/forms/index.d.ts.map +0 -1
  228. package/dist/molecules/index.d.ts +0 -4
  229. package/dist/molecules/index.d.ts.map +0 -1
  230. package/dist/molecules/layout/AppHeader/AppHeader.d.ts +0 -7
  231. package/dist/molecules/layout/AppHeader/AppHeader.d.ts.map +0 -1
  232. package/dist/molecules/layout/AppHeader/index.d.ts +0 -2
  233. package/dist/molecules/layout/AppHeader/index.d.ts.map +0 -1
  234. package/dist/molecules/layout/AppLayout.d.ts +0 -2
  235. package/dist/molecules/layout/AppLayout.d.ts.map +0 -1
  236. package/dist/molecules/layout/PageTemplate.d.ts +0 -19
  237. package/dist/molecules/layout/PageTemplate.d.ts.map +0 -1
  238. package/dist/molecules/layout/SectionHeader/SectionHeader.d.ts +0 -24
  239. package/dist/molecules/layout/SectionHeader/SectionHeader.d.ts.map +0 -1
  240. package/dist/molecules/layout/SectionHeader/index.d.ts +0 -2
  241. package/dist/molecules/layout/SectionHeader/index.d.ts.map +0 -1
  242. package/dist/molecules/layout/ShowcaseSection.d.ts +0 -22
  243. package/dist/molecules/layout/ShowcaseSection.d.ts.map +0 -1
  244. package/dist/molecules/layout/Sidebar.d.ts +0 -6
  245. package/dist/molecules/layout/Sidebar.d.ts.map +0 -1
  246. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts +0 -13
  247. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts.map +0 -1
  248. package/dist/molecules/layout/SidebarButton/index.d.ts +0 -2
  249. package/dist/molecules/layout/SidebarButton/index.d.ts.map +0 -1
  250. package/dist/molecules/layout/SidebarContext.d.ts +0 -12
  251. package/dist/molecules/layout/SidebarContext.d.ts.map +0 -1
  252. package/dist/molecules/layout/index.d.ts +0 -8
  253. package/dist/molecules/layout/index.d.ts.map +0 -1
  254. package/dist/molecules/navigation/NavMenu.d.ts +0 -20
  255. package/dist/molecules/navigation/NavMenu.d.ts.map +0 -1
  256. package/dist/molecules/navigation/Pagination.d.ts +0 -14
  257. package/dist/molecules/navigation/Pagination.d.ts.map +0 -1
  258. package/dist/molecules/navigation/index.d.ts +0 -3
  259. package/dist/molecules/navigation/index.d.ts.map +0 -1
  260. package/dist/organisms/index.d.ts +0 -2
  261. package/dist/organisms/index.d.ts.map +0 -1
  262. package/dist/organisms/showcase/ComponentShowcasePage.d.ts +0 -3
  263. package/dist/organisms/showcase/ComponentShowcasePage.d.ts.map +0 -1
  264. package/dist/templates/AuthTemplate.d.ts +0 -68
  265. package/dist/templates/AuthTemplate.d.ts.map +0 -1
  266. package/dist/templates/ComponentShowcaseTemplate.d.ts +0 -53
  267. package/dist/templates/ComponentShowcaseTemplate.d.ts.map +0 -1
  268. package/dist/templates/DashboardTemplate.d.ts +0 -62
  269. package/dist/templates/DashboardTemplate.d.ts.map +0 -1
  270. package/dist/templates/DataTemplate.d.ts +0 -78
  271. package/dist/templates/DataTemplate.d.ts.map +0 -1
  272. package/dist/templates/admin/AdminCRUDTemplate.d.ts +0 -105
  273. package/dist/templates/admin/AdminCRUDTemplate.d.ts.map +0 -1
  274. package/dist/templates/admin/AdminDashboardTemplate.d.ts +0 -89
  275. package/dist/templates/admin/AdminDashboardTemplate.d.ts.map +0 -1
  276. package/dist/templates/admin/AdminDetailTemplate.d.ts +0 -132
  277. package/dist/templates/admin/AdminDetailTemplate.d.ts.map +0 -1
  278. package/dist/templates/admin/index.d.ts +0 -4
  279. package/dist/templates/admin/index.d.ts.map +0 -1
  280. package/dist/templates/factory.d.ts +0 -28
  281. package/dist/templates/factory.d.ts.map +0 -1
  282. package/dist/templates/index.d.ts +0 -7
  283. package/dist/templates/index.d.ts.map +0 -1
package/dist/index.es.js CHANGED
@@ -14,7 +14,7 @@ import { Slot } from "@radix-ui/react-slot";
14
14
  import * as LabelPrimitive from "@radix-ui/react-label";
15
15
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
16
16
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
17
- import { ChevronRight, Check, Circle, Loader2, ArrowRight, TrendingUp, TrendingDown, Minus, FileX, AlertCircle, Search, Database, Sparkles, Mail, Lock, Shield, User, Sun, Moon, UserCircle, Settings, LogOut, X, ChevronsUpDown, ChevronUp, ChevronDown, ChevronLeft, Clock, Calendar, BarChart3, AreaChart, LineChart, Upload, Image, File, CheckCircle, Info, AlertTriangle, Home, Palette, Square, Waves, Zap, TreePine, Sunset, Building2, Users, DollarSign, ShoppingCart, Menu, MoreHorizontal, Plus, Filter, Download, Activity, RefreshCw, Eye, Edit, Trash2, FileText, History, ArrowLeft, Save, Copy, ExternalLink, Grid3X3, Layers, XCircle } from "lucide-react";
17
+ import { ChevronRight, Check, Circle, Loader2, Target, ExternalLink, ArrowRight, TrendingUp, TrendingDown, Minus, FileX, AlertCircle, Search, Database, Sparkles, Mail, Lock, Shield, User, Sun, Moon, UserCircle, Settings, LogOut, X, ChevronsUpDown, ChevronUp, ChevronDown, ChevronLeft, Clock, Calendar, BarChart3, AreaChart, LineChart, Upload, Image, File, CheckCircle, Info, AlertTriangle, Home, Palette, Square, Waves, Zap, TreePine, Sunset, Building2, Users, DollarSign, ShoppingCart, Menu, Layout, MoreHorizontal, Plus, Filter, Download, Activity, RefreshCw, Eye, Edit, Trash2, FileText, History, ArrowLeft, Save, Copy, PieChart, List, Wallet, Grid3X3, Layers, XCircle } from "lucide-react";
18
18
  import { createPortal } from "react-dom";
19
19
  import { useLocation, useNavigate, useSearchParams, Outlet, BrowserRouter, Routes, Route } from "react-router-dom";
20
20
  import { createRoot } from "react-dom/client";
@@ -244,6 +244,175 @@ const tooltipContent = {
244
244
  profile: "Profile",
245
245
  account: "Account settings"
246
246
  };
247
+ class MetricCalculationEngine {
248
+ static calculateMetric(config, data, previousData) {
249
+ const currentValue = this.aggregateValue(config, data);
250
+ const previousValue = previousData ? this.aggregateValue(config, previousData) : void 0;
251
+ const trend = this.calculateTrend(currentValue, previousValue);
252
+ const formattedValue = this.formatValue(currentValue, config.format, config.type);
253
+ const target = typeof config.target === "function" ? config.target(data) : config.target;
254
+ return {
255
+ current: currentValue,
256
+ previous: previousValue,
257
+ trend,
258
+ target,
259
+ formattedValue
260
+ };
261
+ }
262
+ static aggregateValue(config, data) {
263
+ if (!data.length) return 0;
264
+ const values = data.map((item) => {
265
+ const value = this.extractValue(item, config.key);
266
+ return typeof value === "number" ? value : 0;
267
+ }).filter((value) => !isNaN(value));
268
+ if (!values.length) return 0;
269
+ switch (config.aggregation || "sum") {
270
+ case "sum":
271
+ return values.reduce((sum, value) => sum + value, 0);
272
+ case "avg":
273
+ return values.reduce((sum, value) => sum + value, 0) / values.length;
274
+ case "count":
275
+ return values.length;
276
+ case "min":
277
+ return Math.min(...values);
278
+ case "max":
279
+ return Math.max(...values);
280
+ default:
281
+ return values.reduce((sum, value) => sum + value, 0);
282
+ }
283
+ }
284
+ static extractValue(item, key) {
285
+ return key.split(".").reduce((obj, k) => obj == null ? void 0 : obj[k], item);
286
+ }
287
+ static calculateTrend(current, previous) {
288
+ if (previous === void 0 || previous === 0) return "neutral";
289
+ const change = (current - previous) / Math.abs(previous) * 100;
290
+ if (change > 1) return "up";
291
+ if (change < -1) return "down";
292
+ return "neutral";
293
+ }
294
+ static formatValue(value, format, type) {
295
+ let formatted = value;
296
+ if ((format == null ? void 0 : format.decimals) !== void 0) {
297
+ formatted = Number(value.toFixed(format.decimals));
298
+ }
299
+ let result = formatted.toString();
300
+ if ((format == null ? void 0 : format.thousands) !== false && Math.abs(formatted) >= 1e3) {
301
+ result = formatted.toLocaleString();
302
+ }
303
+ switch (type) {
304
+ case "currency":
305
+ result = new Intl.NumberFormat("en-US", {
306
+ style: "currency",
307
+ currency: "USD",
308
+ minimumFractionDigits: (format == null ? void 0 : format.decimals) ?? 2,
309
+ maximumFractionDigits: (format == null ? void 0 : format.decimals) ?? 2
310
+ }).format(formatted);
311
+ break;
312
+ case "percentage":
313
+ result = `${formatted.toFixed((format == null ? void 0 : format.decimals) ?? 1)}%`;
314
+ break;
315
+ case "duration":
316
+ result = this.formatDuration(formatted);
317
+ break;
318
+ case "ratio":
319
+ result = `${formatted.toFixed((format == null ? void 0 : format.decimals) ?? 2)}:1`;
320
+ break;
321
+ default:
322
+ if (format == null ? void 0 : format.prefix) result = format.prefix + result;
323
+ if (format == null ? void 0 : format.suffix) result = result + format.suffix;
324
+ }
325
+ return result;
326
+ }
327
+ static formatDuration(minutes) {
328
+ const hours = Math.floor(minutes / 60);
329
+ const mins = Math.floor(minutes % 60);
330
+ if (hours > 0) {
331
+ return `${hours}h ${mins}m`;
332
+ }
333
+ return `${mins}m`;
334
+ }
335
+ static calculateTrendData(config, data, dateField = "date", periods = 12) {
336
+ const groupedData = this.groupByPeriod(data, dateField);
337
+ const sortedDates = Object.keys(groupedData).sort();
338
+ return sortedDates.slice(-periods).map((date) => ({
339
+ date,
340
+ value: this.aggregateValue(config, groupedData[date]),
341
+ label: this.formatDateLabel(date)
342
+ }));
343
+ }
344
+ static groupByPeriod(data, dateField) {
345
+ return data.reduce((groups, item) => {
346
+ const date = this.extractValue(item, dateField);
347
+ if (!date) return groups;
348
+ const period = new Date(date).toISOString().split("T")[0];
349
+ if (!groups[period]) groups[period] = [];
350
+ groups[period].push(item);
351
+ return groups;
352
+ }, {});
353
+ }
354
+ static formatDateLabel(dateString) {
355
+ const date = new Date(dateString);
356
+ return date.toLocaleDateString("en-US", {
357
+ month: "short",
358
+ day: "numeric"
359
+ });
360
+ }
361
+ static calculateCategoryBreakdown(data, categoryField, valueField, maxCategories = 8) {
362
+ const groups = data.reduce((acc, item) => {
363
+ const category = String(this.extractValue(item, categoryField) || "Unknown");
364
+ const value = this.extractValue(item, valueField) || 0;
365
+ if (!acc[category]) acc[category] = 0;
366
+ acc[category] += typeof value === "number" ? value : 0;
367
+ return acc;
368
+ }, {});
369
+ const total = Object.values(groups).reduce((sum, value) => sum + value, 0);
370
+ let categories = Object.entries(groups).map(([category, value]) => ({
371
+ category,
372
+ value,
373
+ percentage: total > 0 ? value / total * 100 : 0
374
+ })).sort((a, b) => b.value - a.value);
375
+ if (categories.length > maxCategories) {
376
+ const topCategories = categories.slice(0, maxCategories - 1);
377
+ const otherValue = categories.slice(maxCategories - 1).reduce((sum, cat) => sum + cat.value, 0);
378
+ topCategories.push({
379
+ category: "Other",
380
+ value: otherValue,
381
+ percentage: total > 0 ? otherValue / total * 100 : 0
382
+ });
383
+ categories = topCategories;
384
+ }
385
+ return categories;
386
+ }
387
+ static detectInsights(metrics, thresholds = {}) {
388
+ const insights = [];
389
+ for (const [key, metric] of Object.entries(metrics)) {
390
+ const threshold = thresholds[key];
391
+ if (metric.target && metric.current < metric.target * 0.8) {
392
+ insights.push({
393
+ type: "negative",
394
+ message: `${key} is significantly below target`,
395
+ value: metric.current
396
+ });
397
+ }
398
+ if (metric.trend === "up" && metric.previous && metric.current > metric.previous * 1.2) {
399
+ insights.push({
400
+ type: "positive",
401
+ message: `${key} showing strong growth`,
402
+ value: metric.current
403
+ });
404
+ }
405
+ if (threshold && metric.current >= threshold.critical) {
406
+ insights.push({
407
+ type: "negative",
408
+ message: `${key} has reached critical threshold`,
409
+ value: metric.current
410
+ });
411
+ }
412
+ }
413
+ return insights.slice(0, 5);
414
+ }
415
+ }
247
416
  function cn(...inputs) {
248
417
  return twMerge(clsx(inputs));
249
418
  }
@@ -1265,6 +1434,83 @@ const DataBadge = ({
1265
1434
  }
1266
1435
  return badge;
1267
1436
  };
1437
+ const getStageStatus = (stage) => {
1438
+ switch (stage) {
1439
+ case "Closed Won":
1440
+ return "success";
1441
+ case "Negotiation":
1442
+ return "warning";
1443
+ case "Proposal Sent":
1444
+ return "info";
1445
+ case "Qualified":
1446
+ return "info";
1447
+ case "Discovery":
1448
+ return "neutral";
1449
+ default:
1450
+ return "neutral";
1451
+ }
1452
+ };
1453
+ const SalesPanel = ({
1454
+ sales,
1455
+ onSaleClick,
1456
+ onClose
1457
+ }) => {
1458
+ const topDeals = sales.slice(0, 5);
1459
+ const totalValue = sales.reduce((sum, sale) => sum + sale.amount, 0);
1460
+ return /* @__PURE__ */ jsxs("div", { className: "fixed right-0 top-16 h-[calc(100vh-4rem)] w-72 bg-background border-l border-border shadow-lg flex flex-col z-30", children: [
1461
+ /* @__PURE__ */ jsx("div", { className: "p-3 border-b border-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1462
+ /* @__PURE__ */ jsxs("h3", { className: "font-medium flex items-center gap-2", children: [
1463
+ /* @__PURE__ */ jsx(Target, { className: "w-4 h-4" }),
1464
+ "Pipeline"
1465
+ ] }),
1466
+ onClose && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, children: "×" })
1467
+ ] }) }),
1468
+ /* @__PURE__ */ jsx("div", { className: "p-3 border-b border-border", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1469
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1470
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Total Value" }),
1471
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-green-600", children: [
1472
+ "$",
1473
+ totalValue.toLocaleString()
1474
+ ] })
1475
+ ] }),
1476
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1477
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Active Deals" }),
1478
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: sales.length })
1479
+ ] })
1480
+ ] }) }),
1481
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-auto p-3", children: [
1482
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium mb-3", children: "Recent Opportunities" }),
1483
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: topDeals.map((sale) => /* @__PURE__ */ jsxs(
1484
+ "div",
1485
+ {
1486
+ className: "p-2 border border-border rounded-md hover:bg-muted/50 cursor-pointer transition-colors",
1487
+ onClick: () => onSaleClick == null ? void 0 : onSaleClick(sale),
1488
+ children: [
1489
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-start mb-1", children: [
1490
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1491
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: sale.customer }),
1492
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground truncate", children: sale.product })
1493
+ ] }),
1494
+ /* @__PURE__ */ jsx("div", { className: "text-right ml-2", children: /* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-green-600", children: [
1495
+ "$",
1496
+ sale.amount.toLocaleString()
1497
+ ] }) })
1498
+ ] }),
1499
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
1500
+ /* @__PURE__ */ jsx(DataBadge, { variant: "status", status: getStageStatus(sale.stage), children: sale.stage }),
1501
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: sale.salesperson })
1502
+ ] })
1503
+ ]
1504
+ },
1505
+ sale.id
1506
+ )) })
1507
+ ] }),
1508
+ /* @__PURE__ */ jsx("div", { className: "p-3 border-t border-border", children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "w-full", children: [
1509
+ /* @__PURE__ */ jsx(ExternalLink, { className: "w-4 h-4 mr-2" }),
1510
+ "View All Deals"
1511
+ ] }) })
1512
+ ] });
1513
+ };
1268
1514
  const StatCard = ({
1269
1515
  title,
1270
1516
  value,
@@ -5598,7 +5844,11 @@ const Sidebar = ({ className }) => {
5598
5844
  const items = [
5599
5845
  { value: "showcase", label: "Showcase", icon: /* @__PURE__ */ jsx(Palette, { className: "w-5 h-5" }), path: "/showcase", category: 5 },
5600
5846
  { value: "admin-dashboard", label: "Admin Dashboard", icon: /* @__PURE__ */ jsx(Shield, { className: "w-5 h-5" }), path: "/admin/dashboard", category: 2 },
5601
- { value: "admin-users", label: "User Management", icon: /* @__PURE__ */ jsx(Users, { className: "w-5 h-5" }), path: "/admin/users", category: 3 }
5847
+ { value: "admin-users", label: "User Management", icon: /* @__PURE__ */ jsx(Users, { className: "w-5 h-5" }), path: "/admin/users", category: 3 },
5848
+ { value: "admin-sales", label: "Sales Dashboard", icon: /* @__PURE__ */ jsx(TrendingUp, { className: "w-5 h-5" }), path: "/admin/sales", category: 4 },
5849
+ { value: "entity-performance", label: "Performance Dashboard", icon: /* @__PURE__ */ jsx(BarChart3, { className: "w-5 h-5" }), path: "/entity/performance", category: 6 },
5850
+ { value: "entity-management", label: "Entity Management", icon: /* @__PURE__ */ jsx(Database, { className: "w-5 h-5" }), path: "/entity/management", category: 7 },
5851
+ { value: "entity-template", label: "Template Example", icon: /* @__PURE__ */ jsx(Layout, { className: "w-5 h-5" }), path: "/entity/template-example", category: 1 }
5602
5852
  ];
5603
5853
  const handleNavigation = (path) => {
5604
5854
  if (path.includes("?")) {
@@ -5726,6 +5976,28 @@ const AppLayout = () => {
5726
5976
  )
5727
5977
  ] });
5728
5978
  };
5979
+ const DashboardWithSidePanel = ({
5980
+ children,
5981
+ sidePanel,
5982
+ showSidePanel = false,
5983
+ sidePanelWidth = 72,
5984
+ className
5985
+ }) => {
5986
+ const marginClass = `pr-${sidePanelWidth}`;
5987
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-full", className), children: [
5988
+ /* @__PURE__ */ jsx(
5989
+ "div",
5990
+ {
5991
+ className: cn(
5992
+ "transition-all duration-300",
5993
+ showSidePanel ? marginClass : ""
5994
+ ),
5995
+ children
5996
+ }
5997
+ ),
5998
+ showSidePanel && sidePanel
5999
+ ] });
6000
+ };
5729
6001
  const SectionHeader = ({
5730
6002
  title,
5731
6003
  description,
@@ -7738,6 +8010,1636 @@ const AdminDetailTemplate = ({
7738
8010
  ] }) }) })
7739
8011
  ] });
7740
8012
  };
8013
+ const MetricsOverviewPanel = ({
8014
+ metrics,
8015
+ data,
8016
+ previousData,
8017
+ isLoading = false,
8018
+ onMetricClick,
8019
+ className,
8020
+ layout = "grid",
8021
+ columns = 4,
8022
+ category,
8023
+ renderCustomMetric,
8024
+ renderHeader,
8025
+ renderFooter,
8026
+ headerSlot,
8027
+ footerSlot
8028
+ }) => {
8029
+ const calculatedMetrics = React__default.useMemo(() => {
8030
+ if (isLoading || !(data == null ? void 0 : data.length) || !(metrics == null ? void 0 : metrics.length)) return {};
8031
+ return metrics.reduce((acc, metric) => {
8032
+ acc[metric.key] = MetricCalculationEngine.calculateMetric(
8033
+ metric,
8034
+ data,
8035
+ previousData
8036
+ );
8037
+ return acc;
8038
+ }, {});
8039
+ }, [metrics, data, previousData, isLoading]);
8040
+ const getLayoutClasses = () => {
8041
+ switch (layout) {
8042
+ case "horizontal":
8043
+ return "flex flex-wrap gap-4";
8044
+ case "vertical":
8045
+ return "flex flex-col gap-4";
8046
+ case "grid":
8047
+ default:
8048
+ return cn(
8049
+ "grid gap-4",
8050
+ {
8051
+ "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4": columns === 4,
8052
+ "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3": columns === 3,
8053
+ "grid-cols-1 sm:grid-cols-2": columns === 2
8054
+ }
8055
+ );
8056
+ }
8057
+ };
8058
+ const renderMetricCard = (metric, index) => {
8059
+ if (renderCustomMetric) {
8060
+ const customContent = renderCustomMetric(metric, calculatedMetrics[metric.key], index);
8061
+ if (customContent) return customContent;
8062
+ }
8063
+ const metricValue = calculatedMetrics[metric.key];
8064
+ if (isLoading || !metricValue) {
8065
+ return /* @__PURE__ */ jsx(
8066
+ StatCard,
8067
+ {
8068
+ title: metric.label,
8069
+ value: "",
8070
+ isLoading: true,
8071
+ category,
8072
+ icon: metric.icon ? /* @__PURE__ */ jsx(metric.icon, {}) : void 0
8073
+ },
8074
+ metric.key
8075
+ );
8076
+ }
8077
+ const trend = metricValue.trend !== "neutral" && metricValue.previous ? {
8078
+ value: Number(((metricValue.current - metricValue.previous) / Math.abs(metricValue.previous) * 100).toFixed(1)),
8079
+ label: "vs last period"
8080
+ } : void 0;
8081
+ const formatTargetValue = (value) => {
8082
+ switch (metric.type) {
8083
+ case "currency":
8084
+ return new Intl.NumberFormat("en-US", {
8085
+ style: "currency",
8086
+ currency: "USD"
8087
+ }).format(value);
8088
+ case "percentage":
8089
+ return `${value}%`;
8090
+ default:
8091
+ return value.toString();
8092
+ }
8093
+ };
8094
+ const subtitle = metricValue.target ? `Target: ${formatTargetValue(metricValue.target)}` : void 0;
8095
+ return /* @__PURE__ */ jsx(
8096
+ StatCard,
8097
+ {
8098
+ title: metric.label,
8099
+ value: metricValue.formattedValue,
8100
+ subtitle,
8101
+ trend,
8102
+ category,
8103
+ icon: metric.icon ? /* @__PURE__ */ jsx(metric.icon, {}) : void 0,
8104
+ onClick: onMetricClick ? () => onMetricClick(metric, metricValue) : void 0,
8105
+ valueTooltip: `Current: ${metricValue.formattedValue}${metricValue.previous ? ` | Previous: ${formatTargetValue(metricValue.previous)}` : ""}`,
8106
+ iconTooltip: `View ${metric.label} details`
8107
+ },
8108
+ metric.key
8109
+ );
8110
+ };
8111
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), "data-component-name": "MetricsOverviewPanel", children: [
8112
+ headerSlot,
8113
+ renderHeader && renderHeader(),
8114
+ /* @__PURE__ */ jsx("div", { className: getLayoutClasses(), children: metrics.map((metric, index) => renderMetricCard(metric, index)) }),
8115
+ renderFooter && renderFooter(),
8116
+ footerSlot
8117
+ ] });
8118
+ };
8119
+ const MetricsOverviewWithInsightsPanel = ({
8120
+ showInsights = true,
8121
+ insightThresholds,
8122
+ renderInsight,
8123
+ ...props
8124
+ }) => {
8125
+ const safeMetrics = props.metrics || [];
8126
+ const safeData = props.data || [];
8127
+ const calculatedMetrics = React__default.useMemo(() => {
8128
+ if (props.isLoading || !safeData.length || !safeMetrics.length) return {};
8129
+ return safeMetrics.reduce((acc, metric) => {
8130
+ acc[metric.key] = MetricCalculationEngine.calculateMetric(
8131
+ metric,
8132
+ safeData,
8133
+ props.previousData
8134
+ );
8135
+ return acc;
8136
+ }, {});
8137
+ }, [safeMetrics, safeData, props.previousData, props.isLoading]);
8138
+ const insights = React__default.useMemo(() => {
8139
+ if (!showInsights || props.isLoading || Object.keys(calculatedMetrics).length === 0) {
8140
+ return [];
8141
+ }
8142
+ return MetricCalculationEngine.detectInsights(calculatedMetrics, insightThresholds);
8143
+ }, [calculatedMetrics, showInsights, insightThresholds, props.isLoading]);
8144
+ const renderInsightsSection = () => {
8145
+ if (!showInsights || insights.length === 0) return null;
8146
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8147
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Key Insights" }),
8148
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: insights.map((insight, index) => {
8149
+ if (renderInsight) {
8150
+ const customInsight = renderInsight(insight, index);
8151
+ if (customInsight) return customInsight;
8152
+ }
8153
+ const colorClass = {
8154
+ positive: "text-status-success",
8155
+ negative: "text-status-error",
8156
+ neutral: "text-muted-foreground"
8157
+ }[insight.type];
8158
+ return /* @__PURE__ */ jsxs(
8159
+ "div",
8160
+ {
8161
+ className: cn("text-sm", colorClass),
8162
+ children: [
8163
+ "• ",
8164
+ insight.message
8165
+ ]
8166
+ },
8167
+ index
8168
+ );
8169
+ }) })
8170
+ ] });
8171
+ };
8172
+ return /* @__PURE__ */ jsx(
8173
+ MetricsOverviewPanel,
8174
+ {
8175
+ ...props,
8176
+ footerSlot: /* @__PURE__ */ jsxs(Fragment, { children: [
8177
+ renderInsightsSection(),
8178
+ props.footerSlot
8179
+ ] })
8180
+ }
8181
+ );
8182
+ };
8183
+ const EntityListPanel = ({
8184
+ config,
8185
+ data,
8186
+ isLoading = false,
8187
+ onRowClick,
8188
+ onAction,
8189
+ className,
8190
+ columns: customColumns,
8191
+ showSearch = true,
8192
+ showPagination = true,
8193
+ pageSize = 10,
8194
+ searchPlaceholder,
8195
+ enableSelection = false,
8196
+ enableBulkActions = false,
8197
+ enableExport = true,
8198
+ enableFiltering = false,
8199
+ enableRefresh = true,
8200
+ renderToolbar,
8201
+ renderBulkActions,
8202
+ renderCustomColumn,
8203
+ renderEmptyState,
8204
+ headerSlot,
8205
+ footerSlot,
8206
+ onExport,
8207
+ onRefresh
8208
+ }) => {
8209
+ const [selectedItems, setSelectedItems] = React__default.useState([]);
8210
+ const [showFilters, setShowFilters] = React__default.useState(false);
8211
+ const tableColumns = useMemo(() => {
8212
+ if (customColumns) return customColumns;
8213
+ const generatedColumns = [];
8214
+ if (enableSelection) {
8215
+ generatedColumns.push({
8216
+ key: "__selection",
8217
+ header: /* @__PURE__ */ jsx(
8218
+ "input",
8219
+ {
8220
+ type: "checkbox",
8221
+ checked: selectedItems.length === data.length && data.length > 0,
8222
+ onChange: (e) => {
8223
+ if (e.target.checked) {
8224
+ setSelectedItems([...data]);
8225
+ } else {
8226
+ setSelectedItems([]);
8227
+ }
8228
+ }
8229
+ }
8230
+ ),
8231
+ cell: (item) => /* @__PURE__ */ jsx(
8232
+ "input",
8233
+ {
8234
+ type: "checkbox",
8235
+ checked: selectedItems.some((selected) => selected.id === item.id),
8236
+ onChange: (e) => {
8237
+ if (e.target.checked) {
8238
+ setSelectedItems((prev) => [...prev, item]);
8239
+ } else {
8240
+ setSelectedItems((prev) => prev.filter((selected) => selected.id !== item.id));
8241
+ }
8242
+ }
8243
+ }
8244
+ ),
8245
+ sortable: false,
8246
+ width: "50px"
8247
+ });
8248
+ }
8249
+ if (data.length > 0) {
8250
+ const sampleItem = data[0];
8251
+ Object.keys(sampleItem).forEach((key) => {
8252
+ if (key === "id") return;
8253
+ const isStatus = key.toLowerCase().includes("status");
8254
+ const isCategory = key.toLowerCase().includes("category") || key.toLowerCase().includes("type");
8255
+ const isDate = key.toLowerCase().includes("date") || key.toLowerCase().includes("time");
8256
+ const isAmount = key.toLowerCase().includes("amount") || key.toLowerCase().includes("price") || key.toLowerCase().includes("cost");
8257
+ generatedColumns.push({
8258
+ key,
8259
+ header: key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, " $1"),
8260
+ type: isStatus ? "status" : isCategory ? "category" : "default",
8261
+ sortable: true,
8262
+ cell: renderCustomColumn ? (item) => {
8263
+ const column = { key, header: "", type: isStatus ? "status" : isCategory ? "category" : "default" };
8264
+ const customContent = renderCustomColumn(column, item);
8265
+ if (customContent) return customContent;
8266
+ const value = item[key];
8267
+ if (isDate && value) {
8268
+ return new Date(value).toLocaleDateString();
8269
+ }
8270
+ if (isAmount && typeof value === "number") {
8271
+ return new Intl.NumberFormat("en-US", {
8272
+ style: "currency",
8273
+ currency: "USD"
8274
+ }).format(value);
8275
+ }
8276
+ return (value == null ? void 0 : value.toString()) || "-";
8277
+ } : void 0
8278
+ });
8279
+ });
8280
+ }
8281
+ return generatedColumns;
8282
+ }, [customColumns, data, enableSelection, selectedItems, renderCustomColumn]);
8283
+ const handleExport = () => {
8284
+ if (onExport) {
8285
+ onExport(selectedItems.length > 0 ? selectedItems : data);
8286
+ } else {
8287
+ const headers = tableColumns.filter((col) => col.key !== "__selection").map((col) => col.key);
8288
+ const csvContent = [
8289
+ headers.join(","),
8290
+ ...(selectedItems.length > 0 ? selectedItems : data).map(
8291
+ (item) => headers.map((header) => item[header] || "").join(",")
8292
+ )
8293
+ ].join("\n");
8294
+ const blob = new Blob([csvContent], { type: "text/csv" });
8295
+ const url = URL.createObjectURL(blob);
8296
+ const a = document.createElement("a");
8297
+ a.href = url;
8298
+ a.download = `${config.display.title.toLowerCase().replace(/\s+/g, "-")}-export.csv`;
8299
+ a.click();
8300
+ URL.revokeObjectURL(url);
8301
+ }
8302
+ };
8303
+ const renderToolbarSection = () => {
8304
+ var _a;
8305
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 mb-4", children: [
8306
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8307
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground", children: config.display.title }),
8308
+ config.display.description && /* @__PURE__ */ jsxs(Badge, { variant: "outline", className: "text-xs", children: [
8309
+ data.length,
8310
+ " items"
8311
+ ] })
8312
+ ] }),
8313
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8314
+ renderToolbar && renderToolbar(),
8315
+ enableFiltering && /* @__PURE__ */ jsxs(
8316
+ Button,
8317
+ {
8318
+ variant: "outline",
8319
+ size: "sm",
8320
+ onClick: () => setShowFilters(!showFilters),
8321
+ className: cn(showFilters && "bg-muted"),
8322
+ children: [
8323
+ /* @__PURE__ */ jsx(Filter, { className: "w-4 h-4 mr-2" }),
8324
+ "Filters"
8325
+ ]
8326
+ }
8327
+ ),
8328
+ enableRefresh && /* @__PURE__ */ jsxs(
8329
+ Button,
8330
+ {
8331
+ variant: "outline",
8332
+ size: "sm",
8333
+ onClick: onRefresh,
8334
+ disabled: isLoading,
8335
+ children: [
8336
+ /* @__PURE__ */ jsx(RefreshCw, { className: cn("w-4 h-4 mr-2", isLoading && "animate-spin") }),
8337
+ "Refresh"
8338
+ ]
8339
+ }
8340
+ ),
8341
+ enableExport && /* @__PURE__ */ jsxs(
8342
+ Button,
8343
+ {
8344
+ variant: "outline",
8345
+ size: "sm",
8346
+ onClick: handleExport,
8347
+ disabled: data.length === 0,
8348
+ children: [
8349
+ /* @__PURE__ */ jsx(Download, { className: "w-4 h-4 mr-2" }),
8350
+ "Export"
8351
+ ]
8352
+ }
8353
+ ),
8354
+ (_a = config.actions) == null ? void 0 : _a.filter((action) => action.type === "primary").map((action) => /* @__PURE__ */ jsxs(
8355
+ Button,
8356
+ {
8357
+ size: "sm",
8358
+ onClick: () => onAction == null ? void 0 : onAction(action, []),
8359
+ disabled: isLoading,
8360
+ children: [
8361
+ action.icon && /* @__PURE__ */ jsx(action.icon, { className: "w-4 h-4 mr-2" }),
8362
+ action.label
8363
+ ]
8364
+ },
8365
+ action.label
8366
+ ))
8367
+ ] })
8368
+ ] });
8369
+ };
8370
+ const renderBulkActionsSection = () => {
8371
+ var _a;
8372
+ if (!enableBulkActions || selectedItems.length === 0) return null;
8373
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between bg-muted/50 p-3 rounded-md mb-4", children: [
8374
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8375
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
8376
+ selectedItems.length,
8377
+ " items selected"
8378
+ ] }),
8379
+ /* @__PURE__ */ jsx(
8380
+ Button,
8381
+ {
8382
+ variant: "ghost",
8383
+ size: "sm",
8384
+ onClick: () => setSelectedItems([]),
8385
+ children: "Clear selection"
8386
+ }
8387
+ )
8388
+ ] }),
8389
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8390
+ renderBulkActions && renderBulkActions(selectedItems),
8391
+ (_a = config.actions) == null ? void 0 : _a.filter((action) => action.type !== "primary").map((action) => /* @__PURE__ */ jsxs(
8392
+ Button,
8393
+ {
8394
+ variant: action.type === "danger" ? "destructive" : "outline",
8395
+ size: "sm",
8396
+ onClick: () => onAction == null ? void 0 : onAction(action, selectedItems),
8397
+ children: [
8398
+ action.icon && /* @__PURE__ */ jsx(action.icon, { className: "w-4 h-4 mr-2" }),
8399
+ action.label
8400
+ ]
8401
+ },
8402
+ action.label
8403
+ ))
8404
+ ] })
8405
+ ] });
8406
+ };
8407
+ const renderEmptyStateSection = () => {
8408
+ var _a;
8409
+ if (data.length > 0) return null;
8410
+ if (renderEmptyState) {
8411
+ return renderEmptyState();
8412
+ }
8413
+ return /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
8414
+ /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground mb-4", children: [
8415
+ "No ",
8416
+ config.display.title.toLowerCase(),
8417
+ " found"
8418
+ ] }),
8419
+ ((_a = config.actions) == null ? void 0 : _a.find((action) => action.type === "primary")) && /* @__PURE__ */ jsxs(Button, { onClick: () => {
8420
+ var _a2;
8421
+ const primaryAction = (_a2 = config.actions) == null ? void 0 : _a2.find((action) => action.type === "primary");
8422
+ if (primaryAction) onAction == null ? void 0 : onAction(primaryAction, []);
8423
+ }, children: [
8424
+ /* @__PURE__ */ jsx(Plus, { className: "w-4 h-4 mr-2" }),
8425
+ "Add ",
8426
+ config.display.title.slice(0, -1)
8427
+ ] })
8428
+ ] });
8429
+ };
8430
+ return /* @__PURE__ */ jsxs(Card, { className: cn("p-6", className), category: config.display.category, "data-component-name": "EntityListPanel", children: [
8431
+ headerSlot,
8432
+ renderToolbarSection(),
8433
+ renderBulkActionsSection(),
8434
+ data.length === 0 ? renderEmptyStateSection() : /* @__PURE__ */ jsx(
8435
+ DataTable,
8436
+ {
8437
+ data,
8438
+ columns: tableColumns,
8439
+ isLoading,
8440
+ showSearch,
8441
+ showPagination,
8442
+ pageSize,
8443
+ searchPlaceholder: searchPlaceholder || `Search ${config.display.title.toLowerCase()}...`,
8444
+ onRowClick,
8445
+ hover: !!onRowClick,
8446
+ emptyMessage: `No ${config.display.title.toLowerCase()} found`
8447
+ }
8448
+ ),
8449
+ footerSlot
8450
+ ] });
8451
+ };
8452
+ const TrendAnalysisPanel = ({
8453
+ metrics,
8454
+ data,
8455
+ temporal,
8456
+ isLoading = false,
8457
+ className,
8458
+ category,
8459
+ defaultChartType = "line",
8460
+ dateField = "date",
8461
+ enablePeriodSelection = true,
8462
+ enableChartTypeSelection = true,
8463
+ enableMetricSelection = true,
8464
+ showComparisons = true,
8465
+ renderHeader,
8466
+ renderFooter,
8467
+ renderCustomChart,
8468
+ headerSlot,
8469
+ footerSlot,
8470
+ onMetricChange,
8471
+ onPeriodChange,
8472
+ onChartTypeChange,
8473
+ onExport
8474
+ }) => {
8475
+ const [selectedMetric, setSelectedMetric] = useState(metrics[0]);
8476
+ const [selectedPeriod, setSelectedPeriod] = useState((temporal == null ? void 0 : temporal.defaultCycle) || "monthly");
8477
+ const [selectedChartType, setSelectedChartType] = useState(defaultChartType);
8478
+ const [showForecast, setShowForecast] = useState(false);
8479
+ const trendData = useMemo(() => {
8480
+ if (!selectedMetric || !data.length) return [];
8481
+ const periods = selectedPeriod === "yearly" ? 5 : selectedPeriod === "quarterly" ? 8 : selectedPeriod === "monthly" ? 12 : selectedPeriod === "weekly" ? 12 : 30;
8482
+ return MetricCalculationEngine.calculateTrendData(
8483
+ selectedMetric,
8484
+ data,
8485
+ dateField,
8486
+ periods
8487
+ );
8488
+ }, [selectedMetric, data, dateField, selectedPeriod]);
8489
+ const chartData = useMemo(() => {
8490
+ return trendData.map((point) => ({
8491
+ label: point.label || point.date,
8492
+ value: point.value,
8493
+ category
8494
+ }));
8495
+ }, [trendData, category]);
8496
+ const trendPercentage = useMemo(() => {
8497
+ if (chartData.length < 2) return null;
8498
+ const first = chartData[0].value;
8499
+ const last = chartData[chartData.length - 1].value;
8500
+ if (first === 0) return null;
8501
+ return (last - first) / Math.abs(first) * 100;
8502
+ }, [chartData]);
8503
+ const forecastData = useMemo(() => {
8504
+ var _a, _b;
8505
+ if (!showForecast || !((_a = temporal == null ? void 0 : temporal.forecasting) == null ? void 0 : _a.enabled) || chartData.length < 3) {
8506
+ return [];
8507
+ }
8508
+ const periods = ((_b = temporal == null ? void 0 : temporal.forecasting) == null ? void 0 : _b.periods) || 3;
8509
+ const lastValue = chartData[chartData.length - 1].value;
8510
+ const trend = trendPercentage ? trendPercentage / 100 : 0;
8511
+ return Array.from({ length: periods }, (_, index) => ({
8512
+ label: `Future ${index + 1}`,
8513
+ value: lastValue * (1 + trend * (index + 1) / chartData.length),
8514
+ category: 8
8515
+ // Use category 8 for forecast
8516
+ }));
8517
+ }, [showForecast, temporal == null ? void 0 : temporal.forecasting, chartData, trendPercentage]);
8518
+ const combinedChartData = useMemo(() => {
8519
+ if (forecastData.length === 0) return chartData;
8520
+ return [...chartData, ...forecastData];
8521
+ }, [chartData, forecastData]);
8522
+ const handleMetricChange = (metricKey) => {
8523
+ const metric = metrics.find((m) => m.key === metricKey);
8524
+ if (metric) {
8525
+ setSelectedMetric(metric);
8526
+ onMetricChange == null ? void 0 : onMetricChange(metric);
8527
+ }
8528
+ };
8529
+ const handlePeriodChange = (period) => {
8530
+ setSelectedPeriod(period);
8531
+ onPeriodChange == null ? void 0 : onPeriodChange(period);
8532
+ };
8533
+ const handleChartTypeChange = (chartType) => {
8534
+ setSelectedChartType(chartType);
8535
+ onChartTypeChange == null ? void 0 : onChartTypeChange(chartType);
8536
+ };
8537
+ const handleExport = () => {
8538
+ if (onExport) {
8539
+ onExport(combinedChartData, selectedMetric);
8540
+ } else {
8541
+ const csvContent = [
8542
+ "Date,Value",
8543
+ ...combinedChartData.map((point) => `${point.label},${point.value}`)
8544
+ ].join("\n");
8545
+ const blob = new Blob([csvContent], { type: "text/csv" });
8546
+ const url = URL.createObjectURL(blob);
8547
+ const a = document.createElement("a");
8548
+ a.href = url;
8549
+ a.download = `${selectedMetric.label}-trend-data.csv`;
8550
+ a.click();
8551
+ URL.revokeObjectURL(url);
8552
+ }
8553
+ };
8554
+ const renderControls = () => {
8555
+ var _a;
8556
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
8557
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
8558
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8559
+ /* @__PURE__ */ jsx(TrendingUp, { className: "w-4 h-4 text-muted-foreground" }),
8560
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground", children: "Trend Analysis" })
8561
+ ] }),
8562
+ trendPercentage !== null && /* @__PURE__ */ jsxs(Badge, { variant: trendPercentage > 0 ? "default" : "destructive", children: [
8563
+ trendPercentage > 0 ? "+" : "",
8564
+ trendPercentage.toFixed(1),
8565
+ "%"
8566
+ ] })
8567
+ ] }),
8568
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8569
+ enableMetricSelection && metrics.length > 1 && /* @__PURE__ */ jsx(
8570
+ Select,
8571
+ {
8572
+ value: selectedMetric.key,
8573
+ onValueChange: handleMetricChange,
8574
+ children: metrics.map((metric) => /* @__PURE__ */ jsx("option", { value: metric.key, children: metric.label }, metric.key))
8575
+ }
8576
+ ),
8577
+ enablePeriodSelection && /* @__PURE__ */ jsx(
8578
+ Select,
8579
+ {
8580
+ value: selectedPeriod,
8581
+ onValueChange: (value) => handlePeriodChange(value),
8582
+ children: ((temporal == null ? void 0 : temporal.cycles) || ["daily", "weekly", "monthly", "quarterly", "yearly"]).map((cycle) => /* @__PURE__ */ jsx("option", { value: cycle, children: cycle.charAt(0).toUpperCase() + cycle.slice(1) }, cycle))
8583
+ }
8584
+ ),
8585
+ enableChartTypeSelection && /* @__PURE__ */ jsxs("div", { className: "flex items-center border rounded", children: [
8586
+ /* @__PURE__ */ jsx(
8587
+ Button,
8588
+ {
8589
+ variant: selectedChartType === "line" ? "default" : "ghost",
8590
+ size: "sm",
8591
+ onClick: () => handleChartTypeChange("line"),
8592
+ children: /* @__PURE__ */ jsx(LineChart, { className: "w-4 h-4" })
8593
+ }
8594
+ ),
8595
+ /* @__PURE__ */ jsx(
8596
+ Button,
8597
+ {
8598
+ variant: selectedChartType === "bar" ? "default" : "ghost",
8599
+ size: "sm",
8600
+ onClick: () => handleChartTypeChange("bar"),
8601
+ children: /* @__PURE__ */ jsx(BarChart3, { className: "w-4 h-4" })
8602
+ }
8603
+ ),
8604
+ /* @__PURE__ */ jsx(
8605
+ Button,
8606
+ {
8607
+ variant: selectedChartType === "area" ? "default" : "ghost",
8608
+ size: "sm",
8609
+ onClick: () => handleChartTypeChange("area"),
8610
+ children: /* @__PURE__ */ jsx(AreaChart, { className: "w-4 h-4" })
8611
+ }
8612
+ )
8613
+ ] }),
8614
+ ((_a = temporal == null ? void 0 : temporal.forecasting) == null ? void 0 : _a.enabled) && /* @__PURE__ */ jsx(
8615
+ Button,
8616
+ {
8617
+ variant: showForecast ? "default" : "outline",
8618
+ size: "sm",
8619
+ onClick: () => setShowForecast(!showForecast),
8620
+ children: "Forecast"
8621
+ }
8622
+ ),
8623
+ /* @__PURE__ */ jsx(
8624
+ Button,
8625
+ {
8626
+ variant: "outline",
8627
+ size: "sm",
8628
+ onClick: handleExport,
8629
+ disabled: chartData.length === 0,
8630
+ children: /* @__PURE__ */ jsx(Download, { className: "w-4 h-4" })
8631
+ }
8632
+ )
8633
+ ] })
8634
+ ] });
8635
+ };
8636
+ const renderChart = () => {
8637
+ if (renderCustomChart) {
8638
+ const customChart = renderCustomChart(selectedMetric, combinedChartData, selectedChartType);
8639
+ if (customChart) return customChart;
8640
+ }
8641
+ return /* @__PURE__ */ jsx(
8642
+ Chart,
8643
+ {
8644
+ title: selectedMetric.label,
8645
+ subtitle: `${selectedPeriod} trend analysis`,
8646
+ data: combinedChartData,
8647
+ type: selectedChartType,
8648
+ category,
8649
+ showTrend: true,
8650
+ trend: trendPercentage !== null ? {
8651
+ value: trendPercentage,
8652
+ label: "overall trend"
8653
+ } : void 0,
8654
+ height: "large",
8655
+ isLoading,
8656
+ noWrapper: true,
8657
+ showLegend: forecastData.length > 0
8658
+ }
8659
+ );
8660
+ };
8661
+ const renderComparisons = () => {
8662
+ var _a, _b;
8663
+ if (!showComparisons || !(temporal == null ? void 0 : temporal.enableComparisons) || chartData.length === 0) {
8664
+ return null;
8665
+ }
8666
+ const currentValue = ((_a = chartData[chartData.length - 1]) == null ? void 0 : _a.value) || 0;
8667
+ const previousValue = ((_b = chartData[chartData.length - 2]) == null ? void 0 : _b.value) || 0;
8668
+ const periodChange = previousValue !== 0 ? (currentValue - previousValue) / Math.abs(previousValue) * 100 : 0;
8669
+ return /* @__PURE__ */ jsxs("div", { className: "border-t pt-4 mt-4", children: [
8670
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-foreground mb-3", children: "Period Comparisons" }),
8671
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-4", children: [
8672
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
8673
+ /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold", children: currentValue.toFixed(0) }),
8674
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "Current" })
8675
+ ] }),
8676
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
8677
+ /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold", children: previousValue.toFixed(0) }),
8678
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "Previous" })
8679
+ ] }),
8680
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
8681
+ /* @__PURE__ */ jsxs("div", { className: cn(
8682
+ "text-2xl font-bold",
8683
+ periodChange > 0 ? "text-status-success" : periodChange < 0 ? "text-status-error" : "text-muted-foreground"
8684
+ ), children: [
8685
+ periodChange > 0 ? "+" : "",
8686
+ periodChange.toFixed(1),
8687
+ "%"
8688
+ ] }),
8689
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "Change" })
8690
+ ] })
8691
+ ] })
8692
+ ] });
8693
+ };
8694
+ return /* @__PURE__ */ jsxs(Card, { className: cn("p-6", className), category, "data-component-name": "TrendAnalysisPanel", children: [
8695
+ headerSlot,
8696
+ renderHeader && renderHeader(),
8697
+ renderControls(),
8698
+ renderChart(),
8699
+ renderComparisons(),
8700
+ renderFooter && renderFooter(),
8701
+ footerSlot
8702
+ ] });
8703
+ };
8704
+ const CategoryBreakdownPanel = ({
8705
+ data,
8706
+ categoryConfig,
8707
+ valueField,
8708
+ isLoading = false,
8709
+ className,
8710
+ category,
8711
+ title = "Category Breakdown",
8712
+ subtitle,
8713
+ defaultView = "both",
8714
+ defaultChartType = "pie",
8715
+ maxCategories = 8,
8716
+ showPercentages = true,
8717
+ enableDrillDown = true,
8718
+ renderHeader,
8719
+ renderFooter,
8720
+ renderCustomCategory,
8721
+ renderDrillDownContent,
8722
+ headerSlot,
8723
+ footerSlot,
8724
+ onCategoryClick,
8725
+ onDrillDown,
8726
+ onExport
8727
+ }) => {
8728
+ const [currentView, setCurrentView] = useState(defaultView);
8729
+ const [chartType, setChartType] = useState(defaultChartType);
8730
+ const [expandedCategories, setExpandedCategories] = useState(/* @__PURE__ */ new Set());
8731
+ const [drillDownLevel, setDrillDownLevel] = useState(0);
8732
+ const [drillDownPath, setDrillDownPath] = useState([]);
8733
+ const categoryBreakdown = useMemo(() => {
8734
+ var _a;
8735
+ if (!data.length) return [];
8736
+ const currentCategoryField = ((_a = categoryConfig == null ? void 0 : categoryConfig.hierarchy) == null ? void 0 : _a[drillDownLevel]) || (categoryConfig == null ? void 0 : categoryConfig.defaultGroupBy) || "category";
8737
+ return MetricCalculationEngine.calculateCategoryBreakdown(
8738
+ data,
8739
+ currentCategoryField,
8740
+ valueField,
8741
+ maxCategories
8742
+ );
8743
+ }, [data, categoryConfig, valueField, maxCategories, drillDownLevel]);
8744
+ const chartData = useMemo(() => {
8745
+ return categoryBreakdown.map((item, index) => ({
8746
+ label: item.category,
8747
+ value: item.value,
8748
+ category: index % 8 + 1
8749
+ }));
8750
+ }, [categoryBreakdown]);
8751
+ const totalValue = useMemo(() => {
8752
+ return categoryBreakdown.reduce((sum, item) => sum + item.value, 0);
8753
+ }, [categoryBreakdown]);
8754
+ const handleCategoryClick = (categoryItem) => {
8755
+ var _a;
8756
+ onCategoryClick == null ? void 0 : onCategoryClick(categoryItem);
8757
+ if (enableDrillDown && (categoryConfig == null ? void 0 : categoryConfig.enableDrillDown) && drillDownLevel < (((_a = categoryConfig == null ? void 0 : categoryConfig.hierarchy) == null ? void 0 : _a.length) || 0) - 1) {
8758
+ setDrillDownLevel((prev) => prev + 1);
8759
+ setDrillDownPath((prev) => [...prev, categoryItem.category]);
8760
+ onDrillDown == null ? void 0 : onDrillDown(categoryItem.category, drillDownLevel + 1);
8761
+ }
8762
+ };
8763
+ const handleDrillUp = (level) => {
8764
+ if (level < drillDownLevel) {
8765
+ setDrillDownLevel(level);
8766
+ setDrillDownPath((prev) => prev.slice(0, level));
8767
+ onDrillDown == null ? void 0 : onDrillDown(level > 0 ? drillDownPath[level - 1] : "", level);
8768
+ }
8769
+ };
8770
+ const toggleCategoryExpansion = (categoryName) => {
8771
+ setExpandedCategories((prev) => {
8772
+ const newSet = new Set(prev);
8773
+ if (newSet.has(categoryName)) {
8774
+ newSet.delete(categoryName);
8775
+ } else {
8776
+ newSet.add(categoryName);
8777
+ }
8778
+ return newSet;
8779
+ });
8780
+ };
8781
+ const handleExport = () => {
8782
+ if (onExport) {
8783
+ onExport(categoryBreakdown);
8784
+ } else {
8785
+ const csvContent = [
8786
+ "Category,Value,Percentage",
8787
+ ...categoryBreakdown.map(
8788
+ (item) => `${item.category},${item.value},${item.percentage.toFixed(2)}%`
8789
+ )
8790
+ ].join("\n");
8791
+ const blob = new Blob([csvContent], { type: "text/csv" });
8792
+ const url = URL.createObjectURL(blob);
8793
+ const a = document.createElement("a");
8794
+ a.href = url;
8795
+ a.download = `category-breakdown-${Date.now()}.csv`;
8796
+ a.click();
8797
+ URL.revokeObjectURL(url);
8798
+ }
8799
+ };
8800
+ const renderControls = () => {
8801
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
8802
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
8803
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8804
+ /* @__PURE__ */ jsx(PieChart, { className: "w-4 h-4 text-muted-foreground" }),
8805
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground", children: title })
8806
+ ] }),
8807
+ subtitle && /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs", children: subtitle }),
8808
+ totalValue > 0 && /* @__PURE__ */ jsxs(Badge, { variant: "outline", children: [
8809
+ "Total: ",
8810
+ new Intl.NumberFormat().format(totalValue)
8811
+ ] })
8812
+ ] }),
8813
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8814
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center border rounded", children: [
8815
+ /* @__PURE__ */ jsx(
8816
+ Button,
8817
+ {
8818
+ variant: currentView === "chart" ? "default" : "ghost",
8819
+ size: "sm",
8820
+ onClick: () => setCurrentView("chart"),
8821
+ children: /* @__PURE__ */ jsx(PieChart, { className: "w-4 h-4" })
8822
+ }
8823
+ ),
8824
+ /* @__PURE__ */ jsx(
8825
+ Button,
8826
+ {
8827
+ variant: currentView === "list" ? "default" : "ghost",
8828
+ size: "sm",
8829
+ onClick: () => setCurrentView("list"),
8830
+ children: /* @__PURE__ */ jsx(List, { className: "w-4 h-4" })
8831
+ }
8832
+ ),
8833
+ /* @__PURE__ */ jsx(
8834
+ Button,
8835
+ {
8836
+ variant: currentView === "both" ? "default" : "ghost",
8837
+ size: "sm",
8838
+ onClick: () => setCurrentView("both"),
8839
+ children: "Both"
8840
+ }
8841
+ )
8842
+ ] }),
8843
+ (currentView === "chart" || currentView === "both") && /* @__PURE__ */ jsxs("div", { className: "flex items-center border rounded", children: [
8844
+ /* @__PURE__ */ jsx(
8845
+ Button,
8846
+ {
8847
+ variant: chartType === "pie" ? "default" : "ghost",
8848
+ size: "sm",
8849
+ onClick: () => setChartType("pie"),
8850
+ children: /* @__PURE__ */ jsx(PieChart, { className: "w-4 h-4" })
8851
+ }
8852
+ ),
8853
+ /* @__PURE__ */ jsx(
8854
+ Button,
8855
+ {
8856
+ variant: chartType === "bar" ? "default" : "ghost",
8857
+ size: "sm",
8858
+ onClick: () => setChartType("bar"),
8859
+ children: /* @__PURE__ */ jsx(BarChart3, { className: "w-4 h-4" })
8860
+ }
8861
+ )
8862
+ ] }),
8863
+ /* @__PURE__ */ jsx(
8864
+ Button,
8865
+ {
8866
+ variant: "outline",
8867
+ size: "sm",
8868
+ onClick: handleExport,
8869
+ disabled: categoryBreakdown.length === 0,
8870
+ children: /* @__PURE__ */ jsx(Download, { className: "w-4 h-4" })
8871
+ }
8872
+ )
8873
+ ] })
8874
+ ] });
8875
+ };
8876
+ const renderBreadcrumb = () => {
8877
+ if (drillDownLevel === 0) return null;
8878
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-4 text-sm text-muted-foreground", children: [
8879
+ /* @__PURE__ */ jsx(
8880
+ Button,
8881
+ {
8882
+ variant: "ghost",
8883
+ size: "sm",
8884
+ onClick: () => handleDrillUp(0),
8885
+ className: "p-0 h-auto font-normal",
8886
+ children: "All"
8887
+ }
8888
+ ),
8889
+ drillDownPath.map((segment, index) => /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
8890
+ /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3" }),
8891
+ /* @__PURE__ */ jsx(
8892
+ Button,
8893
+ {
8894
+ variant: "ghost",
8895
+ size: "sm",
8896
+ onClick: () => handleDrillUp(index + 1),
8897
+ className: "p-0 h-auto font-normal",
8898
+ children: segment
8899
+ }
8900
+ )
8901
+ ] }, index))
8902
+ ] });
8903
+ };
8904
+ const renderChart = () => {
8905
+ if (currentView === "list") return null;
8906
+ return /* @__PURE__ */ jsx("div", { className: cn(currentView === "both" && "mb-6"), children: /* @__PURE__ */ jsx(
8907
+ Chart,
8908
+ {
8909
+ title: "",
8910
+ data: chartData,
8911
+ type: chartType,
8912
+ category,
8913
+ showLegend: true,
8914
+ height: "medium",
8915
+ isLoading,
8916
+ noWrapper: true,
8917
+ onClick: () => {
8918
+ }
8919
+ }
8920
+ ) });
8921
+ };
8922
+ const renderCategoryList = () => {
8923
+ if (currentView === "chart") return null;
8924
+ return /* @__PURE__ */ jsx("div", { className: "space-y-2", children: categoryBreakdown.map((item, index) => {
8925
+ if (renderCustomCategory) {
8926
+ const customContent = renderCustomCategory(item, index);
8927
+ if (customContent) return customContent;
8928
+ }
8929
+ const canExpand = enableDrillDown && categoryConfig.enableDrillDown && "subcategories" in item && item.subcategories && Array.isArray(item.subcategories) && item.subcategories.length > 0;
8930
+ const isExpanded = expandedCategories.has(item.category);
8931
+ return /* @__PURE__ */ jsxs("div", { className: "border rounded-lg", children: [
8932
+ /* @__PURE__ */ jsxs(
8933
+ "div",
8934
+ {
8935
+ className: cn(
8936
+ "flex items-center justify-between p-3 cursor-pointer hover:bg-muted/50",
8937
+ canExpand && "cursor-pointer"
8938
+ ),
8939
+ onClick: () => handleCategoryClick(item),
8940
+ children: [
8941
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
8942
+ canExpand && /* @__PURE__ */ jsx(
8943
+ Button,
8944
+ {
8945
+ variant: "ghost",
8946
+ size: "sm",
8947
+ className: "p-0 w-4 h-4",
8948
+ onClick: (e) => {
8949
+ e.stopPropagation();
8950
+ toggleCategoryExpansion(item.category);
8951
+ },
8952
+ children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3" })
8953
+ }
8954
+ ),
8955
+ /* @__PURE__ */ jsx(
8956
+ DataBadge,
8957
+ {
8958
+ variant: "category",
8959
+ category: index % 8 + 1,
8960
+ size: "sm",
8961
+ children: item.category
8962
+ }
8963
+ )
8964
+ ] }),
8965
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
8966
+ /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
8967
+ /* @__PURE__ */ jsx("div", { className: "font-semibold", children: new Intl.NumberFormat().format(item.value) }),
8968
+ showPercentages && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
8969
+ item.percentage.toFixed(1),
8970
+ "%"
8971
+ ] })
8972
+ ] }),
8973
+ /* @__PURE__ */ jsx("div", { className: "w-20 h-2 bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
8974
+ "div",
8975
+ {
8976
+ className: cn(
8977
+ "h-full transition-all duration-300",
8978
+ `bg-category-${index % 8 + 1}`
8979
+ ),
8980
+ style: { width: `${item.percentage}%` }
8981
+ }
8982
+ ) })
8983
+ ] })
8984
+ ]
8985
+ }
8986
+ ),
8987
+ canExpand && isExpanded && "subcategories" in item && item.subcategories && /* @__PURE__ */ jsx("div", { className: "border-t bg-muted/20", children: renderDrillDownContent ? renderDrillDownContent(item.category, item.subcategories) : /* @__PURE__ */ jsx("div", { className: "p-3 space-y-1", children: Array.isArray(item.subcategories) && item.subcategories.map((subItem) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm pl-4", children: [
8988
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: subItem.category }),
8989
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: new Intl.NumberFormat().format(subItem.value) })
8990
+ ] }, subItem.category)) }) })
8991
+ ] }, item.category);
8992
+ }) });
8993
+ };
8994
+ const renderEmptyState = () => {
8995
+ if (categoryBreakdown.length > 0) return null;
8996
+ return /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
8997
+ /* @__PURE__ */ jsx(Filter, { className: "w-8 h-8 text-muted-foreground mx-auto mb-4" }),
8998
+ /* @__PURE__ */ jsx("div", { className: "text-muted-foreground", children: "No category data available" })
8999
+ ] });
9000
+ };
9001
+ return /* @__PURE__ */ jsxs(Card, { className: cn("p-6", className), category, "data-component-name": "CategoryBreakdownPanel", children: [
9002
+ headerSlot,
9003
+ renderHeader && renderHeader(),
9004
+ renderControls(),
9005
+ renderBreadcrumb(),
9006
+ categoryBreakdown.length === 0 ? renderEmptyState() : /* @__PURE__ */ jsxs(Fragment, { children: [
9007
+ renderChart(),
9008
+ renderCategoryList()
9009
+ ] }),
9010
+ renderFooter && renderFooter(),
9011
+ footerSlot
9012
+ ] });
9013
+ };
9014
+ const EntityPerformanceDashboardTemplate = ({
9015
+ config,
9016
+ data,
9017
+ previousData,
9018
+ isLoading = false,
9019
+ className,
9020
+ layout = "standard",
9021
+ showInsights = true,
9022
+ showTrends = true,
9023
+ showCategories = true,
9024
+ renderCustomActions,
9025
+ renderAdditionalMetrics,
9026
+ renderCustomTrendChart,
9027
+ renderCustomCategoryView,
9028
+ headerSlot,
9029
+ footerSlot,
9030
+ metricsHeaderSlot,
9031
+ metricsFooterSlot,
9032
+ trendsHeaderSlot,
9033
+ trendsFooterSlot,
9034
+ categoriesHeaderSlot,
9035
+ categoriesFooterSlot,
9036
+ onMetricClick,
9037
+ onCategoryClick,
9038
+ onTrendPeriodChange,
9039
+ onExport
9040
+ }) => {
9041
+ const getLayoutClasses = () => {
9042
+ switch (layout) {
9043
+ case "compact":
9044
+ return "space-y-4";
9045
+ case "detailed":
9046
+ return "space-y-8";
9047
+ case "standard":
9048
+ default:
9049
+ return "space-y-6";
9050
+ }
9051
+ };
9052
+ const renderPageHeader = () => {
9053
+ return /* @__PURE__ */ jsx(
9054
+ SectionHeader,
9055
+ {
9056
+ title: config.display.title,
9057
+ description: config.display.description,
9058
+ category: config.display.category,
9059
+ actions: renderCustomActions ? renderCustomActions() : void 0
9060
+ }
9061
+ );
9062
+ };
9063
+ const renderMetricsSection = () => {
9064
+ if (!config.metrics.length) return null;
9065
+ const MetricsComponent = showInsights ? MetricsOverviewWithInsightsPanel : MetricsOverviewPanel;
9066
+ return /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
9067
+ metricsHeaderSlot,
9068
+ /* @__PURE__ */ jsx(
9069
+ MetricsComponent,
9070
+ {
9071
+ metrics: config.metrics,
9072
+ data,
9073
+ previousData,
9074
+ isLoading,
9075
+ onMetricClick,
9076
+ category: config.display.category,
9077
+ columns: layout === "compact" ? 2 : layout === "detailed" ? 4 : 3,
9078
+ headerSlot: renderAdditionalMetrics ? renderAdditionalMetrics() : void 0
9079
+ }
9080
+ ),
9081
+ metricsFooterSlot
9082
+ ] });
9083
+ };
9084
+ const renderTrendsSection = () => {
9085
+ if (!showTrends || !config.temporal || !config.metrics.length) return null;
9086
+ if (renderCustomTrendChart) {
9087
+ const customChart = renderCustomTrendChart(config, data);
9088
+ if (customChart) {
9089
+ return /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
9090
+ trendsHeaderSlot,
9091
+ customChart,
9092
+ trendsFooterSlot
9093
+ ] });
9094
+ }
9095
+ }
9096
+ return /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
9097
+ trendsHeaderSlot,
9098
+ /* @__PURE__ */ jsx(
9099
+ TrendAnalysisPanel,
9100
+ {
9101
+ metrics: config.metrics,
9102
+ data,
9103
+ temporal: config.temporal,
9104
+ isLoading,
9105
+ category: config.display.category,
9106
+ enablePeriodSelection: true,
9107
+ enableChartTypeSelection: layout === "detailed",
9108
+ showComparisons: layout !== "compact",
9109
+ onPeriodChange: onTrendPeriodChange,
9110
+ onExport: (chartData, metric) => onExport == null ? void 0 : onExport("trends", { chartData, metric })
9111
+ }
9112
+ ),
9113
+ trendsFooterSlot
9114
+ ] });
9115
+ };
9116
+ const renderCategoriesSection = () => {
9117
+ var _a;
9118
+ if (!showCategories || !config.categories || !data.length) return null;
9119
+ const valueField = ((_a = config.metrics.find((m) => m.type === "currency" || m.type === "count")) == null ? void 0 : _a.key) || Object.keys(data[0]).find((key) => typeof data[0][key] === "number") || "value";
9120
+ if (renderCustomCategoryView) {
9121
+ const customView = renderCustomCategoryView(config, data);
9122
+ if (customView) {
9123
+ return /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
9124
+ categoriesHeaderSlot,
9125
+ customView,
9126
+ categoriesFooterSlot
9127
+ ] });
9128
+ }
9129
+ }
9130
+ return /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
9131
+ categoriesHeaderSlot,
9132
+ /* @__PURE__ */ jsx(
9133
+ CategoryBreakdownPanel,
9134
+ {
9135
+ data,
9136
+ categoryConfig: config.categories,
9137
+ valueField,
9138
+ isLoading,
9139
+ category: config.display.category,
9140
+ title: `${config.display.title} by ${config.categories.defaultGroupBy}`,
9141
+ defaultView: layout === "compact" ? "list" : "both",
9142
+ enableDrillDown: config.categories.enableDrillDown,
9143
+ onCategoryClick,
9144
+ onExport: (categoryData) => onExport == null ? void 0 : onExport("categories", categoryData)
9145
+ }
9146
+ ),
9147
+ categoriesFooterSlot
9148
+ ] });
9149
+ };
9150
+ const renderLayoutContent = () => {
9151
+ const sections = [
9152
+ renderMetricsSection(),
9153
+ renderTrendsSection(),
9154
+ renderCategoriesSection()
9155
+ ].filter(Boolean);
9156
+ if (layout === "detailed" && sections.length > 1) {
9157
+ const [metricsSection, ...otherSections] = sections;
9158
+ return /* @__PURE__ */ jsxs("div", { className: getLayoutClasses(), children: [
9159
+ metricsSection,
9160
+ otherSections.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: otherSections })
9161
+ ] });
9162
+ }
9163
+ return /* @__PURE__ */ jsx("div", { className: getLayoutClasses(), children: sections });
9164
+ };
9165
+ return /* @__PURE__ */ jsx(AppLayout, { children: /* @__PURE__ */ jsxs(
9166
+ PageTemplate,
9167
+ {
9168
+ className: cn("container mx-auto px-4 py-6", className),
9169
+ "data-component-name": "EntityPerformanceDashboardTemplate",
9170
+ children: [
9171
+ headerSlot,
9172
+ renderPageHeader(),
9173
+ renderLayoutContent(),
9174
+ footerSlot
9175
+ ]
9176
+ }
9177
+ ) });
9178
+ };
9179
+ const EntityPerformanceDashboardTemplateWithRealTime = ({
9180
+ enableRealTime = false,
9181
+ refreshInterval = 3e4,
9182
+ // 30 seconds
9183
+ onDataUpdate,
9184
+ ...props
9185
+ }) => {
9186
+ React__default.useEffect(() => {
9187
+ if (!enableRealTime) return;
9188
+ const interval = setInterval(() => {
9189
+ if (onDataUpdate) {
9190
+ onDataUpdate(props.data);
9191
+ }
9192
+ }, refreshInterval);
9193
+ return () => clearInterval(interval);
9194
+ }, [enableRealTime, refreshInterval, onDataUpdate, props.data]);
9195
+ return /* @__PURE__ */ jsx(EntityPerformanceDashboardTemplate, { ...props });
9196
+ };
9197
+ const EntityManagementTemplate = ({
9198
+ config,
9199
+ data,
9200
+ isLoading = false,
9201
+ className,
9202
+ enableSearch = true,
9203
+ enableFiltering = true,
9204
+ enableBulkActions = true,
9205
+ enableExport = true,
9206
+ pageSize = 10,
9207
+ onCreate,
9208
+ onUpdate,
9209
+ onDelete,
9210
+ onBulkDelete,
9211
+ onView,
9212
+ renderCreateForm,
9213
+ renderEditForm,
9214
+ renderDetailView,
9215
+ renderCustomActions,
9216
+ renderEmptyState,
9217
+ renderFilterPanel,
9218
+ headerSlot,
9219
+ footerSlot,
9220
+ toolbarSlot,
9221
+ listHeaderSlot,
9222
+ listFooterSlot,
9223
+ onRefresh,
9224
+ onFilter,
9225
+ onExport
9226
+ }) => {
9227
+ const [showCreateModal, setShowCreateModal] = useState(false);
9228
+ const [showEditModal, setShowEditModal] = useState(false);
9229
+ const [showDetailModal, setShowDetailModal] = useState(false);
9230
+ const [showFilterPanel, setShowFilterPanel] = useState(false);
9231
+ const [selectedItem, setSelectedItem] = useState(null);
9232
+ const [selectedItems, setSelectedItems] = useState([]);
9233
+ const handleCreate = async (item) => {
9234
+ if (onCreate) {
9235
+ try {
9236
+ await onCreate(item);
9237
+ setShowCreateModal(false);
9238
+ onRefresh == null ? void 0 : onRefresh();
9239
+ } catch (error) {
9240
+ console.error("Create failed:", error);
9241
+ }
9242
+ }
9243
+ };
9244
+ const handleUpdate = async (item) => {
9245
+ if (onUpdate && selectedItem) {
9246
+ try {
9247
+ await onUpdate(selectedItem.id, item);
9248
+ setShowEditModal(false);
9249
+ setSelectedItem(null);
9250
+ onRefresh == null ? void 0 : onRefresh();
9251
+ } catch (error) {
9252
+ console.error("Update failed:", error);
9253
+ }
9254
+ }
9255
+ };
9256
+ const handleBulkDelete = async () => {
9257
+ if (onBulkDelete && selectedItems.length > 0 && confirm(`Are you sure you want to delete ${selectedItems.length} ${config.display.title.toLowerCase()}?`)) {
9258
+ try {
9259
+ const ids = selectedItems.map((item) => item.id);
9260
+ await onBulkDelete(ids);
9261
+ setSelectedItems([]);
9262
+ onRefresh == null ? void 0 : onRefresh();
9263
+ } catch (error) {
9264
+ console.error("Bulk delete failed:", error);
9265
+ }
9266
+ }
9267
+ };
9268
+ const handleView = (item) => {
9269
+ if (onView) {
9270
+ onView(item);
9271
+ } else {
9272
+ setSelectedItem(item);
9273
+ setShowDetailModal(true);
9274
+ }
9275
+ };
9276
+ const handleEdit = (item) => {
9277
+ setSelectedItem(item);
9278
+ setShowEditModal(true);
9279
+ };
9280
+ const handleRowClick = (item) => {
9281
+ handleView(item);
9282
+ };
9283
+ const handleAction = (action, selectedItems2) => {
9284
+ action.onClick({ selectedItems: selectedItems2, config });
9285
+ };
9286
+ const generateDefaultActions = () => {
9287
+ const actions = [];
9288
+ if (onCreate) {
9289
+ actions.push({
9290
+ label: `Add ${config.display.title.slice(0, -1)}`,
9291
+ type: "primary",
9292
+ icon: Plus,
9293
+ onClick: () => setShowCreateModal(true)
9294
+ });
9295
+ }
9296
+ return actions;
9297
+ };
9298
+ const renderPageHeader = () => {
9299
+ const actions = [
9300
+ ...generateDefaultActions(),
9301
+ ...config.actions || []
9302
+ ];
9303
+ return /* @__PURE__ */ jsx(
9304
+ SectionHeader,
9305
+ {
9306
+ title: config.display.title,
9307
+ description: config.display.description,
9308
+ category: config.display.category,
9309
+ actions: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9310
+ renderCustomActions && renderCustomActions(),
9311
+ enableFiltering && /* @__PURE__ */ jsxs(
9312
+ Button,
9313
+ {
9314
+ variant: "outline",
9315
+ size: "sm",
9316
+ onClick: () => setShowFilterPanel(!showFilterPanel),
9317
+ className: cn(showFilterPanel && "bg-muted"),
9318
+ children: [
9319
+ /* @__PURE__ */ jsx(Filter, { className: "w-4 h-4 mr-2" }),
9320
+ "Filters"
9321
+ ]
9322
+ }
9323
+ ),
9324
+ enableExport && /* @__PURE__ */ jsxs(
9325
+ Button,
9326
+ {
9327
+ variant: "outline",
9328
+ size: "sm",
9329
+ onClick: () => onExport == null ? void 0 : onExport(selectedItems.length > 0 ? selectedItems : data, "csv"),
9330
+ disabled: data.length === 0,
9331
+ children: [
9332
+ /* @__PURE__ */ jsx(Download, { className: "w-4 h-4 mr-2" }),
9333
+ "Export"
9334
+ ]
9335
+ }
9336
+ ),
9337
+ actions.map((action) => /* @__PURE__ */ jsxs(
9338
+ Button,
9339
+ {
9340
+ variant: action.type === "primary" ? "default" : "outline",
9341
+ size: "sm",
9342
+ onClick: () => action.onClick({ data, config }),
9343
+ children: [
9344
+ action.icon && /* @__PURE__ */ jsx(action.icon, { className: "w-4 h-4 mr-2" }),
9345
+ action.label
9346
+ ]
9347
+ },
9348
+ action.label
9349
+ ))
9350
+ ] })
9351
+ }
9352
+ );
9353
+ };
9354
+ const renderToolbar = () => {
9355
+ if (selectedItems.length === 0) return null;
9356
+ return /* @__PURE__ */ jsx("div", { className: "bg-muted/50 p-4 rounded-lg mb-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
9357
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9358
+ /* @__PURE__ */ jsxs(Badge, { variant: "secondary", children: [
9359
+ selectedItems.length,
9360
+ " selected"
9361
+ ] }),
9362
+ /* @__PURE__ */ jsx(
9363
+ Button,
9364
+ {
9365
+ variant: "ghost",
9366
+ size: "sm",
9367
+ onClick: () => setSelectedItems([]),
9368
+ children: "Clear selection"
9369
+ }
9370
+ )
9371
+ ] }),
9372
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9373
+ onBulkDelete && /* @__PURE__ */ jsxs(
9374
+ Button,
9375
+ {
9376
+ variant: "destructive",
9377
+ size: "sm",
9378
+ onClick: handleBulkDelete,
9379
+ children: [
9380
+ /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4 mr-2" }),
9381
+ "Delete Selected"
9382
+ ]
9383
+ }
9384
+ ),
9385
+ enableExport && /* @__PURE__ */ jsxs(
9386
+ Button,
9387
+ {
9388
+ variant: "outline",
9389
+ size: "sm",
9390
+ onClick: () => onExport == null ? void 0 : onExport(selectedItems, "csv"),
9391
+ children: [
9392
+ /* @__PURE__ */ jsx(Download, { className: "w-4 h-4 mr-2" }),
9393
+ "Export Selected"
9394
+ ]
9395
+ }
9396
+ )
9397
+ ] })
9398
+ ] }) });
9399
+ };
9400
+ const renderFilterPanelSection = () => {
9401
+ if (!showFilterPanel) return null;
9402
+ return /* @__PURE__ */ jsx(Card, { className: "p-4 mb-4", children: renderFilterPanel ? renderFilterPanel(onFilter || (() => {
9403
+ })) : /* @__PURE__ */ jsx("div", { className: "text-center text-muted-foreground py-4", children: "Filter functionality not implemented yet" }) });
9404
+ };
9405
+ const renderCreateModal = () => {
9406
+ if (!showCreateModal) return null;
9407
+ return /* @__PURE__ */ jsx(
9408
+ Modal,
9409
+ {
9410
+ isOpen: showCreateModal,
9411
+ onClose: () => setShowCreateModal(false),
9412
+ title: `Create ${config.display.title.slice(0, -1)}`,
9413
+ category: config.display.category,
9414
+ children: renderCreateForm ? renderCreateForm(handleCreate, () => setShowCreateModal(false)) : /* @__PURE__ */ jsx("div", { className: "p-6 text-center text-muted-foreground", children: "Create form not implemented yet" })
9415
+ }
9416
+ );
9417
+ };
9418
+ const renderEditModal = () => {
9419
+ if (!showEditModal || !selectedItem) return null;
9420
+ return /* @__PURE__ */ jsx(
9421
+ Modal,
9422
+ {
9423
+ isOpen: showEditModal,
9424
+ onClose: () => {
9425
+ setShowEditModal(false);
9426
+ setSelectedItem(null);
9427
+ },
9428
+ title: `Edit ${config.display.title.slice(0, -1)}`,
9429
+ category: config.display.category,
9430
+ children: renderEditForm ? renderEditForm(
9431
+ selectedItem,
9432
+ handleUpdate,
9433
+ () => {
9434
+ setShowEditModal(false);
9435
+ setSelectedItem(null);
9436
+ }
9437
+ ) : /* @__PURE__ */ jsx("div", { className: "p-6 text-center text-muted-foreground", children: "Edit form not implemented yet" })
9438
+ }
9439
+ );
9440
+ };
9441
+ const renderDetailModal = () => {
9442
+ if (!showDetailModal || !selectedItem) return null;
9443
+ return /* @__PURE__ */ jsx(
9444
+ Modal,
9445
+ {
9446
+ isOpen: showDetailModal,
9447
+ onClose: () => {
9448
+ setShowDetailModal(false);
9449
+ setSelectedItem(null);
9450
+ },
9451
+ title: `${config.display.title.slice(0, -1)} Details`,
9452
+ category: config.display.category,
9453
+ size: "large",
9454
+ children: renderDetailView ? renderDetailView(
9455
+ selectedItem,
9456
+ () => {
9457
+ setShowDetailModal(false);
9458
+ handleEdit(selectedItem);
9459
+ },
9460
+ () => {
9461
+ setShowDetailModal(false);
9462
+ setSelectedItem(null);
9463
+ }
9464
+ ) : /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsx("div", { className: "space-y-4", children: Object.entries(selectedItem).map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9465
+ /* @__PURE__ */ jsxs("span", { className: "font-medium capitalize", children: [
9466
+ key,
9467
+ ":"
9468
+ ] }),
9469
+ /* @__PURE__ */ jsx("span", { children: (value == null ? void 0 : value.toString()) || "-" })
9470
+ ] }, key)) }) })
9471
+ }
9472
+ );
9473
+ };
9474
+ return /* @__PURE__ */ jsx(AppLayout, { children: /* @__PURE__ */ jsxs(
9475
+ PageTemplate,
9476
+ {
9477
+ className: cn("container mx-auto px-4 py-6", className),
9478
+ "data-component-name": "EntityManagementTemplate",
9479
+ children: [
9480
+ headerSlot,
9481
+ renderPageHeader(),
9482
+ toolbarSlot,
9483
+ renderFilterPanelSection(),
9484
+ renderToolbar(),
9485
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
9486
+ listHeaderSlot,
9487
+ /* @__PURE__ */ jsx(
9488
+ EntityListPanel,
9489
+ {
9490
+ config,
9491
+ data,
9492
+ isLoading,
9493
+ onRowClick: handleRowClick,
9494
+ onAction: handleAction,
9495
+ enableSelection: enableBulkActions,
9496
+ enableBulkActions,
9497
+ enableExport,
9498
+ enableRefresh: !!onRefresh,
9499
+ showSearch: enableSearch,
9500
+ showPagination: true,
9501
+ pageSize,
9502
+ renderEmptyState,
9503
+ onExport,
9504
+ onRefresh
9505
+ }
9506
+ ),
9507
+ listFooterSlot
9508
+ ] }),
9509
+ renderCreateModal(),
9510
+ renderEditModal(),
9511
+ renderDetailModal(),
9512
+ footerSlot
9513
+ ]
9514
+ }
9515
+ ) });
9516
+ };
9517
+ const financialConfig = {
9518
+ entityType: "transactional",
9519
+ display: {
9520
+ title: "Financial Dashboard",
9521
+ description: "Personal finance overview and transaction management",
9522
+ category: 2
9523
+ // Green theme for financial success
9524
+ },
9525
+ metrics: [
9526
+ {
9527
+ key: "totalBalance",
9528
+ label: "Total Balance",
9529
+ type: "currency",
9530
+ trend: true,
9531
+ icon: DollarSign,
9532
+ aggregation: "sum"
9533
+ },
9534
+ {
9535
+ key: "monthlyIncome",
9536
+ label: "Monthly Income",
9537
+ type: "currency",
9538
+ trend: true,
9539
+ icon: TrendingUp,
9540
+ aggregation: "sum"
9541
+ },
9542
+ {
9543
+ key: "monthlyExpenses",
9544
+ label: "Monthly Expenses",
9545
+ type: "currency",
9546
+ trend: true,
9547
+ icon: Wallet,
9548
+ aggregation: "sum"
9549
+ },
9550
+ {
9551
+ key: "savingsRate",
9552
+ label: "Savings Rate",
9553
+ type: "percentage",
9554
+ target: 20,
9555
+ icon: Target
9556
+ }
9557
+ ],
9558
+ temporal: {
9559
+ cycles: ["monthly", "quarterly", "yearly"],
9560
+ defaultCycle: "monthly",
9561
+ enableComparisons: true,
9562
+ forecasting: {
9563
+ enabled: true,
9564
+ periods: 3,
9565
+ algorithm: "seasonal"
9566
+ }
9567
+ },
9568
+ categories: {
9569
+ hierarchy: ["account", "category", "type"],
9570
+ defaultGroupBy: "category",
9571
+ enableDrillDown: true,
9572
+ colorCoding: true
9573
+ },
9574
+ actions: [
9575
+ {
9576
+ label: "Add Transaction",
9577
+ type: "primary",
9578
+ onClick: ({ data, config }) => {
9579
+ console.log("Adding new transaction", { data, config });
9580
+ }
9581
+ },
9582
+ {
9583
+ label: "Generate Report",
9584
+ type: "secondary",
9585
+ onClick: ({ selectedItems, data, config }) => {
9586
+ console.log("Generating report", { selectedItems, data, config });
9587
+ }
9588
+ }
9589
+ ]
9590
+ };
9591
+ const sampleFinancialData = [
9592
+ {
9593
+ id: "1",
9594
+ amount: 5e3,
9595
+ category: "Salary",
9596
+ account: "Checking",
9597
+ date: "2024-01-15",
9598
+ description: "Monthly salary",
9599
+ type: "income",
9600
+ status: "completed"
9601
+ },
9602
+ {
9603
+ id: "2",
9604
+ amount: -1200,
9605
+ category: "Rent",
9606
+ account: "Checking",
9607
+ date: "2024-01-01",
9608
+ description: "Monthly rent payment",
9609
+ type: "expense",
9610
+ status: "completed"
9611
+ },
9612
+ {
9613
+ id: "3",
9614
+ amount: -300,
9615
+ category: "Groceries",
9616
+ account: "Checking",
9617
+ date: "2024-01-10",
9618
+ description: "Weekly groceries",
9619
+ type: "expense",
9620
+ status: "completed"
9621
+ },
9622
+ {
9623
+ id: "4",
9624
+ amount: -80,
9625
+ category: "Utilities",
9626
+ account: "Checking",
9627
+ date: "2024-01-05",
9628
+ description: "Electric bill",
9629
+ type: "expense",
9630
+ status: "completed"
9631
+ },
9632
+ {
9633
+ id: "5",
9634
+ amount: -45,
9635
+ category: "Entertainment",
9636
+ account: "Checking",
9637
+ date: "2024-01-12",
9638
+ description: "Movie tickets",
9639
+ type: "expense",
9640
+ status: "completed"
9641
+ }
9642
+ ];
7741
9643
  function createReactApp(config) {
7742
9644
  const appConfig = typeof config === "string" ? { title: config } : config;
7743
9645
  const {
@@ -10038,6 +11940,7 @@ export {
10038
11940
  CardFooter,
10039
11941
  CardHeader,
10040
11942
  CardTitle,
11943
+ CategoryBreakdownPanel,
10041
11944
  Chart,
10042
11945
  ColorSwatch,
10043
11946
  ComponentShowcasePage,
@@ -10049,6 +11952,7 @@ export {
10049
11952
  DashboardCard,
10050
11953
  DashboardGrid,
10051
11954
  DashboardTemplate,
11955
+ DashboardWithSidePanel,
10052
11956
  DataBadge,
10053
11957
  DataDetailTemplate,
10054
11958
  DataTable,
@@ -10071,6 +11975,10 @@ export {
10071
11975
  DropdownMenuSubTrigger,
10072
11976
  DropdownMenuTrigger,
10073
11977
  EmptyState,
11978
+ EntityListPanel,
11979
+ EntityManagementTemplate,
11980
+ EntityPerformanceDashboardTemplate,
11981
+ EntityPerformanceDashboardTemplateWithRealTime,
10074
11982
  ErrorBoundary,
10075
11983
  FileUpload,
10076
11984
  FormField,
@@ -10082,6 +11990,9 @@ export {
10082
11990
  Loading,
10083
11991
  LoginForm,
10084
11992
  LogoutButton,
11993
+ MetricCalculationEngine,
11994
+ MetricsOverviewPanel,
11995
+ MetricsOverviewWithInsightsPanel,
10085
11996
  Modal,
10086
11997
  NavMenu,
10087
11998
  PageTemplate,
@@ -10091,6 +12002,7 @@ export {
10091
12002
  ProtectedRoute,
10092
12003
  RESPONSIVE_CHART_HEIGHTS,
10093
12004
  ROUTES,
12005
+ SalesPanel,
10094
12006
  SearchInput,
10095
12007
  SectionHeader,
10096
12008
  Select,
@@ -10121,6 +12033,7 @@ export {
10121
12033
  Toast,
10122
12034
  ToastContainer,
10123
12035
  Tooltip,
12036
+ TrendAnalysisPanel,
10124
12037
  UI_CONFIG,
10125
12038
  UserAvatar,
10126
12039
  UserMenu,
@@ -10130,12 +12043,14 @@ export {
10130
12043
  createReactApp,
10131
12044
  createSimpleApp,
10132
12045
  env,
12046
+ financialConfig,
10133
12047
  formatNumberWithTooltip,
10134
12048
  getAnimationClasses,
10135
12049
  getChartHeight,
10136
12050
  getContainerHeightClass,
10137
12051
  interactionVariants,
10138
12052
  legacyPatterns,
12053
+ sampleFinancialData,
10139
12054
  setGlobalAuthService,
10140
12055
  tooltipContent,
10141
12056
  useApiMutation,