@burdenoff/microfe-bigconsole 2026.610.1 → 2026.612.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 (23) hide show
  1. package/dist/bigconsole/components/widgets/WidgetRegistry.js +2 -1
  2. package/dist/bigconsole/components/widgets/WidgetRegistry.js.map +1 -1
  3. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +4 -4
  4. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  5. package/dist/bigconsole/components/widgets/form/FormWidget.js +20 -20
  6. package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
  7. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +1 -1
  8. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  9. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +2 -2
  10. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
  11. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +2 -2
  12. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
  13. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +37 -37
  14. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  15. package/dist/bigconsole/hooks/useDashboardOperations.js +92 -70
  16. package/dist/bigconsole/hooks/useDashboardOperations.js.map +1 -1
  17. package/dist/bigconsole/pages/DashboardsPage.js +109 -72
  18. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  19. package/dist/bigconsole/pages/InsightsPage.js +783 -395
  20. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  21. package/dist/generated/wspace-operations.js +105 -107
  22. package/dist/generated/wspace-operations.js.map +1 -1
  23. package/package.json +1 -1
@@ -6,20 +6,20 @@ import n from "../components/dashboard/CreateDashboardDialog.js";
6
6
  import r from "../components/dashboard/ImportDashboardDialog.js";
7
7
  import { isNative as i, nativeConfirm as a, nativeImpact as o, nativeNotify as s } from "../../utils/nativeBridge.js";
8
8
  import { memo as c, useCallback as l, useState as u } from "react";
9
- import { Calendar as d, FileText as f, FolderOpen as p, Layers as m, LayoutDashboard as h, Pencil as g, Plus as _, Search as v, Trash2 as y, Upload as b } from "lucide-react";
10
- import { useI18n as x } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
+ import { Calendar as d, Copy as f, FileText as p, FolderOpen as m, Layers as h, LayoutDashboard as g, Pencil as _, Plus as v, Search as y, Trash2 as b, Upload as x } from "lucide-react";
10
+ import { useI18n as ee } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
11
  import { jsx as S, jsxs as C } from "react/jsx-runtime";
12
12
  import { Badge as w, Button as T, Card as E, CardContent as D, Input as O, Spinner as k } from "@burdenoff/fe-libs/ui";
13
13
  //#region src/bigconsole/pages/DashboardsPage.tsx
14
14
  var A = c(function() {
15
- let c = e(), { t: A } = x(), j = l((e, t) => {
15
+ let c = e(), { t: A } = ee(), j = l((e, t) => {
16
16
  let n = A(e);
17
17
  return n === e ? t : n;
18
- }, [A]), [M, N] = u(""), [P, F] = u(!1), [I, L] = u(!1), [R, z] = u(!1), { loading: B, error: V, dashboards: H, createDashboard: U, deleteDashboard: W, refetch: G } = t(), K = H.filter((e) => e.name.toLowerCase().includes(M.toLowerCase()) || e.description?.toLowerCase().includes(M.toLowerCase())), q = l(() => {
18
+ }, [A]), [M, N] = u(""), [P, F] = u(!1), [I, L] = u(!1), [R, z] = u(!1), { loading: B, error: V, dashboards: H, createDashboard: U, deleteDashboard: W, cloneDashboard: G, refetch: K } = t(), q = H.filter((e) => e.name.toLowerCase().includes(M.toLowerCase()) || e.description?.toLowerCase().includes(M.toLowerCase())), J = l(() => {
19
19
  F(!0);
20
- }, []), J = l(() => {
20
+ }, []), Y = l(() => {
21
21
  I || F(!1);
22
- }, [I]), Y = l(async (e) => {
22
+ }, [I]), X = l(async (e) => {
23
23
  L(!0);
24
24
  try {
25
25
  let t = await U({
@@ -34,11 +34,11 @@ var A = c(function() {
34
34
  } finally {
35
35
  L(!1);
36
36
  }
37
- }, [U, c]), X = l((e) => {
37
+ }, [U, c]), Z = l((e) => {
38
38
  c(`/dashboards/${e}`);
39
- }, [c]), Z = l((e, t) => {
39
+ }, [c]), Q = l((e, t) => {
40
40
  t.stopPropagation(), c(`/dashboards/${e}/builder`);
41
- }, [c]), Q = l(async (e, t) => {
41
+ }, [c]), te = l(async (e, t) => {
42
42
  t.stopPropagation();
43
43
  let n = j("bigconsole.dashboards.confirmDelete", "Are you sure you want to delete this dashboard?"), r = await a({
44
44
  title: "Delete dashboard?",
@@ -54,20 +54,36 @@ var A = c(function() {
54
54
  throw i() && s("error"), e;
55
55
  }
56
56
  }
57
- }, [W, j]), $ = l(() => {
57
+ }, [W, j]), ne = l(async (e, t, n) => {
58
+ n.stopPropagation();
59
+ let r = j("bigconsole.dashboards.clone.defaultSuffix", `${t} (Copy)`), a = window.prompt(j("bigconsole.dashboards.clone.namePrompt", "Name for the cloned dashboard:"), r);
60
+ if (!(!a || !a.trim())) {
61
+ o("medium");
62
+ try {
63
+ let t = await G(e, a.trim());
64
+ t && (i() && s("success"), c(`/dashboards/${t.id}`));
65
+ } catch (e) {
66
+ throw i() && s("error"), e;
67
+ }
68
+ }
69
+ }, [
70
+ G,
71
+ c,
72
+ j
73
+ ]), $ = l(() => {
58
74
  z(!0);
59
- }, []), ee = l(() => {
75
+ }, []), re = l(() => {
60
76
  z(!1);
61
- }, []), te = l((e, t) => {
62
- G();
63
- }, [G]), ne = (e) => {
77
+ }, []), ie = l((e, t) => {
78
+ K();
79
+ }, [K]), ae = (e) => {
64
80
  let t = new Date(e), n = /* @__PURE__ */ new Date(), r = n.getTime() - t.getTime(), i = Math.floor(r / 6e4), a = Math.floor(r / 36e5), o = Math.floor(r / 864e5);
65
81
  return i < 1 ? j("bigconsole.dashboards.time.justNow", "Just now") : i < 60 ? `${i}${j("bigconsole.dashboards.time.minutesAgoSuffix", "m ago")}` : a < 24 ? `${a}${j("bigconsole.dashboards.time.hoursAgoSuffix", "h ago")}` : o < 7 ? `${o}${j("bigconsole.dashboards.time.daysAgoSuffix", "d ago")}` : new Intl.DateTimeFormat("en-US", {
66
82
  month: "short",
67
83
  day: "numeric",
68
84
  year: t.getFullYear() === n.getFullYear() ? void 0 : "numeric"
69
85
  }).format(t);
70
- }, re = (e) => e.widgetCount ?? 0, ie = (e) => e.pages?.length || 0;
86
+ }, oe = (e) => e.widgetCount ?? 0, se = (e) => e.pages?.length || 0;
71
87
  return V ? /* @__PURE__ */ S("div", {
72
88
  style: { padding: "var(--space-pagePadding)" },
73
89
  children: /* @__PURE__ */ S(E, {
@@ -96,7 +112,7 @@ var A = c(function() {
96
112
  }),
97
113
  /* @__PURE__ */ S(T, {
98
114
  size: "sm",
99
- onClick: () => G(),
115
+ onClick: () => K(),
100
116
  style: { marginTop: "var(--space-formGap)" },
101
117
  children: j("bigconsole.dashboards.error.retry", "Retry")
102
118
  })
@@ -141,7 +157,7 @@ var A = c(function() {
141
157
  borderRadius: "var(--radius-card)",
142
158
  backgroundColor: "var(--color-action-primary-bg)"
143
159
  },
144
- children: /* @__PURE__ */ S(h, { style: {
160
+ children: /* @__PURE__ */ S(g, { style: {
145
161
  height: "var(--size-icon-lg)",
146
162
  width: "var(--size-icon-lg)",
147
163
  color: "var(--color-action-primary-text)"
@@ -172,14 +188,14 @@ var A = c(function() {
172
188
  children: [/* @__PURE__ */ C(T, {
173
189
  variant: "outline",
174
190
  onClick: $,
175
- children: [/* @__PURE__ */ S(b, { style: {
191
+ children: [/* @__PURE__ */ S(x, { style: {
176
192
  marginRight: "var(--space-iconGap)",
177
193
  height: "var(--size-icon-sm)",
178
194
  width: "var(--size-icon-sm)"
179
195
  } }), j("bigconsole.dashboards.actions.import", "Import")]
180
196
  }), /* @__PURE__ */ C(T, {
181
- onClick: q,
182
- children: [/* @__PURE__ */ S(_, { style: {
197
+ onClick: J,
198
+ children: [/* @__PURE__ */ S(v, { style: {
183
199
  marginRight: "var(--space-iconGap)",
184
200
  height: "var(--size-icon-sm)",
185
201
  width: "var(--size-icon-sm)"
@@ -199,7 +215,7 @@ var A = c(function() {
199
215
  position: "relative",
200
216
  maxWidth: "400px"
201
217
  },
202
- children: [/* @__PURE__ */ S(v, { style: {
218
+ children: [/* @__PURE__ */ S(y, { style: {
203
219
  position: "absolute",
204
220
  left: "var(--space-controlGap)",
205
221
  top: "50%",
@@ -241,14 +257,14 @@ var A = c(function() {
241
257
  })]
242
258
  })
243
259
  }),
244
- !B && K.length > 0 && /* @__PURE__ */ S("div", {
260
+ !B && q.length > 0 && /* @__PURE__ */ S("div", {
245
261
  style: {
246
262
  display: "grid",
247
263
  gridTemplateColumns: "repeat(auto-fill, minmax(min(320px, 100%), 1fr))",
248
264
  gap: "var(--space-formGap)"
249
265
  },
250
- children: K.map((e) => /* @__PURE__ */ S(E, {
251
- onClick: () => X(e.id),
266
+ children: q.map((e) => /* @__PURE__ */ S(E, {
267
+ onClick: () => Z(e.id),
252
268
  style: {
253
269
  cursor: "pointer",
254
270
  transition: "all 0.2s ease"
@@ -275,7 +291,7 @@ var A = c(function() {
275
291
  borderRadius: "var(--radius-button)",
276
292
  backgroundColor: "var(--color-action-primary-bg)"
277
293
  },
278
- children: /* @__PURE__ */ S(h, { style: {
294
+ children: /* @__PURE__ */ S(g, { style: {
279
295
  height: "var(--size-icon-md)",
280
296
  width: "var(--size-icon-md)",
281
297
  color: "var(--color-action-primary-text)"
@@ -340,7 +356,7 @@ var A = c(function() {
340
356
  gap: "var(--space-iconGap)"
341
357
  },
342
358
  children: [
343
- /* @__PURE__ */ S(m, { style: {
359
+ /* @__PURE__ */ S(h, { style: {
344
360
  height: "var(--size-icon-sm)",
345
361
  width: "var(--size-icon-sm)",
346
362
  color: "var(--color-action-primary-bg)"
@@ -351,7 +367,7 @@ var A = c(function() {
351
367
  fontWeight: "var(--font-weight-semibold)",
352
368
  color: "var(--color-text-primary)"
353
369
  },
354
- children: ie(e)
370
+ children: se(e)
355
371
  }),
356
372
  /* @__PURE__ */ S("span", {
357
373
  style: {
@@ -374,7 +390,7 @@ var A = c(function() {
374
390
  gap: "var(--space-iconGap)"
375
391
  },
376
392
  children: [
377
- /* @__PURE__ */ S(f, { style: {
393
+ /* @__PURE__ */ S(p, { style: {
378
394
  height: "var(--size-icon-sm)",
379
395
  width: "var(--size-icon-sm)",
380
396
  color: "var(--color-action-primary-bg)"
@@ -385,7 +401,7 @@ var A = c(function() {
385
401
  fontWeight: "var(--font-weight-semibold)",
386
402
  color: "var(--color-text-primary)"
387
403
  },
388
- children: re(e)
404
+ children: oe(e)
389
405
  }),
390
406
  /* @__PURE__ */ S("span", {
391
407
  style: {
@@ -422,7 +438,7 @@ var A = c(function() {
422
438
  fontWeight: "var(--font-weight-medium)",
423
439
  color: "var(--color-text-muted)"
424
440
  },
425
- children: ne(e.updatedAt)
441
+ children: ae(e.updatedAt)
426
442
  })]
427
443
  }), /* @__PURE__ */ C("div", {
428
444
  style: {
@@ -430,45 +446,64 @@ var A = c(function() {
430
446
  alignItems: "center",
431
447
  gap: "var(--space-controlGap)"
432
448
  },
433
- children: [/* @__PURE__ */ S(T, {
434
- variant: "ghost",
435
- size: "sm",
436
- onClick: (t) => Z(e.id, t),
437
- style: {
438
- height: "var(--size-controlHeight-sm)",
439
- width: "var(--size-controlHeight-sm)",
440
- padding: 0,
441
- borderRadius: "var(--radius-button)"
442
- },
443
- title: j("bigconsole.dashboards.actions.editTitle", "Edit Dashboard"),
444
- children: /* @__PURE__ */ S(g, { style: {
445
- height: "var(--size-icon-sm)",
446
- width: "var(--size-icon-sm)"
447
- } })
448
- }), /* @__PURE__ */ S(T, {
449
- variant: "ghost",
450
- size: "sm",
451
- onClick: (t) => Q(e.id, t),
452
- style: {
453
- height: "var(--size-controlHeight-sm)",
454
- width: "var(--size-controlHeight-sm)",
455
- padding: 0,
456
- borderRadius: "var(--radius-button)"
457
- },
458
- className: "hover:text-destructive hover:bg-destructive/10",
459
- title: j("bigconsole.dashboards.actions.deleteTitle", "Delete Dashboard"),
460
- children: /* @__PURE__ */ S(y, { style: {
461
- height: "var(--size-icon-sm)",
462
- width: "var(--size-icon-sm)"
463
- } })
464
- })]
449
+ children: [
450
+ /* @__PURE__ */ S(T, {
451
+ variant: "ghost",
452
+ size: "sm",
453
+ onClick: (t) => Q(e.id, t),
454
+ style: {
455
+ height: "var(--size-controlHeight-sm)",
456
+ width: "var(--size-controlHeight-sm)",
457
+ padding: 0,
458
+ borderRadius: "var(--radius-button)"
459
+ },
460
+ title: j("bigconsole.dashboards.actions.editTitle", "Edit Dashboard"),
461
+ children: /* @__PURE__ */ S(_, { style: {
462
+ height: "var(--size-icon-sm)",
463
+ width: "var(--size-icon-sm)"
464
+ } })
465
+ }),
466
+ /* @__PURE__ */ S(T, {
467
+ variant: "ghost",
468
+ size: "sm",
469
+ onClick: (t) => ne(e.id, e.name, t),
470
+ style: {
471
+ height: "var(--size-controlHeight-sm)",
472
+ width: "var(--size-controlHeight-sm)",
473
+ padding: 0,
474
+ borderRadius: "var(--radius-button)"
475
+ },
476
+ title: j("bigconsole.dashboards.actions.cloneTitle", "Clone Dashboard"),
477
+ children: /* @__PURE__ */ S(f, { style: {
478
+ height: "var(--size-icon-sm)",
479
+ width: "var(--size-icon-sm)"
480
+ } })
481
+ }),
482
+ /* @__PURE__ */ S(T, {
483
+ variant: "ghost",
484
+ size: "sm",
485
+ onClick: (t) => te(e.id, t),
486
+ style: {
487
+ height: "var(--size-controlHeight-sm)",
488
+ width: "var(--size-controlHeight-sm)",
489
+ padding: 0,
490
+ borderRadius: "var(--radius-button)"
491
+ },
492
+ className: "hover:text-destructive hover:bg-destructive/10",
493
+ title: j("bigconsole.dashboards.actions.deleteTitle", "Delete Dashboard"),
494
+ children: /* @__PURE__ */ S(b, { style: {
495
+ height: "var(--size-icon-sm)",
496
+ width: "var(--size-icon-sm)"
497
+ } })
498
+ })
499
+ ]
465
500
  })]
466
501
  })
467
502
  ]
468
503
  })
469
504
  }, e.id))
470
505
  }),
471
- !B && K.length === 0 && /* @__PURE__ */ S(E, {
506
+ !B && q.length === 0 && /* @__PURE__ */ S(E, {
472
507
  className: "border-dashed",
473
508
  children: /* @__PURE__ */ C(D, {
474
509
  style: {
@@ -490,7 +525,7 @@ var A = c(function() {
490
525
  backgroundColor: "var(--color-bg-sunken)",
491
526
  marginBottom: "var(--space-sectionGap)"
492
527
  },
493
- children: /* @__PURE__ */ S(p, { style: {
528
+ children: /* @__PURE__ */ S(m, { style: {
494
529
  height: "var(--size-icon-xl)",
495
530
  width: "var(--size-icon-xl)",
496
531
  color: "var(--color-text-muted)"
@@ -517,19 +552,21 @@ var A = c(function() {
517
552
  !M && /* @__PURE__ */ C("div", {
518
553
  style: {
519
554
  display: "flex",
520
- gap: "var(--space-controlGap)"
555
+ gap: "var(--space-controlGap)",
556
+ flexWrap: "wrap",
557
+ justifyContent: "center"
521
558
  },
522
559
  children: [/* @__PURE__ */ C(T, {
523
560
  variant: "outline",
524
561
  onClick: $,
525
- children: [/* @__PURE__ */ S(b, { style: {
562
+ children: [/* @__PURE__ */ S(x, { style: {
526
563
  marginRight: "var(--space-iconGap)",
527
564
  height: "var(--size-icon-sm)",
528
565
  width: "var(--size-icon-sm)"
529
566
  } }), j("bigconsole.dashboards.actions.importDashboard", "Import Dashboard")]
530
567
  }), /* @__PURE__ */ C(T, {
531
- onClick: q,
532
- children: [/* @__PURE__ */ S(_, { style: {
568
+ onClick: J,
569
+ children: [/* @__PURE__ */ S(v, { style: {
533
570
  marginRight: "var(--space-iconGap)",
534
571
  height: "var(--size-icon-sm)",
535
572
  width: "var(--size-icon-sm)"
@@ -544,13 +581,13 @@ var A = c(function() {
544
581
  /* @__PURE__ */ S(n, {
545
582
  isOpen: P,
546
583
  isCreating: I,
547
- onClose: J,
548
- onCreate: Y
584
+ onClose: Y,
585
+ onCreate: X
549
586
  }),
550
587
  /* @__PURE__ */ S(r, {
551
588
  isOpen: R,
552
- onClose: ee,
553
- onSuccess: te
589
+ onClose: re,
590
+ onSuccess: ie
554
591
  })
555
592
  ]
556
593
  });
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardsPage.js","names":[],"sources":["../../../src/bigconsole/pages/DashboardsPage.tsx"],"sourcesContent":["/**\n * DashboardsPage\n *\n * List and manage dashboards - fetches data from real backend.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { type FC, memo, useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useBigConsoleNavigate } from '../context';\nimport { isNative, nativeConfirm, nativeImpact, nativeNotify } from '../../utils/nativeBridge';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport {\n Plus,\n Upload,\n Search,\n LayoutDashboard,\n Calendar,\n Layers,\n FileText,\n Pencil,\n Trash2,\n FolderOpen,\n} from 'lucide-react';\nimport { useDashboardOperations } from '../hooks';\nimport { CreateDashboardDialog } from '../components/dashboard/CreateDashboardDialog';\nimport { ImportDashboardDialog } from '../components/dashboard/ImportDashboardDialog';\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DashboardsPage: FC = memo(function DashboardsPage() {\n const navigate = useBigConsoleNavigate();\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string) => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n },\n [t]\n );\n const [searchQuery, setSearchQuery] = useState('');\n const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);\n const [isCreating, setIsCreating] = useState(false);\n const [isImportDialogOpen, setIsImportDialogOpen] = useState(false);\n\n const { loading, error, dashboards, createDashboard, deleteDashboard, refetch } = useDashboardOperations();\n\n // Filter dashboards by search query\n const filteredDashboards = dashboards.filter(\n (d) =>\n d.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n d.description?.toLowerCase().includes(searchQuery.toLowerCase())\n );\n\n const handleOpenCreateDialog = useCallback(() => {\n setIsCreateDialogOpen(true);\n }, []);\n\n const handleCloseCreateDialog = useCallback(() => {\n if (!isCreating) {\n setIsCreateDialogOpen(false);\n }\n }, [isCreating]);\n\n const handleCreateDashboard = useCallback(\n async (data: { name: string; description: string; category: string; tags?: string[] }) => {\n setIsCreating(true);\n try {\n const newDashboard = await createDashboard({\n name: data.name,\n description: data.description,\n category: data.category,\n tags: data.tags,\n });\n\n if (newDashboard) {\n setIsCreateDialogOpen(false);\n navigate(`/dashboards/${newDashboard.id}/builder`);\n }\n } catch (err) {\n // Surface the failure instead of swallowing it: log for debugging,\n // notify on native, and rethrow so CreateDashboardDialog displays the error.\n console.error('Failed to create dashboard:', err);\n if (isNative()) void nativeNotify('error');\n throw err;\n } finally {\n setIsCreating(false);\n }\n },\n [createDashboard, navigate]\n );\n\n const handleOpenDashboard = useCallback(\n (dashboardId: string) => {\n navigate(`/dashboards/${dashboardId}`);\n },\n [navigate]\n );\n\n const handleEditDashboard = useCallback(\n (dashboardId: string, e: React.MouseEvent) => {\n e.stopPropagation();\n navigate(`/dashboards/${dashboardId}/builder`);\n },\n [navigate]\n );\n\n const handleDeleteDashboard = useCallback(\n async (dashboardId: string, e: React.MouseEvent) => {\n e.stopPropagation();\n const msg = tr('bigconsole.dashboards.confirmDelete', 'Are you sure you want to delete this dashboard?');\n const native = await nativeConfirm({\n title: 'Delete dashboard?',\n message: msg,\n okButtonTitle: 'Delete',\n cancelButtonTitle: 'Cancel',\n });\n const ok = native === null ? window.confirm(msg) : native;\n if (ok) {\n nativeImpact('medium');\n try {\n await deleteDashboard(dashboardId);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n }\n },\n [deleteDashboard, tr]\n );\n\n const handleOpenImportDialog = useCallback(() => {\n setIsImportDialogOpen(true);\n }, []);\n\n const handleCloseImportDialog = useCallback(() => {\n setIsImportDialogOpen(false);\n }, []);\n\n const handleImportSuccess = useCallback(\n (dashboardId: string, dashboardName: string) => {\n refetch();\n },\n [refetch]\n );\n\n // Format relative date\n const formatRelativeDate = (dateStr: string) => {\n const date = new Date(dateStr);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return tr('bigconsole.dashboards.time.justNow', 'Just now');\n if (diffMins < 60) return `${diffMins}${tr('bigconsole.dashboards.time.minutesAgoSuffix', 'm ago')}`;\n if (diffHours < 24) return `${diffHours}${tr('bigconsole.dashboards.time.hoursAgoSuffix', 'h ago')}`;\n if (diffDays < 7) return `${diffDays}${tr('bigconsole.dashboards.time.daysAgoSuffix', 'd ago')}`;\n\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: date.getFullYear() !== now.getFullYear() ? 'numeric' : undefined,\n }).format(date);\n };\n\n // Get widget count - uses widgetCount field from backend\n const getWidgetCount = (dashboard: (typeof dashboards)[0]) => {\n return dashboard.widgetCount ?? 0;\n };\n\n // Get page count\n const getPageCount = (dashboard: (typeof dashboards)[0]) => {\n return dashboard.pages?.length || 0;\n };\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <h3\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n }}\n >\n {tr('bigconsole.dashboards.error.title', 'Error loading dashboards')}\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()} style={{ marginTop: 'var(--space-formGap)' }}>\n {tr('bigconsole.dashboards.error.retry', 'Retry')}\n </Button>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div style={{ borderBottom: '1px solid var(--color-border)', backgroundColor: 'var(--color-bg-surface)' }}>\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n flexWrap: 'wrap',\n gap: 'var(--space-formGap)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)', minWidth: 0 }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <LayoutDashboard\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n {tr('bigconsole.dashboards.title', 'Dashboards')}\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n {tr('bigconsole.dashboards.subtitle', 'Create and manage your analytics dashboards')}\n </p>\n </div>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)', flexWrap: 'wrap' }}>\n <Button variant=\"outline\" onClick={handleOpenImportDialog}>\n <Upload\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.import', 'Import')}\n </Button>\n <Button onClick={handleOpenCreateDialog}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.create', 'Create Dashboard')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n {/* Search Bar */}\n <div style={{ marginBottom: 'var(--space-sectionGap)' }}>\n <div style={{ position: 'relative', maxWidth: '400px' }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder={tr('bigconsole.dashboards.search.placeholder', 'Search dashboards...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n\n {/* Loading state */}\n {loading && dashboards.length === 0 && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n {tr('bigconsole.dashboards.loading', 'Loading dashboards...')}\n </p>\n </div>\n </div>\n )}\n\n {/* Dashboard Grid */}\n {!loading && filteredDashboards.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(min(320px, 100%), 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredDashboards.map((dashboard) => (\n <Card\n key={dashboard.id}\n onClick={() => handleOpenDashboard(dashboard.id)}\n style={{\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n }}\n className=\"hover:shadow-md hover:border-primary/50\"\n >\n <CardContent style={{ padding: 'var(--space-cardPadding)' }}>\n {/* Card Header with Icon and Name */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n flexShrink: 0,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <LayoutDashboard\n style={{\n height: 'var(--size-icon-md)',\n width: 'var(--size-icon-md)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <h3\n style={{\n fontWeight: 'var(--font-weight-bold)',\n fontSize: 'var(--font-size-body-md)',\n margin: 0,\n color: 'var(--color-text-primary)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {dashboard.name}\n </h3>\n {dashboard.category && (\n <Badge\n variant=\"secondary\"\n style={{\n marginTop: 'var(--space-controlGap)',\n fontSize: '10px',\n fontWeight: 'var(--font-weight-semibold)',\n textTransform: 'uppercase',\n }}\n >\n {dashboard.category}\n </Badge>\n )}\n </div>\n </div>\n\n {/* Description */}\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n lineHeight: 'var(--font-lineHeight-normal)',\n color: 'var(--color-text-secondary)',\n margin: '0 0 var(--space-formGap) 0',\n minHeight: '40px',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n }}\n >\n {dashboard.description || tr('bigconsole.dashboards.card.noDescription', 'No description provided')}\n </p>\n\n {/* Stats Row */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-formGap)',\n marginBottom: 'var(--space-formGap)',\n padding: 'var(--space-controlGap) var(--space-cardPadding)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Layers\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-action-primary-bg)',\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n {getPageCount(dashboard)}\n </span>\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n {tr('bigconsole.dashboards.card.pages', 'pages')}\n </span>\n </div>\n <div\n style={{ width: '1px', height: 'var(--size-icon-sm)', backgroundColor: 'var(--color-border)' }}\n />\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <FileText\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-action-primary-bg)',\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n {getWidgetCount(dashboard)}\n </span>\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n {tr('bigconsole.dashboards.card.widgets', 'widgets')}\n </span>\n </div>\n </div>\n\n {/* Footer with Date and Actions */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingTop: 'var(--space-controlGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n }}\n >\n <Calendar\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-muted)',\n }}\n >\n {formatRelativeDate(dashboard.updatedAt)}\n </span>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => handleEditDashboard(dashboard.id, e)}\n style={{\n height: 'var(--size-controlHeight-sm)',\n width: 'var(--size-controlHeight-sm)',\n padding: 0,\n borderRadius: 'var(--radius-button)',\n }}\n title={tr('bigconsole.dashboards.actions.editTitle', 'Edit Dashboard')}\n >\n <Pencil style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => handleDeleteDashboard(dashboard.id, e)}\n style={{\n height: 'var(--size-controlHeight-sm)',\n width: 'var(--size-controlHeight-sm)',\n padding: 0,\n borderRadius: 'var(--radius-button)',\n }}\n className=\"hover:text-destructive hover:bg-destructive/10\"\n title={tr('bigconsole.dashboards.actions.deleteTitle', 'Delete Dashboard')}\n >\n <Trash2 style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </Button>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n\n {/* Empty state */}\n {!loading && filteredDashboards.length === 0 && (\n <Card className=\"border-dashed\">\n <CardContent\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px var(--space-pagePadding)',\n }}\n >\n <div\n style={{\n display: 'flex',\n height: '80px',\n width: '80px',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '50%',\n backgroundColor: 'var(--color-bg-sunken)',\n marginBottom: 'var(--space-sectionGap)',\n }}\n >\n <FolderOpen\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-text-muted)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-semibold)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {searchQuery\n ? tr('bigconsole.dashboards.empty.filteredTitle', 'No dashboards found')\n : tr('bigconsole.dashboards.empty.title', 'No dashboards yet')}\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginBottom: 'var(--space-sectionGap)',\n textAlign: 'center',\n maxWidth: '360px',\n }}\n >\n {searchQuery\n ? tr('bigconsole.dashboards.empty.filteredDescription', 'Try adjusting your search terms')\n : tr(\n 'bigconsole.dashboards.empty.description',\n 'Get started by creating your first dashboard to visualize your data'\n )}\n </p>\n {!searchQuery && (\n <div style={{ display: 'flex', gap: 'var(--space-controlGap)' }}>\n <Button variant=\"outline\" onClick={handleOpenImportDialog}>\n <Upload\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.importDashboard', 'Import Dashboard')}\n </Button>\n <Button onClick={handleOpenCreateDialog}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.create', 'Create Dashboard')}\n </Button>\n </div>\n )}\n </CardContent>\n </Card>\n )}\n </div>\n\n {/* Create Dashboard Dialog */}\n <CreateDashboardDialog\n isOpen={isCreateDialogOpen}\n isCreating={isCreating}\n onClose={handleCloseCreateDialog}\n onCreate={handleCreateDashboard}\n />\n\n {/* Import Dashboard Dialog */}\n <ImportDashboardDialog\n isOpen={isImportDialogOpen}\n onClose={handleCloseImportDialog}\n onSuccess={handleImportSuccess}\n />\n </div>\n );\n});\n\nexport default DashboardsPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"DashboardsPage.js","names":[],"sources":["../../../src/bigconsole/pages/DashboardsPage.tsx"],"sourcesContent":["/**\n * DashboardsPage\n *\n * List and manage dashboards - fetches data from real backend.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { type FC, memo, useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useBigConsoleNavigate } from '../context';\nimport { isNative, nativeConfirm, nativeImpact, nativeNotify } from '../../utils/nativeBridge';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport {\n Plus,\n Upload,\n Search,\n LayoutDashboard,\n Calendar,\n Layers,\n FileText,\n Pencil,\n Trash2,\n Copy,\n FolderOpen,\n} from 'lucide-react';\nimport { useDashboardOperations } from '../hooks';\nimport { CreateDashboardDialog } from '../components/dashboard/CreateDashboardDialog';\nimport { ImportDashboardDialog } from '../components/dashboard/ImportDashboardDialog';\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DashboardsPage: FC = memo(function DashboardsPage() {\n const navigate = useBigConsoleNavigate();\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string) => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n },\n [t]\n );\n const [searchQuery, setSearchQuery] = useState('');\n const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);\n const [isCreating, setIsCreating] = useState(false);\n const [isImportDialogOpen, setIsImportDialogOpen] = useState(false);\n\n const { loading, error, dashboards, createDashboard, deleteDashboard, cloneDashboard, refetch } =\n useDashboardOperations();\n\n // Filter dashboards by search query\n const filteredDashboards = dashboards.filter(\n (d) =>\n d.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n d.description?.toLowerCase().includes(searchQuery.toLowerCase())\n );\n\n const handleOpenCreateDialog = useCallback(() => {\n setIsCreateDialogOpen(true);\n }, []);\n\n const handleCloseCreateDialog = useCallback(() => {\n if (!isCreating) {\n setIsCreateDialogOpen(false);\n }\n }, [isCreating]);\n\n const handleCreateDashboard = useCallback(\n async (data: { name: string; description: string; category: string; tags?: string[] }) => {\n setIsCreating(true);\n try {\n const newDashboard = await createDashboard({\n name: data.name,\n description: data.description,\n category: data.category,\n tags: data.tags,\n });\n\n if (newDashboard) {\n setIsCreateDialogOpen(false);\n navigate(`/dashboards/${newDashboard.id}/builder`);\n }\n } catch (err) {\n // Surface the failure instead of swallowing it: log for debugging,\n // notify on native, and rethrow so CreateDashboardDialog displays the error.\n console.error('Failed to create dashboard:', err);\n if (isNative()) void nativeNotify('error');\n throw err;\n } finally {\n setIsCreating(false);\n }\n },\n [createDashboard, navigate]\n );\n\n const handleOpenDashboard = useCallback(\n (dashboardId: string) => {\n navigate(`/dashboards/${dashboardId}`);\n },\n [navigate]\n );\n\n const handleEditDashboard = useCallback(\n (dashboardId: string, e: React.MouseEvent) => {\n e.stopPropagation();\n navigate(`/dashboards/${dashboardId}/builder`);\n },\n [navigate]\n );\n\n const handleDeleteDashboard = useCallback(\n async (dashboardId: string, e: React.MouseEvent) => {\n e.stopPropagation();\n const msg = tr('bigconsole.dashboards.confirmDelete', 'Are you sure you want to delete this dashboard?');\n const native = await nativeConfirm({\n title: 'Delete dashboard?',\n message: msg,\n okButtonTitle: 'Delete',\n cancelButtonTitle: 'Cancel',\n });\n const ok = native === null ? window.confirm(msg) : native;\n if (ok) {\n nativeImpact('medium');\n try {\n await deleteDashboard(dashboardId);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n }\n },\n [deleteDashboard, tr]\n );\n\n const handleCloneDashboard = useCallback(\n async (dashboardId: string, sourceName: string, e: React.MouseEvent) => {\n e.stopPropagation();\n const defaultName = tr('bigconsole.dashboards.clone.defaultSuffix', `${sourceName} (Copy)`);\n const name = window.prompt(\n tr('bigconsole.dashboards.clone.namePrompt', 'Name for the cloned dashboard:'),\n defaultName\n );\n if (!name || !name.trim()) return;\n nativeImpact('medium');\n try {\n const cloned = await cloneDashboard(dashboardId, name.trim());\n if (cloned) {\n if (isNative()) void nativeNotify('success');\n navigate(`/dashboards/${cloned.id}`);\n }\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n },\n [cloneDashboard, navigate, tr]\n );\n\n const handleOpenImportDialog = useCallback(() => {\n setIsImportDialogOpen(true);\n }, []);\n\n const handleCloseImportDialog = useCallback(() => {\n setIsImportDialogOpen(false);\n }, []);\n\n const handleImportSuccess = useCallback(\n (dashboardId: string, dashboardName: string) => {\n refetch();\n },\n [refetch]\n );\n\n // Format relative date\n const formatRelativeDate = (dateStr: string) => {\n const date = new Date(dateStr);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return tr('bigconsole.dashboards.time.justNow', 'Just now');\n if (diffMins < 60) return `${diffMins}${tr('bigconsole.dashboards.time.minutesAgoSuffix', 'm ago')}`;\n if (diffHours < 24) return `${diffHours}${tr('bigconsole.dashboards.time.hoursAgoSuffix', 'h ago')}`;\n if (diffDays < 7) return `${diffDays}${tr('bigconsole.dashboards.time.daysAgoSuffix', 'd ago')}`;\n\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: date.getFullYear() !== now.getFullYear() ? 'numeric' : undefined,\n }).format(date);\n };\n\n // Get widget count - uses widgetCount field from backend\n const getWidgetCount = (dashboard: (typeof dashboards)[0]) => {\n return dashboard.widgetCount ?? 0;\n };\n\n // Get page count\n const getPageCount = (dashboard: (typeof dashboards)[0]) => {\n return dashboard.pages?.length || 0;\n };\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <h3\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n }}\n >\n {tr('bigconsole.dashboards.error.title', 'Error loading dashboards')}\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()} style={{ marginTop: 'var(--space-formGap)' }}>\n {tr('bigconsole.dashboards.error.retry', 'Retry')}\n </Button>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div style={{ borderBottom: '1px solid var(--color-border)', backgroundColor: 'var(--color-bg-surface)' }}>\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n flexWrap: 'wrap',\n gap: 'var(--space-formGap)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)', minWidth: 0 }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <LayoutDashboard\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n {tr('bigconsole.dashboards.title', 'Dashboards')}\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n {tr('bigconsole.dashboards.subtitle', 'Create and manage your analytics dashboards')}\n </p>\n </div>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)', flexWrap: 'wrap' }}>\n <Button variant=\"outline\" onClick={handleOpenImportDialog}>\n <Upload\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.import', 'Import')}\n </Button>\n <Button onClick={handleOpenCreateDialog}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.create', 'Create Dashboard')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n {/* Search Bar */}\n <div style={{ marginBottom: 'var(--space-sectionGap)' }}>\n <div style={{ position: 'relative', maxWidth: '400px' }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder={tr('bigconsole.dashboards.search.placeholder', 'Search dashboards...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n\n {/* Loading state */}\n {loading && dashboards.length === 0 && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n {tr('bigconsole.dashboards.loading', 'Loading dashboards...')}\n </p>\n </div>\n </div>\n )}\n\n {/* Dashboard Grid */}\n {!loading && filteredDashboards.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(min(320px, 100%), 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredDashboards.map((dashboard) => (\n <Card\n key={dashboard.id}\n onClick={() => handleOpenDashboard(dashboard.id)}\n style={{\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n }}\n className=\"hover:shadow-md hover:border-primary/50\"\n >\n <CardContent style={{ padding: 'var(--space-cardPadding)' }}>\n {/* Card Header with Icon and Name */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n flexShrink: 0,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <LayoutDashboard\n style={{\n height: 'var(--size-icon-md)',\n width: 'var(--size-icon-md)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <h3\n style={{\n fontWeight: 'var(--font-weight-bold)',\n fontSize: 'var(--font-size-body-md)',\n margin: 0,\n color: 'var(--color-text-primary)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {dashboard.name}\n </h3>\n {dashboard.category && (\n <Badge\n variant=\"secondary\"\n style={{\n marginTop: 'var(--space-controlGap)',\n fontSize: '10px',\n fontWeight: 'var(--font-weight-semibold)',\n textTransform: 'uppercase',\n }}\n >\n {dashboard.category}\n </Badge>\n )}\n </div>\n </div>\n\n {/* Description */}\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n lineHeight: 'var(--font-lineHeight-normal)',\n color: 'var(--color-text-secondary)',\n margin: '0 0 var(--space-formGap) 0',\n minHeight: '40px',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n }}\n >\n {dashboard.description || tr('bigconsole.dashboards.card.noDescription', 'No description provided')}\n </p>\n\n {/* Stats Row */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-formGap)',\n marginBottom: 'var(--space-formGap)',\n padding: 'var(--space-controlGap) var(--space-cardPadding)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Layers\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-action-primary-bg)',\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n {getPageCount(dashboard)}\n </span>\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n {tr('bigconsole.dashboards.card.pages', 'pages')}\n </span>\n </div>\n <div\n style={{ width: '1px', height: 'var(--size-icon-sm)', backgroundColor: 'var(--color-border)' }}\n />\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <FileText\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-action-primary-bg)',\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n {getWidgetCount(dashboard)}\n </span>\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n {tr('bigconsole.dashboards.card.widgets', 'widgets')}\n </span>\n </div>\n </div>\n\n {/* Footer with Date and Actions */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingTop: 'var(--space-controlGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n }}\n >\n <Calendar\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-muted)',\n }}\n >\n {formatRelativeDate(dashboard.updatedAt)}\n </span>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => handleEditDashboard(dashboard.id, e)}\n style={{\n height: 'var(--size-controlHeight-sm)',\n width: 'var(--size-controlHeight-sm)',\n padding: 0,\n borderRadius: 'var(--radius-button)',\n }}\n title={tr('bigconsole.dashboards.actions.editTitle', 'Edit Dashboard')}\n >\n <Pencil style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => handleCloneDashboard(dashboard.id, dashboard.name, e)}\n style={{\n height: 'var(--size-controlHeight-sm)',\n width: 'var(--size-controlHeight-sm)',\n padding: 0,\n borderRadius: 'var(--radius-button)',\n }}\n title={tr('bigconsole.dashboards.actions.cloneTitle', 'Clone Dashboard')}\n >\n <Copy style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => handleDeleteDashboard(dashboard.id, e)}\n style={{\n height: 'var(--size-controlHeight-sm)',\n width: 'var(--size-controlHeight-sm)',\n padding: 0,\n borderRadius: 'var(--radius-button)',\n }}\n className=\"hover:text-destructive hover:bg-destructive/10\"\n title={tr('bigconsole.dashboards.actions.deleteTitle', 'Delete Dashboard')}\n >\n <Trash2 style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </Button>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n\n {/* Empty state */}\n {!loading && filteredDashboards.length === 0 && (\n <Card className=\"border-dashed\">\n <CardContent\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px var(--space-pagePadding)',\n }}\n >\n <div\n style={{\n display: 'flex',\n height: '80px',\n width: '80px',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '50%',\n backgroundColor: 'var(--color-bg-sunken)',\n marginBottom: 'var(--space-sectionGap)',\n }}\n >\n <FolderOpen\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-text-muted)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-semibold)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {searchQuery\n ? tr('bigconsole.dashboards.empty.filteredTitle', 'No dashboards found')\n : tr('bigconsole.dashboards.empty.title', 'No dashboards yet')}\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginBottom: 'var(--space-sectionGap)',\n textAlign: 'center',\n maxWidth: '360px',\n }}\n >\n {searchQuery\n ? tr('bigconsole.dashboards.empty.filteredDescription', 'Try adjusting your search terms')\n : tr(\n 'bigconsole.dashboards.empty.description',\n 'Get started by creating your first dashboard to visualize your data'\n )}\n </p>\n {!searchQuery && (\n <div\n style={{\n display: 'flex',\n gap: 'var(--space-controlGap)',\n flexWrap: 'wrap',\n justifyContent: 'center',\n }}\n >\n <Button variant=\"outline\" onClick={handleOpenImportDialog}>\n <Upload\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.importDashboard', 'Import Dashboard')}\n </Button>\n <Button onClick={handleOpenCreateDialog}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dashboards.actions.create', 'Create Dashboard')}\n </Button>\n </div>\n )}\n </CardContent>\n </Card>\n )}\n </div>\n\n {/* Create Dashboard Dialog */}\n <CreateDashboardDialog\n isOpen={isCreateDialogOpen}\n isCreating={isCreating}\n onClose={handleCloseCreateDialog}\n onCreate={handleCreateDashboard}\n />\n\n {/* Import Dashboard Dialog */}\n <ImportDashboardDialog\n isOpen={isImportDialogOpen}\n onClose={handleCloseImportDialog}\n onSuccess={handleImportSuccess}\n />\n </div>\n );\n});\n\nexport default DashboardsPage;\n"],"mappings":"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"}