@elevasis/ui 1.19.0 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/api/index.js +2 -2
  2. package/dist/auth/index.js +3 -3
  3. package/dist/charts/index.css +14 -0
  4. package/dist/charts/index.js +8 -6
  5. package/dist/{chunk-7ATCF6UL.js → chunk-3DIU726S.js} +11 -4
  6. package/dist/chunk-4SY4EQSK.js +68 -0
  7. package/dist/{chunk-2Z7LYTIX.js → chunk-AQ5MQDSS.js} +30 -17
  8. package/dist/chunk-AWMZCYKH.js +639 -0
  9. package/dist/{chunk-BVNAC4SQ.js → chunk-C7AD6N23.js} +38 -48
  10. package/dist/{chunk-ZFCG5SHW.js → chunk-COTI2QPO.js} +1 -1
  11. package/dist/{chunk-WAPZN2U3.js → chunk-EMN755L5.js} +7 -41
  12. package/dist/{chunk-LBY7FVFD.js → chunk-ERVB3QJQ.js} +31 -715
  13. package/dist/chunk-GBMNCNHX.js +105 -0
  14. package/dist/{chunk-MBZDE6UT.js → chunk-IOKL7BKE.js} +9 -1
  15. package/dist/{chunk-35UWYH2A.js → chunk-JFRG2JJE.js} +8 -2
  16. package/dist/chunk-JIABC3AE.js +2622 -0
  17. package/dist/chunk-JZEXFQ6N.js +671 -0
  18. package/dist/chunk-LGKLC5MG.js +44 -0
  19. package/dist/chunk-MG3NF7QL.js +63 -0
  20. package/dist/{chunk-KBLGVZBD.js → chunk-NNKKBSJN.js} +2 -22
  21. package/dist/{chunk-JNBHUCKW.js → chunk-NVOCKXUQ.js} +1 -1
  22. package/dist/chunk-OFAXUZPZ.js +2411 -0
  23. package/dist/chunk-PDHTXPSF.js +12 -0
  24. package/dist/chunk-QJ2S46NI.js +23 -0
  25. package/dist/{chunk-NUULWBAD.js → chunk-R3R367QY.js} +1 -1
  26. package/dist/{chunk-UANJP5P7.js → chunk-R7WLWGPO.js} +5 -5
  27. package/dist/{chunk-CC3SDRIF.js → chunk-RWQIFKMJ.js} +1 -1
  28. package/dist/chunk-UMFPUM7Q.js +1281 -0
  29. package/dist/{chunk-KNJKCD73.js → chunk-VLTVZXP6.js} +4 -4
  30. package/dist/chunk-WWEMNIHW.js +37 -0
  31. package/dist/{chunk-UTWJZEOJ.js → chunk-XOTN3X3Z.js} +3 -3
  32. package/dist/components/index.css +14 -0
  33. package/dist/components/index.d.ts +41 -7
  34. package/dist/components/index.js +564 -5023
  35. package/dist/components/navigation/index.js +2 -63
  36. package/dist/features/auth/index.css +579 -0
  37. package/dist/features/auth/index.d.ts +2557 -0
  38. package/dist/features/auth/index.js +125 -0
  39. package/dist/features/dashboard/index.css +579 -0
  40. package/dist/features/dashboard/index.d.ts +244 -0
  41. package/dist/features/dashboard/index.js +650 -0
  42. package/dist/features/monitoring/index.css +579 -0
  43. package/dist/features/monitoring/index.d.ts +121 -0
  44. package/dist/features/monitoring/index.js +538 -0
  45. package/dist/features/operations/index.css +14 -0
  46. package/dist/features/operations/index.d.ts +1675 -2
  47. package/dist/features/operations/index.js +2148 -28
  48. package/dist/features/settings/index.css +579 -0
  49. package/dist/features/settings/index.d.ts +2589 -0
  50. package/dist/features/settings/index.js +1437 -0
  51. package/dist/hooks/index.css +14 -0
  52. package/dist/hooks/index.d.ts +29 -11
  53. package/dist/hooks/index.js +13 -13
  54. package/dist/hooks/published.css +14 -0
  55. package/dist/hooks/published.d.ts +29 -11
  56. package/dist/hooks/published.js +12 -12
  57. package/dist/index.css +14 -0
  58. package/dist/index.d.ts +41 -12
  59. package/dist/index.js +15 -15
  60. package/dist/initialization/index.js +2 -2
  61. package/dist/layout/index.d.ts +7 -1
  62. package/dist/layout/index.js +7 -5
  63. package/dist/organization/index.js +2 -2
  64. package/dist/provider/index.css +14 -0
  65. package/dist/provider/index.d.ts +1 -1
  66. package/dist/provider/index.js +10 -10
  67. package/dist/provider/published.d.ts +1 -1
  68. package/dist/provider/published.js +6 -6
  69. package/dist/theme/index.d.ts +1 -1
  70. package/dist/theme/index.js +3 -3
  71. package/dist/theme/presets/__tests__/getPreset.test.d.ts +2 -0
  72. package/dist/theme/presets/__tests__/getPreset.test.d.ts.map +1 -0
  73. package/dist/theme/presets/__tests__/getPreset.test.js +92 -0
  74. package/dist/theme/presets/cyber-volt.d.ts +12 -0
  75. package/dist/theme/presets/cyber-volt.d.ts.map +1 -0
  76. package/dist/theme/presets/cyber-volt.js +70 -0
  77. package/dist/theme/presets/regal.d.ts +8 -0
  78. package/dist/theme/presets/regal.d.ts.map +1 -0
  79. package/dist/theme/presets/regal.js +69 -0
  80. package/dist/theme/presets/rose-gold.d.ts +12 -0
  81. package/dist/theme/presets/rose-gold.d.ts.map +1 -0
  82. package/dist/theme/presets/rose-gold.js +76 -0
  83. package/dist/types/index.d.ts +1 -1
  84. package/dist/utils/index.d.ts +12 -1
  85. package/dist/utils/index.js +1 -1
  86. package/dist/zustand/index.d.ts +80 -0
  87. package/dist/zustand/index.js +105 -0
  88. package/package.json +55 -4
  89. package/dist/chunk-2YW3LDFT.js +0 -1542
  90. package/dist/theme/presets/cyber-void.d.ts +0 -12
  91. package/dist/theme/presets/cyber-void.d.ts.map +0 -1
  92. package/dist/theme/presets/cyber-void.js +0 -75
  93. package/dist/{chunk-DVKEEY5J.js → chunk-TUXTSEAF.js} +1 -1
  94. package/dist/{chunk-U2522LSW.js → chunk-V7XHGJQZ.js} +1 -1
@@ -0,0 +1,1281 @@
1
+ import { FilterBar } from './chunk-PDHTXPSF.js';
2
+ import { CyberAreaChart } from './chunk-ERVB3QJQ.js';
3
+ import { APIErrorAlert, CardHeader, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, EmptyState } from './chunk-AWMZCYKH.js';
4
+ import { useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, useMarkAsRead } from './chunk-AQ5MQDSS.js';
5
+ import { formatBucketTime } from './chunk-LXHZYSMQ.js';
6
+ import { formatDuration } from './chunk-XA34RETF.js';
7
+ import { PAGE_SIZE_DEFAULT } from './chunk-IOKL7BKE.js';
8
+ import { useRouterContext } from './chunk-Q7DJKLEN.js';
9
+ import { Table, Text, Badge, Tooltip, Select, TextInput, Button, Card, Stack, Group, Paper, Center, Loader, ActionIcon, SegmentedControl, NumberFormatter, Box, Alert, Title, Switch, Pagination, UnstyledButton } from '@mantine/core';
10
+ import { IconCircleCheck, IconThumbDown, IconThumbUp, IconClock, IconCircleX, IconSearch, IconFilterOff, IconArrowUpRight, IconAlertTriangle, IconAlertCircle, IconExternalLink, IconChartPie, IconHeartbeat, IconDownload, IconCpu, IconTrendingUp, IconChartBar, IconCash, IconInfoCircle, IconBug, IconChecks, IconCircle, IconCircleFilled, IconArrowUp, IconArrowDown, IconFileOff, IconRobot, IconKey, IconUser } from '@tabler/icons-react';
11
+ import { jsxs, jsx } from 'react/jsx-runtime';
12
+ import { formatDistanceToNow } from 'date-fns';
13
+ import { useState } from 'react';
14
+
15
+ function formatStartTime(timestamp) {
16
+ return new Date(timestamp).toLocaleString("en-US", {
17
+ month: "short",
18
+ day: "numeric",
19
+ hour: "numeric",
20
+ minute: "2-digit"
21
+ });
22
+ }
23
+ function getStatusConfig(status) {
24
+ switch (status) {
25
+ case "running":
26
+ return {
27
+ icon: /* @__PURE__ */ jsx(IconCircle, { size: 14, color: "var(--color-primary)" }),
28
+ label: "Running",
29
+ color: "blue"
30
+ };
31
+ case "completed":
32
+ return {
33
+ icon: /* @__PURE__ */ jsx(IconCircleCheck, { size: 14, color: "var(--color-success)" }),
34
+ label: "Completed",
35
+ color: "green"
36
+ };
37
+ case "failed":
38
+ return {
39
+ icon: /* @__PURE__ */ jsx(IconCircleX, { size: 14, color: "var(--color-error)" }),
40
+ label: "Failed",
41
+ color: "red"
42
+ };
43
+ case "warning":
44
+ return {
45
+ icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 14, color: "var(--color-warning)" }),
46
+ label: "Warning",
47
+ color: "yellow"
48
+ };
49
+ case "pending":
50
+ default:
51
+ return {
52
+ icon: /* @__PURE__ */ jsx(IconCircle, { size: 14, color: "var(--mantine-color-gray-6)" }),
53
+ label: "Pending",
54
+ color: "gray"
55
+ };
56
+ }
57
+ }
58
+ function LoadingState() {
59
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "md" }) });
60
+ }
61
+ function EmptyState2() {
62
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "xs", children: [
63
+ /* @__PURE__ */ jsx(IconFileOff, { size: 48, color: "var(--color-text-subtle)" }),
64
+ /* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, c: "dimmed", children: "No executions found" }),
65
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Executions will appear here when workflows or agents are run" })
66
+ ] }) });
67
+ }
68
+ function ExecutionLogsTable({ executions, isLoading, onRowClick }) {
69
+ const handleRowClick = (execution) => {
70
+ onRowClick?.({
71
+ resourceType: execution.resourceType,
72
+ resourceId: execution.resourceId,
73
+ executionId: execution.id
74
+ });
75
+ };
76
+ return /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
77
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
78
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
79
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
80
+ /* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
81
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Duration" }),
82
+ /* @__PURE__ */ jsx(Table.Th, { ta: "center", children: "Env" }),
83
+ /* @__PURE__ */ jsx(Table.Th, { ta: "center", children: "Version" })
84
+ ] }) }),
85
+ /* @__PURE__ */ jsx(Table.Tbody, { children: isLoading ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: 6, children: /* @__PURE__ */ jsx(LoadingState, {}) }) }) : executions.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: 6, children: /* @__PURE__ */ jsx(EmptyState2, {}) }) }) : executions.map((execution) => {
86
+ const statusConfig3 = getStatusConfig(execution.status);
87
+ return /* @__PURE__ */ jsxs(
88
+ Table.Tr,
89
+ {
90
+ style: { cursor: onRowClick ? "pointer" : void 0 },
91
+ onClick: () => handleRowClick(execution),
92
+ children: [
93
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 200 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", lineClamp: 1, title: execution.resourceName, children: execution.resourceName }) }),
94
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: statusConfig3.color, variant: "light", size: "sm", leftSection: statusConfig3.icon, children: statusConfig3.label }) }),
95
+ /* @__PURE__ */ jsx(Table.Td, { style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Text, { size: "sm", children: formatStartTime(execution.startTime) }) }),
96
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: execution.status === "running" ? "dimmed" : void 0, children: formatDuration(execution.duration) }) }),
97
+ /* @__PURE__ */ jsx(Table.Td, { ta: "center", children: /* @__PURE__ */ jsx(Badge, { color: execution.resourceStatus === "prod" ? "green" : "gray", variant: "light", size: "sm", children: execution.resourceStatus.toUpperCase() }) }),
98
+ /* @__PURE__ */ jsx(Table.Td, { ta: "center", children: /* @__PURE__ */ jsx(
99
+ Tooltip,
100
+ {
101
+ label: `Resource: ${execution.resourceVersion ?? "-"}
102
+ API: ${execution.apiVersion ?? "-"}
103
+ SDK: ${execution.sdkVersion ?? "-"}`,
104
+ multiline: true,
105
+ position: "left",
106
+ children: /* @__PURE__ */ jsx(Text, { size: "sm", ff: "monospace", c: "dimmed", style: { cursor: "help" }, children: execution.resourceVersion ?? "-" })
107
+ }
108
+ ) })
109
+ ]
110
+ },
111
+ execution.id
112
+ );
113
+ }) })
114
+ ] });
115
+ }
116
+ var statusConfig = {
117
+ success: { color: "green", icon: IconCircleCheck },
118
+ failure: { color: "red", icon: IconCircleX },
119
+ pending: { color: "yellow", icon: IconClock },
120
+ approved: { color: "green", icon: IconThumbUp },
121
+ rejected: { color: "red", icon: IconThumbDown },
122
+ completed: { color: "blue", icon: IconCircleCheck }
123
+ };
124
+ var activityTypeLabels = {
125
+ workflow_execution: "Workflow",
126
+ agent_run: "Agent",
127
+ hitl_action: "HITL Action",
128
+ webhook_received: "Webhook In",
129
+ webhook_executed: "Webhook Out",
130
+ webhook_failed: "Webhook Fail",
131
+ credential_change: "Credential",
132
+ api_key_change: "API Key",
133
+ deployment_change: "Deployment",
134
+ membership_change: "Membership"
135
+ };
136
+ function getActorDisplay(actorType) {
137
+ switch (actorType) {
138
+ case "user":
139
+ return { label: "User", color: "blue", icon: IconUser };
140
+ case "api_key":
141
+ return { label: "API Key", color: "violet", icon: IconKey };
142
+ default:
143
+ return { label: "System", color: "gray", icon: IconRobot };
144
+ }
145
+ }
146
+ var COLUMN_COUNT = 6;
147
+ function LoadingState2() {
148
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "md" }) });
149
+ }
150
+ function EmptyState3() {
151
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "xs", children: [
152
+ /* @__PURE__ */ jsx(IconFileOff, { size: 48, color: "var(--color-text-subtle)" }),
153
+ /* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, c: "dimmed", children: "No activities found" }),
154
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Activities will appear here as workflows and agents run" })
155
+ ] }) });
156
+ }
157
+ function ActivityTable({ activities, isLoading, onRowClick }) {
158
+ return /* @__PURE__ */ jsxs(Table, { children: [
159
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
160
+ /* @__PURE__ */ jsx(Table.Th, { children: "Title" }),
161
+ /* @__PURE__ */ jsx(Table.Th, { children: "Type" }),
162
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
163
+ /* @__PURE__ */ jsx(Table.Th, { children: "Actor" }),
164
+ /* @__PURE__ */ jsx(Table.Th, { children: "Entity" }),
165
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Time" })
166
+ ] }) }),
167
+ /* @__PURE__ */ jsx(Table.Tbody, { children: isLoading ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: COLUMN_COUNT, children: /* @__PURE__ */ jsx(LoadingState2, {}) }) }) : activities.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: COLUMN_COUNT, children: /* @__PURE__ */ jsx(EmptyState3, {}) }) }) : activities.map((activity) => {
168
+ const config = statusConfig[activity.status];
169
+ const StatusIcon = config.icon;
170
+ const actor = getActorDisplay(activity.actorType);
171
+ const ActorIcon = actor.icon;
172
+ return /* @__PURE__ */ jsxs(
173
+ Table.Tr,
174
+ {
175
+ style: { cursor: onRowClick ? "pointer" : void 0 },
176
+ onClick: () => onRowClick?.(activity),
177
+ children: [
178
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 250 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", lineClamp: 1, title: activity.title, children: activity.title }) }),
179
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", size: "sm", color: "gray", children: activityTypeLabels[activity.activityType] }) }),
180
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: config.color, variant: "light", size: "sm", leftSection: /* @__PURE__ */ jsx(StatusIcon, { size: 14 }), children: activity.status }) }),
181
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: actor.color, variant: "light", size: "sm", leftSection: /* @__PURE__ */ jsx(ActorIcon, { size: 14 }), children: actor.label }) }),
182
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 200 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", lineClamp: 1, title: activity.entityName || activity.entityId, children: activity.entityName || activity.entityId }) }),
183
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatDistanceToNow(activity.occurredAt, { addSuffix: true }) }) })
184
+ ]
185
+ },
186
+ activity.id
187
+ );
188
+ }) })
189
+ ] });
190
+ }
191
+ var activityTypeOptions = [
192
+ { value: "all", label: "All Types" },
193
+ { value: "workflow_execution", label: "Workflow Executions" },
194
+ { value: "agent_run", label: "Agent Runs" },
195
+ { value: "hitl_action", label: "HITL Actions" },
196
+ { value: "webhook_received", label: "Webhook Received" },
197
+ { value: "webhook_executed", label: "Webhook Executed" },
198
+ { value: "webhook_failed", label: "Webhook Failed" },
199
+ { value: "credential_change", label: "Credential Changes" },
200
+ { value: "api_key_change", label: "API Key Changes" },
201
+ { value: "deployment_change", label: "Deployment Changes" },
202
+ { value: "membership_change", label: "Membership Changes" }
203
+ ];
204
+ var statusOptions = [
205
+ { value: "all", label: "All Statuses" },
206
+ { value: "success", label: "Success" },
207
+ { value: "failure", label: "Failure" },
208
+ { value: "pending", label: "Pending" },
209
+ { value: "approved", label: "Approved" },
210
+ { value: "rejected", label: "Rejected" },
211
+ { value: "completed", label: "Completed" }
212
+ ];
213
+ function ActivityFilters({ filters, onFilterChange, onReset }) {
214
+ return /* @__PURE__ */ jsxs(
215
+ FilterBar,
216
+ {
217
+ actions: /* @__PURE__ */ jsx(Button, { variant: "subtle", color: "gray", leftSection: /* @__PURE__ */ jsx(IconFilterOff, { size: 16 }), onClick: onReset, children: "Reset" }),
218
+ children: [
219
+ /* @__PURE__ */ jsx(
220
+ Select,
221
+ {
222
+ placeholder: "Activity Type",
223
+ data: activityTypeOptions,
224
+ value: filters.activityType || "all",
225
+ onChange: (value) => onFilterChange("activityType", value),
226
+ style: { flex: 1, minWidth: 200 }
227
+ }
228
+ ),
229
+ /* @__PURE__ */ jsx(
230
+ Select,
231
+ {
232
+ placeholder: "Status",
233
+ data: statusOptions,
234
+ value: filters.status || "all",
235
+ onChange: (value) => onFilterChange("status", value),
236
+ style: { flex: 1, minWidth: 150 }
237
+ }
238
+ ),
239
+ /* @__PURE__ */ jsx(
240
+ TextInput,
241
+ {
242
+ placeholder: "Search by name...",
243
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
244
+ value: filters.search || "",
245
+ onChange: (event) => onFilterChange("search", event.currentTarget.value),
246
+ style: { flex: 1, minWidth: 200 }
247
+ }
248
+ )
249
+ ]
250
+ }
251
+ );
252
+ }
253
+ var statusConfig2 = {
254
+ success: { color: "green", icon: IconCircleCheck },
255
+ failure: { color: "red", icon: IconCircleX },
256
+ pending: { color: "yellow", icon: IconClock },
257
+ approved: { color: "green", icon: IconThumbUp },
258
+ rejected: { color: "red", icon: IconThumbDown },
259
+ completed: { color: "blue", icon: IconCircleCheck }
260
+ };
261
+ function getActorDisplay2(actorType) {
262
+ switch (actorType) {
263
+ case "user":
264
+ return { label: "User", color: "blue", icon: IconUser };
265
+ case "api_key":
266
+ return { label: "API Key", color: "violet", icon: IconKey };
267
+ default:
268
+ return { label: "System", color: "gray", icon: IconRobot };
269
+ }
270
+ }
271
+ function getNavigationPath(activity) {
272
+ switch (activity.activityType) {
273
+ case "workflow_execution":
274
+ return `/operations/resources/workflow/${activity.entityId}`;
275
+ case "agent_run":
276
+ return `/operations/resources/agent/${activity.entityId}`;
277
+ case "hitl_action":
278
+ return "/command-queue";
279
+ case "credential_change":
280
+ return "/settings/credentials";
281
+ case "api_key_change":
282
+ return "/settings/api-keys";
283
+ case "deployment_change":
284
+ return "/settings/deployments";
285
+ case "membership_change":
286
+ return "/settings/organization";
287
+ default:
288
+ return null;
289
+ }
290
+ }
291
+ function ActivityCard({ activity }) {
292
+ const config = statusConfig2[activity.status];
293
+ const StatusIcon = config.icon;
294
+ const { navigate } = useRouterContext();
295
+ const navigationPath = getNavigationPath(activity);
296
+ const isClickable = navigationPath !== null;
297
+ const actor = getActorDisplay2(activity.actorType);
298
+ const ActorIcon = actor.icon;
299
+ const handleClick = () => {
300
+ if (navigationPath) {
301
+ navigate(navigationPath);
302
+ }
303
+ };
304
+ return /* @__PURE__ */ jsx(
305
+ Card,
306
+ {
307
+ withBorder: true,
308
+ style: {
309
+ cursor: isClickable ? "pointer" : "default",
310
+ transition: "box-shadow var(--duration-fast) var(--easing)"
311
+ },
312
+ onClick: handleClick,
313
+ children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
314
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
315
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", style: { flex: 1, minWidth: 0 }, children: [
316
+ /* @__PURE__ */ jsx(StatusIcon, { size: 16, color: `var(--mantine-color-${config.color}-6)` }),
317
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, style: { flex: 1, fontFamily: "var(--elevasis-font-family-subtitle)" }, truncate: true, children: activity.title })
318
+ ] }),
319
+ /* @__PURE__ */ jsx(Badge, { size: "sm", color: config.color, variant: "light", children: activity.status })
320
+ ] }),
321
+ activity.description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: activity.description }),
322
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
323
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, style: { flex: 1 }, children: activity.entityName || activity.entityId }),
324
+ /* @__PURE__ */ jsx(Badge, { size: "xs", color: actor.color, variant: "dot", leftSection: /* @__PURE__ */ jsx(ActorIcon, { size: 10 }), children: actor.label }),
325
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { whiteSpace: "nowrap" }, children: formatDistanceToNow(activity.occurredAt, { addSuffix: true }) })
326
+ ] })
327
+ ] })
328
+ }
329
+ );
330
+ }
331
+ function ErrorAnalysisCard({ data, isLoading, error }) {
332
+ const topFailures = data?.topFailingResources.map((res) => ({
333
+ id: res.resourceId,
334
+ name: res.name,
335
+ errorCount: res.errorCount,
336
+ failureRate: res.failureRate
337
+ })) ?? [];
338
+ if (error) {
339
+ return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load error analysis metrics" });
340
+ }
341
+ if (isLoading) {
342
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
343
+ }
344
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
345
+ /* @__PURE__ */ jsx(
346
+ CardHeader,
347
+ {
348
+ icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 18 }),
349
+ title: "Error Analysis",
350
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
351
+ }
352
+ ),
353
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "sm", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Top Failing Resources" }),
354
+ /* @__PURE__ */ jsxs(Table, { children: [
355
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
356
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
357
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Errors" }),
358
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "% Failed" }),
359
+ /* @__PURE__ */ jsx(Table.Th, {})
360
+ ] }) }),
361
+ /* @__PURE__ */ jsx(Table.Tbody, { children: topFailures.map((resource) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
362
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
363
+ /* @__PURE__ */ jsx(IconAlertCircle, { size: 16, color: "var(--color-error)" }),
364
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: resource.name })
365
+ ] }) }),
366
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Badge, { color: "red", variant: "light", children: resource.errorCount }) }),
367
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: resource.failureRate > 10 ? "red" : "dimmed", children: [
368
+ resource.failureRate,
369
+ "%"
370
+ ] }) }),
371
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 }) }) })
372
+ ] }, resource.id)) })
373
+ ] })
374
+ ] });
375
+ }
376
+ function ExecutionBreakdownTable({ data, isLoading, error }) {
377
+ if (error) {
378
+ return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load execution breakdown" });
379
+ }
380
+ if (isLoading) {
381
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
382
+ }
383
+ const totalExecutions = data?.totalExecutions ?? 0;
384
+ const statusCounts = data?.statusCounts ?? { success: 0, failed: 0, pending: 0, warning: 0 };
385
+ const p95Duration = data?.p95Duration ?? 0;
386
+ const statusRows = [
387
+ {
388
+ status: "Completed",
389
+ count: statusCounts.success,
390
+ percentage: totalExecutions > 0 ? statusCounts.success / totalExecutions * 100 : 0,
391
+ avgDuration: p95Duration * 0.85,
392
+ // Estimate avg duration from P95
393
+ color: "green"
394
+ },
395
+ {
396
+ status: "Warning",
397
+ count: statusCounts.warning,
398
+ percentage: totalExecutions > 0 ? statusCounts.warning / totalExecutions * 100 : 0,
399
+ avgDuration: p95Duration * 0.85,
400
+ // Warning executions completed, similar to success
401
+ color: "yellow"
402
+ },
403
+ {
404
+ status: "Failed",
405
+ count: statusCounts.failed,
406
+ percentage: totalExecutions > 0 ? statusCounts.failed / totalExecutions * 100 : 0,
407
+ avgDuration: p95Duration * 0.6,
408
+ // Failed executions typically shorter
409
+ color: "red"
410
+ },
411
+ {
412
+ status: "Running",
413
+ count: 0,
414
+ // No running count in current data structure
415
+ percentage: 0,
416
+ avgDuration: 0,
417
+ color: "blue"
418
+ },
419
+ {
420
+ status: "Pending",
421
+ count: statusCounts.pending,
422
+ percentage: totalExecutions > 0 ? statusCounts.pending / totalExecutions * 100 : 0,
423
+ avgDuration: 0,
424
+ // Pending has no duration
425
+ color: "gray"
426
+ }
427
+ ];
428
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
429
+ /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconChartPie, { size: 18 }), title: "Execution Status Breakdown" }),
430
+ /* @__PURE__ */ jsxs(Table, { children: [
431
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
432
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
433
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Count" }),
434
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Percentage" }),
435
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Avg Duration" })
436
+ ] }) }),
437
+ /* @__PURE__ */ jsx(Table.Tbody, { children: statusRows.map((row) => /* @__PURE__ */ jsxs(
438
+ Table.Tr,
439
+ {
440
+ style: { cursor: "pointer" },
441
+ onClick: () => {
442
+ console.log(`Filter to ${row.status} executions`);
443
+ },
444
+ children: [
445
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: row.color, variant: "light", children: row.status }) }),
446
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: row.count.toLocaleString() }) }),
447
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
448
+ row.percentage.toFixed(1),
449
+ "%"
450
+ ] }) }),
451
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: row.avgDuration > 0 ? `${(row.avgDuration / 1e3).toFixed(1)}s` : "-" }) })
452
+ ]
453
+ },
454
+ row.status
455
+ )) })
456
+ ] })
457
+ ] });
458
+ }
459
+ function ExecutionHealthCard({ data, isLoading, error }) {
460
+ const successRate = data?.successRate ?? 0;
461
+ const p95Duration = data?.p95Duration ?? 0;
462
+ const totalExecutions = data?.totalExecutions ?? 0;
463
+ const failedCount = data?.statusCounts.failed ?? 0;
464
+ const warningCount = data?.statusCounts.warning ?? 0;
465
+ const trendData = data?.trendData.map((d) => ({
466
+ hour: formatBucketTime(d.time, data?.granularity ?? "hour"),
467
+ errors: d.errorCount,
468
+ warnings: d.warningCount
469
+ })) ?? [];
470
+ const hasExecutions = totalExecutions > 0;
471
+ const statusColor = hasExecutions ? successRate >= 98 ? "green" : successRate >= 95 ? "yellow" : "red" : "gray";
472
+ const statusLabel = hasExecutions ? successRate >= 98 ? "Healthy" : successRate >= 95 ? "Warning" : "Critical" : "No Data";
473
+ if (error) {
474
+ return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load execution health metrics" });
475
+ }
476
+ if (isLoading) {
477
+ return /* @__PURE__ */ jsx(StatsCardSkeleton, {});
478
+ }
479
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
480
+ /* @__PURE__ */ jsx(
481
+ CardHeader,
482
+ {
483
+ icon: /* @__PURE__ */ jsx(IconHeartbeat, { size: 18 }),
484
+ title: "Execution Health",
485
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
486
+ }
487
+ ),
488
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", mb: "md", children: [
489
+ /* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
490
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
491
+ /* @__PURE__ */ jsx(
492
+ Text,
493
+ {
494
+ size: "xl",
495
+ fw: 700,
496
+ c: "var(--color-error)",
497
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
498
+ children: failedCount
499
+ }
500
+ ),
501
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "failures" })
502
+ ] }),
503
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
504
+ /* @__PURE__ */ jsx(
505
+ Text,
506
+ {
507
+ size: "xl",
508
+ fw: 700,
509
+ c: warningCount > 0 ? "yellow" : "dimmed",
510
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
511
+ children: warningCount
512
+ }
513
+ ),
514
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "warnings" })
515
+ ] }),
516
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
517
+ /* @__PURE__ */ jsxs(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: [
518
+ (p95Duration / 1e3).toFixed(1),
519
+ "s"
520
+ ] }),
521
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "P95" })
522
+ ] })
523
+ ] }),
524
+ /* @__PURE__ */ jsx(Badge, { size: "md", variant: "dot", color: statusColor, children: statusLabel })
525
+ ] }),
526
+ /* @__PURE__ */ jsx(
527
+ CyberAreaChart,
528
+ {
529
+ data: trendData,
530
+ series: [
531
+ { dataKey: "warnings", color: "yellow", name: "Warnings" },
532
+ { dataKey: "errors", color: "red", name: "Errors" }
533
+ ],
534
+ xDataKey: "hour",
535
+ height: 200,
536
+ yDomain: [0, "auto"]
537
+ }
538
+ ),
539
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", mt: "sm", children: [
540
+ totalExecutions.toLocaleString(),
541
+ " total executions"
542
+ ] })
543
+ ] });
544
+ }
545
+ var resourceOptions = [{ value: "", label: "All Resources" }];
546
+ var statusOptions2 = [
547
+ { value: "all", label: "All" },
548
+ { value: "running", label: "Running" },
549
+ { value: "completed", label: "Completed" },
550
+ { value: "warning", label: "Warning" },
551
+ { value: "failed", label: "Failed" }
552
+ ];
553
+ var environmentOptions = [
554
+ { value: "all", label: "All" },
555
+ { value: "dev", label: "Dev" },
556
+ { value: "prod", label: "Prod" }
557
+ ];
558
+ function ExecutionLogsFilters({ filters, onFilterChange, onReset }) {
559
+ const hasActiveFilters = filters.resourceId !== void 0 || filters.status !== "all" || filters.resourceStatus !== "all";
560
+ return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "wrap", children: [
561
+ /* @__PURE__ */ jsx(
562
+ Select,
563
+ {
564
+ placeholder: "Resource",
565
+ data: resourceOptions,
566
+ value: filters.resourceId ?? "",
567
+ onChange: (value) => onFilterChange("resourceId", value === "" || value === null ? void 0 : value),
568
+ style: { minWidth: 180 }
569
+ }
570
+ ),
571
+ /* @__PURE__ */ jsx(
572
+ SegmentedControl,
573
+ {
574
+ data: statusOptions2,
575
+ value: filters.status,
576
+ onChange: (value) => onFilterChange("status", value)
577
+ }
578
+ ),
579
+ /* @__PURE__ */ jsx(
580
+ SegmentedControl,
581
+ {
582
+ data: environmentOptions,
583
+ value: filters.resourceStatus,
584
+ onChange: (value) => onFilterChange("resourceStatus", value)
585
+ }
586
+ ),
587
+ hasActiveFilters && /* @__PURE__ */ jsx(Button, { variant: "subtle", color: "gray", leftSection: /* @__PURE__ */ jsx(IconFilterOff, { size: 16 }), onClick: onReset, children: "Reset" })
588
+ ] }) });
589
+ }
590
+ function CostByModelTable({ data, isLoading, error }) {
591
+ const [sortField, setSortField] = useState("cost");
592
+ const [sortDirection, setSortDirection] = useState("desc");
593
+ const totalCost = data?.totalCostUsd ?? 0;
594
+ const tableData = data?.models.map((m) => ({
595
+ model: m.model,
596
+ cost: m.totalCostUsd,
597
+ percentage: totalCost > 0 ? m.totalCostUsd / totalCost * 100 : 0,
598
+ calls: m.callCount,
599
+ avgCost: m.avgCostPerCall,
600
+ inputTokens: m.totalInputTokens,
601
+ outputTokens: m.totalOutputTokens
602
+ })) ?? [];
603
+ const sortedData = [...tableData].sort((a, b) => {
604
+ const aValue = a[sortField];
605
+ const bValue = b[sortField];
606
+ if (typeof aValue === "string" && typeof bValue === "string") {
607
+ return sortDirection === "asc" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
608
+ }
609
+ return sortDirection === "asc" ? aValue - bValue : bValue - aValue;
610
+ });
611
+ const highestCost = Math.max(...tableData.map((d) => d.cost), 0);
612
+ const handleSort = (field) => {
613
+ if (sortField === field) {
614
+ setSortDirection(sortDirection === "asc" ? "desc" : "asc");
615
+ } else {
616
+ setSortField(field);
617
+ setSortDirection("desc");
618
+ }
619
+ };
620
+ const handleExport = () => {
621
+ if (!data) return;
622
+ const csvContent = [
623
+ ["Model", "Cost ($)", "Percentage (%)", "Calls", "Avg Cost/Call ($)", "Input Tokens", "Output Tokens"],
624
+ ...sortedData.map((d) => [
625
+ d.model,
626
+ d.cost.toFixed(4),
627
+ d.percentage.toFixed(2),
628
+ d.calls,
629
+ d.avgCost.toFixed(6),
630
+ d.inputTokens,
631
+ d.outputTokens
632
+ ]),
633
+ ["Total", totalCost.toFixed(4), "100.00", data.totalCallCount, "", "", ""]
634
+ ].map((row) => row.join(",")).join("\n");
635
+ const blob = new Blob([csvContent], { type: "text/csv" });
636
+ const url = URL.createObjectURL(blob);
637
+ const link = document.createElement("a");
638
+ link.href = url;
639
+ link.download = `cost-by-model-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`;
640
+ link.click();
641
+ URL.revokeObjectURL(url);
642
+ };
643
+ const SortIcon = ({ field }) => {
644
+ if (sortField !== field) return null;
645
+ return sortDirection === "asc" ? /* @__PURE__ */ jsx(IconArrowUp, { size: 14 }) : /* @__PURE__ */ jsx(IconArrowDown, { size: 14 });
646
+ };
647
+ const formatModelName = (model) => {
648
+ const parts = model.split("/");
649
+ const modelName = parts.length > 1 ? parts[1] : model;
650
+ return modelName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
651
+ };
652
+ if (error) {
653
+ return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load cost by model" });
654
+ }
655
+ if (isLoading) {
656
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
657
+ }
658
+ return /* @__PURE__ */ jsxs(Paper, { children: [
659
+ /* @__PURE__ */ jsx(
660
+ CardHeader,
661
+ {
662
+ icon: /* @__PURE__ */ jsx(IconCpu, { size: 18 }),
663
+ title: "Cost by Model",
664
+ rightSection: /* @__PURE__ */ jsx(Button, { variant: "subtle", size: "xs", leftSection: /* @__PURE__ */ jsx(IconDownload, { size: 14 }), onClick: handleExport, children: "Export CSV" })
665
+ }
666
+ ),
667
+ /* @__PURE__ */ jsxs(Table, { children: [
668
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
669
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("model"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
670
+ "Model",
671
+ /* @__PURE__ */ jsx(SortIcon, { field: "model" })
672
+ ] }) }),
673
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("cost"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
674
+ "Cost",
675
+ /* @__PURE__ */ jsx(SortIcon, { field: "cost" })
676
+ ] }) }),
677
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("percentage"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
678
+ "Percentage",
679
+ /* @__PURE__ */ jsx(SortIcon, { field: "percentage" })
680
+ ] }) }),
681
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("calls"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
682
+ "Calls",
683
+ /* @__PURE__ */ jsx(SortIcon, { field: "calls" })
684
+ ] }) }),
685
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("avgCost"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
686
+ "Avg Cost/Call",
687
+ /* @__PURE__ */ jsx(SortIcon, { field: "avgCost" })
688
+ ] }) })
689
+ ] }) }),
690
+ /* @__PURE__ */ jsxs(Table.Tbody, { children: [
691
+ sortedData.map((row) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
692
+ /* @__PURE__ */ jsxs(Table.Td, { children: [
693
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: row.cost === highestCost ? 600 : 400, children: formatModelName(row.model) }),
694
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: row.model })
695
+ ] }),
696
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", fw: row.cost === highestCost ? 600 : 400, children: [
697
+ "$",
698
+ row.cost.toFixed(4)
699
+ ] }) }),
700
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Badge, { color: row.percentage > 30 ? "red" : row.percentage > 15 ? "yellow" : "gray", children: [
701
+ row.percentage.toFixed(1),
702
+ "%"
703
+ ] }) }),
704
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: row.calls.toLocaleString() }) }),
705
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
706
+ "$",
707
+ row.avgCost.toFixed(6)
708
+ ] }) })
709
+ ] }, row.model)),
710
+ tableData.length > 0 && /* @__PURE__ */ jsxs(Table.Tr, { children: [
711
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: "Total" }) }),
712
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", fw: 700, children: [
713
+ "$",
714
+ totalCost.toFixed(4)
715
+ ] }) }),
716
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { children: "100.0%" }) }),
717
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: (data?.totalCallCount ?? 0).toLocaleString() }) }),
718
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "-" }) })
719
+ ] })
720
+ ] })
721
+ ] }),
722
+ tableData.length === 0 && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", py: "xl", children: "No cost data available for this time period" })
723
+ ] });
724
+ }
725
+ function BusinessImpactCard({
726
+ impactData,
727
+ summaryData,
728
+ trendsData,
729
+ data,
730
+ isLoading,
731
+ error,
732
+ laborRate = 75
733
+ }) {
734
+ const businessData = impactData ?? data;
735
+ const laborCostSavings = businessData?.totalSavingsUsd ?? 0;
736
+ const platformCost = businessData?.totalCostUsd ?? 0;
737
+ const netSavings = businessData?.netSavingsUsd ?? 0;
738
+ const roi = businessData?.roi ?? 0;
739
+ const hoursSaved = Math.round(laborCostSavings / laborRate);
740
+ const previousCost = summaryData?.previous.totalCostUsd ?? platformCost;
741
+ const previousSavings = laborCostSavings * (previousCost > 0 ? (summaryData?.previous.totalCostUsd ?? platformCost) / platformCost : 0.8);
742
+ const previousHoursSaved = Math.round(previousSavings / laborRate);
743
+ const totalTrendCost = trendsData?.totalCostUsd ?? 0;
744
+ const trendData = (trendsData?.trendData ?? []).map((point) => {
745
+ const date = new Date(point.time);
746
+ const timeLabel = trendsData?.granularity === "hour" ? date.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" }) : date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
747
+ const proportion = totalTrendCost > 0 ? point.totalCostUsd / totalTrendCost : 1 / (trendsData?.trendData.length ?? 1);
748
+ return {
749
+ time: timeLabel,
750
+ savings: laborCostSavings * proportion
751
+ };
752
+ });
753
+ if (error) {
754
+ return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load business impact metrics" });
755
+ }
756
+ if (isLoading) {
757
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
758
+ }
759
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
760
+ /* @__PURE__ */ jsx(
761
+ CardHeader,
762
+ {
763
+ icon: /* @__PURE__ */ jsx(IconTrendingUp, { size: 18 }),
764
+ title: "Business Impact",
765
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
766
+ }
767
+ ),
768
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", mb: "md", children: [
769
+ /* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
770
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
771
+ /* @__PURE__ */ jsx(
772
+ Text,
773
+ {
774
+ size: "xl",
775
+ fw: 700,
776
+ c: "var(--color-primary)",
777
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
778
+ children: hoursSaved
779
+ }
780
+ ),
781
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "hrs saved" }),
782
+ /* @__PURE__ */ jsx(TrendIndicator, { current: hoursSaved, previous: previousHoursSaved })
783
+ ] }),
784
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
785
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: laborCostSavings, thousandSeparator: true }) }),
786
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "labor saved" })
787
+ ] })
788
+ ] }),
789
+ /* @__PURE__ */ jsx(
790
+ Badge,
791
+ {
792
+ size: "lg",
793
+ variant: roi > 0 ? "dot" : "light",
794
+ color: roi > 1e3 ? "green" : roi > 500 ? "yellow" : "gray",
795
+ children: roi > 0 ? `${roi.toFixed(0)}x ROI` : "N/A"
796
+ }
797
+ )
798
+ ] }),
799
+ /* @__PURE__ */ jsx(
800
+ CyberAreaChart,
801
+ {
802
+ data: trendData,
803
+ series: [{ dataKey: "savings", color: "blue", name: "Savings" }],
804
+ xDataKey: "time",
805
+ height: 200,
806
+ yTickFormatter: (v) => `$${v.toFixed(2)}`
807
+ }
808
+ ),
809
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "sm", children: [
810
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
811
+ "Platform cost: ",
812
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: platformCost, decimalScale: 2 })
813
+ ] }),
814
+ /* @__PURE__ */ jsxs(Text, { size: "xs", fw: 500, c: netSavings < 0 ? "var(--color-error)" : "var(--color-primary)", children: [
815
+ "Net savings: ",
816
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: netSavings, thousandSeparator: true, decimalScale: 2 })
817
+ ] })
818
+ ] })
819
+ ] });
820
+ }
821
+ function CostBreakdownCard({
822
+ breakdownData,
823
+ summaryData,
824
+ data,
825
+ isLoading,
826
+ error,
827
+ budget = 1500
828
+ }) {
829
+ const resourceData = breakdownData ?? data;
830
+ const legacyTotalCost = resourceData?.resources.reduce((sum, r) => sum + r.totalCostUsd, 0) ?? 0;
831
+ const mtdCost = summaryData?.mtd.totalCostUsd ?? legacyTotalCost * 2;
832
+ const projectedMonthlyCost = summaryData?.projection.monthlyCostUsd ?? mtdCost * 1.05;
833
+ const workflowCosts = resourceData?.resources.slice(0, 4).map((r) => ({
834
+ name: r.resourceId,
835
+ cost: r.totalCostUsd,
836
+ executions: r.executionCount,
837
+ avgCost: r.avgCostUsd
838
+ })) ?? [];
839
+ if (error) {
840
+ return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load cost breakdown" });
841
+ }
842
+ if (isLoading) {
843
+ return /* @__PURE__ */ jsx(DetailCardSkeleton, { rows: 3 });
844
+ }
845
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
846
+ /* @__PURE__ */ jsx(
847
+ CardHeader,
848
+ {
849
+ icon: /* @__PURE__ */ jsx(IconChartBar, { size: 18 }),
850
+ title: "AI Costs Breakdown",
851
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
852
+ }
853
+ ),
854
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", mb: "md", children: [
855
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Top Spenders" }),
856
+ workflowCosts.length > 0 ? workflowCosts.map((workflow) => /* @__PURE__ */ jsx(
857
+ Box,
858
+ {
859
+ p: "sm",
860
+ style: {
861
+ borderLeft: "3px solid var(--color-primary)",
862
+ backgroundColor: "var(--color-surface)",
863
+ borderRadius: 4
864
+ },
865
+ children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
866
+ /* @__PURE__ */ jsxs(Stack, { gap: 0, style: { flex: 1 }, children: [
867
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: workflow.name }),
868
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
869
+ workflow.executions,
870
+ " executions - $",
871
+ workflow.avgCost.toFixed(4),
872
+ "/exec"
873
+ ] })
874
+ ] }),
875
+ /* @__PURE__ */ jsx(
876
+ Text,
877
+ {
878
+ size: "sm",
879
+ fw: 600,
880
+ c: "var(--color-primary)",
881
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
882
+ children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: workflow.cost, decimalScale: 4 })
883
+ }
884
+ )
885
+ ] })
886
+ },
887
+ workflow.name
888
+ )) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", py: "md", children: "No resource data available" })
889
+ ] }),
890
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "sm", children: [
891
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
892
+ "Projected: ",
893
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: projectedMonthlyCost, thousandSeparator: true, decimalScale: 2 })
894
+ ] }),
895
+ /* @__PURE__ */ jsxs(
896
+ Text,
897
+ {
898
+ size: "xs",
899
+ fw: 600,
900
+ c: projectedMonthlyCost > budget ? "red" : "dimmed",
901
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
902
+ children: [
903
+ "Budget: ",
904
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: budget, thousandSeparator: true, decimalScale: 2 })
905
+ ]
906
+ }
907
+ )
908
+ ] })
909
+ ] });
910
+ }
911
+ function CostMetricsCard({
912
+ summaryData,
913
+ trendsData,
914
+ data,
915
+ isLoading,
916
+ error,
917
+ budget = 1500
918
+ }) {
919
+ const legacyTotalCost = data?.resources.reduce((sum, r) => sum + r.totalCostUsd, 0) ?? 0;
920
+ const todayCost = summaryData?.current.totalCostUsd ?? legacyTotalCost;
921
+ const previousCost = summaryData?.previous.totalCostUsd ?? legacyTotalCost * 0.9;
922
+ const mtdCost = summaryData?.mtd.totalCostUsd ?? legacyTotalCost * 2;
923
+ const projectedMonthlyCost = summaryData?.projection.monthlyCostUsd ?? mtdCost * 1.05;
924
+ const confidence = summaryData?.projection.confidence ?? "low";
925
+ const budgetStatus = projectedMonthlyCost <= budget ? "green" : projectedMonthlyCost <= budget * 1.1 ? "yellow" : "red";
926
+ const budgetLabel = projectedMonthlyCost <= budget ? "On Budget" : projectedMonthlyCost <= budget * 1.1 ? "Warning" : "Over Budget";
927
+ const chartData = trendsData?.trendData.slice(-7).map((point, idx) => {
928
+ const days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
929
+ return {
930
+ day: trendsData.granularity === "day" ? new Date(point.time).toLocaleDateString("en-US", { weekday: "short" }) : days[idx % 7],
931
+ cost: point.totalCostUsd
932
+ };
933
+ }) ?? data?.resources.slice(0, 7).map((r, idx) => ({
934
+ day: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][idx] || `Day ${idx + 1}`,
935
+ cost: r.totalCostUsd
936
+ })) ?? [];
937
+ if (error) {
938
+ return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load cost metrics" });
939
+ }
940
+ if (isLoading) {
941
+ return /* @__PURE__ */ jsx(StatsCardSkeleton, {});
942
+ }
943
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
944
+ /* @__PURE__ */ jsx(
945
+ CardHeader,
946
+ {
947
+ icon: /* @__PURE__ */ jsx(IconCash, { size: 18 }),
948
+ title: "AI Costs",
949
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
950
+ }
951
+ ),
952
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", mb: "md", children: [
953
+ /* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
954
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
955
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: todayCost, decimalScale: 2 }) }),
956
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "period" }),
957
+ /* @__PURE__ */ jsx(TrendIndicator, { current: todayCost, previous: previousCost, inverse: true })
958
+ ] }),
959
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
960
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: mtdCost, thousandSeparator: true, decimalScale: 2 }) }),
961
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "MTD" })
962
+ ] })
963
+ ] }),
964
+ /* @__PURE__ */ jsx(Badge, { size: "md", variant: "dot", color: budgetStatus, children: budgetLabel })
965
+ ] }),
966
+ chartData.length > 0 ? /* @__PURE__ */ jsx(
967
+ CyberAreaChart,
968
+ {
969
+ data: chartData,
970
+ series: [{ dataKey: "cost", color: "blue", name: "Cost" }],
971
+ xDataKey: "day",
972
+ height: 120,
973
+ yTickFormatter: (v) => `$${v.toFixed(2)}`
974
+ }
975
+ ) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", py: "lg", children: "No trend data available" }),
976
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "sm", children: [
977
+ /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
978
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
979
+ "Projected monthly:",
980
+ " ",
981
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: projectedMonthlyCost, thousandSeparator: true, decimalScale: 2 })
982
+ ] }),
983
+ /* @__PURE__ */ jsx(Tooltip, { label: `Projection confidence: ${confidence}`, children: /* @__PURE__ */ jsx(IconInfoCircle, { size: 12, color: "var(--color-text-subtle)" }) })
984
+ ] }),
985
+ /* @__PURE__ */ jsxs(
986
+ Text,
987
+ {
988
+ size: "xs",
989
+ fw: 600,
990
+ c: projectedMonthlyCost > budget ? "red" : "dimmed",
991
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
992
+ children: [
993
+ "Budget: ",
994
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: budget, thousandSeparator: true, decimalScale: 2 })
995
+ ]
996
+ }
997
+ )
998
+ ] })
999
+ ] });
1000
+ }
1001
+ function ErrorBreakdownTable({ startDate, endDate, onErrorClick }) {
1002
+ const [searchQuery, setSearchQuery] = useState("");
1003
+ const [filterType, setFilterType] = useState("all");
1004
+ const [filterSeverity, setFilterSeverity] = useState();
1005
+ const [showResolved, setShowResolved] = useState(false);
1006
+ const resolveError = useResolveError();
1007
+ const resolveAll = useResolveAllErrors();
1008
+ const { page, setPage, totalPages } = usePaginationState(PAGE_SIZE_DEFAULT, [
1009
+ filterType,
1010
+ filterSeverity,
1011
+ searchQuery,
1012
+ showResolved,
1013
+ startDate,
1014
+ endDate
1015
+ ]);
1016
+ const { data, isLoading, isError, error } = useErrorDetails({
1017
+ errorType: filterType === "all" ? void 0 : filterType,
1018
+ severity: filterSeverity,
1019
+ search: searchQuery || void 0,
1020
+ startDate,
1021
+ endDate,
1022
+ page,
1023
+ limit: PAGE_SIZE_DEFAULT,
1024
+ resolved: showResolved ? void 0 : false
1025
+ });
1026
+ if (isLoading) {
1027
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(Stack, { align: "center", justify: "center", mih: 200, children: /* @__PURE__ */ jsx(Loader, { size: "md" }) }) });
1028
+ }
1029
+ if (isError) {
1030
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, {}), title: "Error Loading Data", children: error?.message || "Failed to load error details. Please try again." }) });
1031
+ }
1032
+ if (!data || data.errors.length === 0) {
1033
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1034
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1035
+ /* @__PURE__ */ jsxs("div", { children: [
1036
+ /* @__PURE__ */ jsx(Title, { order: 3, children: "Recent Errors" }),
1037
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "0 errors found" })
1038
+ ] }),
1039
+ /* @__PURE__ */ jsx(
1040
+ Switch,
1041
+ {
1042
+ label: "Show resolved",
1043
+ checked: showResolved,
1044
+ onChange: (e) => setShowResolved(e.currentTarget.checked),
1045
+ size: "sm"
1046
+ }
1047
+ )
1048
+ ] }),
1049
+ /* @__PURE__ */ jsx(
1050
+ EmptyState,
1051
+ {
1052
+ icon: IconBug,
1053
+ title: "No errors found",
1054
+ description: showResolved ? "No errors found for the selected time range" : "All errors have been resolved"
1055
+ }
1056
+ )
1057
+ ] }) });
1058
+ }
1059
+ const filteredErrors = data.errors;
1060
+ const errorTypes = Array.from(new Set(data.errors.map((e) => e.errorType)));
1061
+ const total = data.total;
1062
+ const getSeverityIcon = (severity) => {
1063
+ switch (severity) {
1064
+ case "critical":
1065
+ return /* @__PURE__ */ jsx(IconAlertCircle, { size: 16, color: "var(--color-error)" });
1066
+ case "warning":
1067
+ return /* @__PURE__ */ jsx(IconAlertTriangle, { size: 16, color: "var(--mantine-color-orange-6)" });
1068
+ default:
1069
+ return /* @__PURE__ */ jsx(IconBug, { size: 16, color: "var(--color-primary)" });
1070
+ }
1071
+ };
1072
+ const getSeverityColor = (severity) => {
1073
+ switch (severity) {
1074
+ case "critical":
1075
+ return "red";
1076
+ case "warning":
1077
+ return "orange";
1078
+ default:
1079
+ return "blue";
1080
+ }
1081
+ };
1082
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1083
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1084
+ /* @__PURE__ */ jsxs("div", { children: [
1085
+ /* @__PURE__ */ jsx(Title, { order: 3, children: "Recent Errors" }),
1086
+ /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
1087
+ filteredErrors.length,
1088
+ " error",
1089
+ filteredErrors.length !== 1 ? "s" : "",
1090
+ " found"
1091
+ ] })
1092
+ ] }),
1093
+ /* @__PURE__ */ jsxs(Group, { children: [
1094
+ /* @__PURE__ */ jsx(
1095
+ Switch,
1096
+ {
1097
+ label: "Show resolved",
1098
+ checked: showResolved,
1099
+ onChange: (e) => setShowResolved(e.currentTarget.checked),
1100
+ size: "sm"
1101
+ }
1102
+ ),
1103
+ !showResolved && filteredErrors.some((e) => !e.resolved) && /* @__PURE__ */ jsx(
1104
+ Button,
1105
+ {
1106
+ leftSection: /* @__PURE__ */ jsx(IconChecks, { size: 16 }),
1107
+ variant: "light",
1108
+ loading: resolveAll.isPending,
1109
+ onClick: () => resolveAll.mutate(),
1110
+ children: "Resolve All"
1111
+ }
1112
+ )
1113
+ ] })
1114
+ ] }),
1115
+ /* @__PURE__ */ jsxs(FilterBar, { children: [
1116
+ /* @__PURE__ */ jsx(
1117
+ TextInput,
1118
+ {
1119
+ placeholder: "Search errors...",
1120
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
1121
+ value: searchQuery,
1122
+ onChange: (e) => {
1123
+ setSearchQuery(e.currentTarget.value);
1124
+ },
1125
+ style: { flex: 1 }
1126
+ }
1127
+ ),
1128
+ /* @__PURE__ */ jsx(
1129
+ Select,
1130
+ {
1131
+ placeholder: "Filter by type",
1132
+ value: filterType,
1133
+ onChange: (value) => {
1134
+ setFilterType(value || "all");
1135
+ },
1136
+ data: [{ value: "all", label: "All Types" }, ...errorTypes.map((type) => ({ value: type, label: type }))],
1137
+ style: { width: 200 },
1138
+ clearable: true
1139
+ }
1140
+ ),
1141
+ /* @__PURE__ */ jsx(
1142
+ Select,
1143
+ {
1144
+ placeholder: "Filter by severity",
1145
+ value: filterSeverity,
1146
+ onChange: (value) => {
1147
+ setFilterSeverity(value);
1148
+ },
1149
+ data: [
1150
+ { value: "critical", label: "Critical" },
1151
+ { value: "warning", label: "Warning" },
1152
+ { value: "info", label: "Info" }
1153
+ ],
1154
+ style: { width: 200 },
1155
+ clearable: true
1156
+ }
1157
+ )
1158
+ ] }),
1159
+ /* @__PURE__ */ jsxs(Table, { children: [
1160
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1161
+ /* @__PURE__ */ jsx(Table.Th, { children: "Timestamp" }),
1162
+ /* @__PURE__ */ jsx(Table.Th, { children: "Type" }),
1163
+ /* @__PURE__ */ jsx(Table.Th, { children: "Message" }),
1164
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1165
+ /* @__PURE__ */ jsx(Table.Th, { ta: "center", children: "Severity" }),
1166
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Actions" })
1167
+ ] }) }),
1168
+ /* @__PURE__ */ jsx(Table.Tbody, { children: filteredErrors.map((error2) => /* @__PURE__ */ jsxs(Table.Tr, { style: { cursor: "pointer" }, onClick: () => onErrorClick?.(error2.executionId), children: [
1169
+ /* @__PURE__ */ jsx(Table.Td, { style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Text, { size: "sm", children: new Date(error2.timestamp).toLocaleString("en-US", {
1170
+ month: "short",
1171
+ day: "numeric",
1172
+ hour: "2-digit",
1173
+ minute: "2-digit"
1174
+ }) }) }),
1175
+ /* @__PURE__ */ jsx(Table.Td, { style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Badge, { variant: "light", size: "sm", children: error2.errorType }) }),
1176
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 300 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", lineClamp: 1, children: error2.message }) }),
1177
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: error2.resourceName }) }),
1178
+ /* @__PURE__ */ jsx(Table.Td, { ta: "center", style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(
1179
+ Badge,
1180
+ {
1181
+ color: getSeverityColor(error2.severity),
1182
+ variant: "light",
1183
+ size: "sm",
1184
+ leftSection: getSeverityIcon(error2.severity),
1185
+ children: error2.severity.toUpperCase()
1186
+ }
1187
+ ) }),
1188
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsxs(Group, { gap: 4, justify: "flex-end", wrap: "nowrap", children: [
1189
+ error2.resolved ? /* @__PURE__ */ jsx(Badge, { color: "green", variant: "light", size: "sm", style: { cursor: "default" }, children: "Resolved" }) : /* @__PURE__ */ jsx(
1190
+ Badge,
1191
+ {
1192
+ color: "gray",
1193
+ variant: "light",
1194
+ size: "sm",
1195
+ style: {
1196
+ cursor: resolveError.isPending && resolveError.variables === error2.id ? "wait" : "pointer",
1197
+ opacity: resolveError.isPending && resolveError.variables === error2.id ? 0.5 : 1
1198
+ },
1199
+ onClick: (e) => {
1200
+ e.stopPropagation();
1201
+ resolveError.mutate(error2.id);
1202
+ },
1203
+ children: "Resolve"
1204
+ }
1205
+ ),
1206
+ /* @__PURE__ */ jsx(
1207
+ ActionIcon,
1208
+ {
1209
+ variant: "subtle",
1210
+ size: "sm",
1211
+ onClick: (e) => {
1212
+ e.stopPropagation();
1213
+ onErrorClick?.(error2.executionId);
1214
+ },
1215
+ children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 })
1216
+ }
1217
+ )
1218
+ ] }) })
1219
+ ] }, error2.id)) })
1220
+ ] }),
1221
+ totalPages(total) > 1 && /* @__PURE__ */ jsx(Group, { justify: "flex-start", children: /* @__PURE__ */ jsx(Pagination, { total: totalPages(total), value: page, onChange: setPage, size: "sm", boundaries: 1 }) })
1222
+ ] }) });
1223
+ }
1224
+ var categoryColors = {
1225
+ info: "blue",
1226
+ queue: "cyan",
1227
+ alert: "yellow",
1228
+ error: "red",
1229
+ system: "gray"
1230
+ };
1231
+ function NotificationItem({ notification, onClose, onNavigate }) {
1232
+ const markAsRead = useMarkAsRead();
1233
+ const handleClick = async () => {
1234
+ if (!notification.read) {
1235
+ await markAsRead.mutateAsync(notification.id);
1236
+ }
1237
+ if (notification.actionUrl) {
1238
+ onNavigate?.(notification.actionUrl);
1239
+ }
1240
+ onClose?.();
1241
+ };
1242
+ const categoryColor = categoryColors[notification.category] || "gray";
1243
+ return /* @__PURE__ */ jsx(
1244
+ UnstyledButton,
1245
+ {
1246
+ onClick: handleClick,
1247
+ style: {
1248
+ width: "100%",
1249
+ padding: "12px",
1250
+ backgroundColor: "transparent",
1251
+ transition: "background-color var(--duration-fast) var(--easing)"
1252
+ },
1253
+ styles: {
1254
+ root: {
1255
+ "&:hover": {
1256
+ backgroundColor: "var(--color-surface-hover)"
1257
+ }
1258
+ }
1259
+ },
1260
+ children: /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "flex-start", wrap: "nowrap", children: [
1261
+ /* @__PURE__ */ jsx(Box, { mt: 4, children: notification.read ? /* @__PURE__ */ jsx(IconCircle, { size: 12, color: "var(--mantine-color-gray-5)" }) : /* @__PURE__ */ jsx(IconCircleFilled, { size: 12, color: `var(--mantine-color-${categoryColor}-6)` }) }),
1262
+ /* @__PURE__ */ jsxs(Stack, { gap: 4, style: { flex: 1 }, children: [
1263
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: notification.read ? 400 : 600, children: notification.title }),
1264
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: notification.message }),
1265
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatDistanceToNow(new Date(notification.createdAt), { addSuffix: true }) })
1266
+ ] })
1267
+ ] })
1268
+ }
1269
+ );
1270
+ }
1271
+ function NotificationList({ notifications, isLoading, onClose, onNavigate }) {
1272
+ if (isLoading) {
1273
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) });
1274
+ }
1275
+ if (notifications.length === 0) {
1276
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No notifications" }) });
1277
+ }
1278
+ return /* @__PURE__ */ jsx(Stack, { gap: 0, children: notifications.map((notification) => /* @__PURE__ */ jsx(NotificationItem, { notification, onClose, onNavigate }, notification.id)) });
1279
+ }
1280
+
1281
+ export { ActivityCard, ActivityFilters, ActivityTable, BusinessImpactCard, CostBreakdownCard, CostByModelTable, CostMetricsCard, ErrorAnalysisCard, ErrorBreakdownTable, ExecutionBreakdownTable, ExecutionHealthCard, ExecutionLogsFilters, ExecutionLogsTable, NotificationItem, NotificationList };