@burdenoff/microfe-workspaces 2026.625.3 → 2026.625.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/hooks/useMemberMutations.js +6 -6
  2. package/dist/hooks/useMemberMutations.js.map +1 -1
  3. package/dist/pages/ActivityListPage.js +32 -48
  4. package/dist/pages/ActivityListPage.js.map +1 -1
  5. package/dist/pages/MembersListPage.js +196 -241
  6. package/dist/pages/MembersListPage.js.map +1 -1
  7. package/dist/pages/PendingInvitesPage.js +69 -78
  8. package/dist/pages/PendingInvitesPage.js.map +1 -1
  9. package/dist/pages/ProjectDetailPage.js +37 -52
  10. package/dist/pages/ProjectDetailPage.js.map +1 -1
  11. package/dist/pages/ProjectMembersPage.js +73 -86
  12. package/dist/pages/ProjectMembersPage.js.map +1 -1
  13. package/dist/pages/ProjectsListPage.js +103 -118
  14. package/dist/pages/ProjectsListPage.js.map +1 -1
  15. package/dist/pages/WorkspaceDetailPage.js +74 -76
  16. package/dist/pages/WorkspaceDetailPage.js.map +1 -1
  17. package/dist/pages/WorkspacesListPage.js +167 -178
  18. package/dist/pages/WorkspacesListPage.js.map +1 -1
  19. package/dist/pages/dashboard/widgets/AgentsWidget.js +21 -22
  20. package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -1
  21. package/dist/pages/dashboard/widgets/ProjectsWidget.js +26 -27
  22. package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
  23. package/dist/pages/dashboard/widgets/RecentActivityWidget.js +19 -23
  24. package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
  25. package/dist/pages/dashboard/widgets/SessionsWidget.js +30 -32
  26. package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -1
  27. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +18 -20
  28. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
  29. package/dist/pages/dashboard/widgets/VibesWidget.js +18 -19
  30. package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -1
  31. package/dist/pages/dashboard/widgets/WelcomeWidget.js +14 -12
  32. package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
  33. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
  34. package/dist/pages/dashboard/widgets/WorkspacesWidget.js +20 -21
  35. package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
  36. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"AgentsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/AgentsWidget.tsx"],"sourcesContent":["import { Bot, ArrowRight, Wifi, WifiOff, AlertTriangle } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nexport function AgentsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const fleet = workspaceData?.agentFleet ?? null;\n const total = fleet?.total ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Agent Fleet\"\n icon={<Bot className=\"size-4\" />}\n size=\"small\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/vibecontrols/agents')}\n >\n Open <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {!fleet || total === 0 ? (\n <div className=\"text-center py-3\">\n <p className=\"text-sm text-text-secondary mb-2\">No agents connected</p>\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/vibecontrols/agents/new')}>\n Connect agent\n </Button>\n </div>\n ) : (\n <div className=\"space-y-3\">\n <p className=\"text-2xl font-semibold text-text-primary\">\n {total}\n <span className=\"ml-1 text-xs font-normal text-text-secondary\">total</span>\n </p>\n <div className=\"grid grid-cols-3 gap-2 text-center\">\n <div className=\"rounded-md bg-status-success-bg/30 p-2\">\n <Wifi className=\"mx-auto size-4 text-status-success-text\" />\n <p className=\"mt-1 text-sm font-semibold text-text-primary\">{fleet.online}</p>\n <p className=\"text-[10px] text-text-secondary\">online</p>\n </div>\n <div className=\"rounded-md bg-status-warning-bg/30 p-2\">\n <AlertTriangle className=\"mx-auto size-4 text-status-warning-text\" />\n <p className=\"mt-1 text-sm font-semibold text-text-primary\">{fleet.degraded}</p>\n <p className=\"text-[10px] text-text-secondary\">degraded</p>\n </div>\n <div className=\"rounded-md bg-text-tertiary/10 p-2\">\n <WifiOff className=\"mx-auto size-4 text-text-tertiary\" />\n <p className=\"mt-1 text-sm font-semibold text-text-primary\">{fleet.offline}</p>\n <p className=\"text-[10px] text-text-secondary\">offline</p>\n </div>\n </div>\n {fleet.lastSeenAt ? (\n <p className=\"text-[11px] text-text-secondary text-center\">\n Last seen{' '}\n {new Date(fleet.lastSeenAt).toLocaleString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n month: 'short',\n day: 'numeric',\n })}\n </p>\n ) : null}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,EAAa,EAAE,kBAAe,cAAW,eAAyB;CAChF,IAAM,IAAQ,GAAe,cAAc,MACrC,IAAQ,GAAO,SAAS;AAE9B,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAK,WAAU,UAAW,CAAA;EAChC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,uBAAuB;aAJjD,CAKC,SACM,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACpC;;YAGV,CAAC,KAAS,MAAU,IACnB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAmC;IAAuB,CAAA,EACvE,kBAAC,GAAD;IAAQ,SAAQ;IAAU,MAAK;IAAK,eAAe,EAAS,2BAA2B;cAAE;IAEhF,CAAA,CACL;OAEN,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,KAAD;KAAG,WAAU;eAAb,CACG,GACD,kBAAC,QAAD;MAAM,WAAU;gBAA+C;MAAY,CAAA,CACzE;;IACJ,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAM,WAAU,2CAA4C,CAAA;QAC5D,kBAAC,KAAD;SAAG,WAAU;mBAAgD,EAAM;SAAW,CAAA;QAC9E,kBAAC,KAAD;SAAG,WAAU;mBAAkC;SAAU,CAAA;QACrD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAe,WAAU,2CAA4C,CAAA;QACrE,kBAAC,KAAD;SAAG,WAAU;mBAAgD,EAAM;SAAa,CAAA;QAChF,kBAAC,KAAD;SAAG,WAAU;mBAAkC;SAAY,CAAA;QACvD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAS,WAAU,qCAAsC,CAAA;QACzD,kBAAC,KAAD;SAAG,WAAU;mBAAgD,EAAM;SAAY,CAAA;QAC/E,kBAAC,KAAD;SAAG,WAAU;mBAAkC;SAAW,CAAA;QACtD;;MACF;;IACL,EAAM,aACL,kBAAC,KAAD;KAAG,WAAU;eAAb;MAA2D;MAC/C;MACT,IAAI,KAAK,EAAM,WAAW,CAAC,eAAe,KAAA,GAAW;OACpD,MAAM;OACN,QAAQ;OACR,OAAO;OACP,KAAK;OACN,CAAC;MACA;SACF;IACA;;EAEM,CAAA"}
1
+ {"version":3,"file":"AgentsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/AgentsWidget.tsx"],"sourcesContent":["import { Bot, ArrowRight, Wifi, WifiOff, AlertTriangle } from 'lucide-react';\nimport { Button, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nexport function AgentsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const fleet = workspaceData?.agentFleet ?? null;\n const total = fleet?.total ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Agent Fleet\"\n icon={<Bot className=\"size-4\" />}\n size=\"small\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/vibecontrols/agents')}\n >\n Open <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {!fleet || total === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-agents\"\n title=\"No agents connected\"\n className=\"py-4\"\n action={\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigate('/vibecontrols/agents/new')}\n >\n Connect agent\n </Button>\n }\n />\n ) : (\n <div className=\"space-y-3\">\n <p className=\"text-2xl font-semibold text-text-primary\">\n {total}\n <span className=\"ml-1 text-xs font-normal text-text-secondary\">total</span>\n </p>\n <div className=\"grid grid-cols-3 gap-2 text-center\">\n <div className=\"rounded-md bg-status-success-bg/30 p-2\">\n <Wifi\n className={`mx-auto size-4 text-status-success-text ${\n fleet.online > 0 ? 'motion-safe:animate-vc-glow-pulse' : ''\n }`}\n />\n <p className=\"mt-1 text-sm font-semibold text-text-primary\">{fleet.online}</p>\n <p className=\"text-[10px] text-text-secondary\">online</p>\n </div>\n <div className=\"rounded-md bg-status-warning-bg/30 p-2\">\n <AlertTriangle className=\"mx-auto size-4 text-status-warning-text\" />\n <p className=\"mt-1 text-sm font-semibold text-text-primary\">{fleet.degraded}</p>\n <p className=\"text-[10px] text-text-secondary\">degraded</p>\n </div>\n <div className=\"rounded-md bg-text-tertiary/10 p-2\">\n <WifiOff className=\"mx-auto size-4 text-text-tertiary\" />\n <p className=\"mt-1 text-sm font-semibold text-text-primary\">{fleet.offline}</p>\n <p className=\"text-[10px] text-text-secondary\">offline</p>\n </div>\n </div>\n {fleet.lastSeenAt ? (\n <p className=\"text-[11px] text-text-secondary text-center\">\n Last seen{' '}\n {new Date(fleet.lastSeenAt).toLocaleString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n month: 'short',\n day: 'numeric',\n })}\n </p>\n ) : null}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,EAAa,EAAE,kBAAe,cAAW,eAAyB;CAChF,IAAM,IAAQ,GAAe,cAAc,MACrC,IAAQ,GAAO,SAAS;AAE9B,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAK,WAAU,UAAW,CAAA;EAChC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,uBAAuB;aAJjD,CAKC,SACM,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACpC;;YAGV,CAAC,KAAS,MAAU,IACnB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,WAAU;GACV,QACE,kBAAC,GAAD;IACE,SAAQ;IACR,MAAK;IACL,eAAe,EAAS,2BAA2B;cACpD;IAEQ,CAAA;GAEX,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,KAAD;KAAG,WAAU;eAAb,CACG,GACD,kBAAC,QAAD;MAAM,WAAU;gBAA+C;MAAY,CAAA,CACzE;;IACJ,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EACE,WAAW,2CACT,EAAM,SAAS,IAAI,sCAAsC,MAE3D,CAAA;QACF,kBAAC,KAAD;SAAG,WAAU;mBAAgD,EAAM;SAAW,CAAA;QAC9E,kBAAC,KAAD;SAAG,WAAU;mBAAkC;SAAU,CAAA;QACrD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAe,WAAU,2CAA4C,CAAA;QACrE,kBAAC,KAAD;SAAG,WAAU;mBAAgD,EAAM;SAAa,CAAA;QAChF,kBAAC,KAAD;SAAG,WAAU;mBAAkC;SAAY,CAAA;QACvD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAS,WAAU,qCAAsC,CAAA;QACzD,kBAAC,KAAD;SAAG,WAAU;mBAAgD,EAAM;SAAY,CAAA;QAC/E,kBAAC,KAAD;SAAG,WAAU;mBAAkC;SAAW,CAAA;QACtD;;MACF;;IACL,EAAM,aACL,kBAAC,KAAD;KAAG,WAAU;eAAb;MAA2D;MAC/C;MACT,IAAI,KAAK,EAAM,WAAW,CAAC,eAAe,KAAA,GAAW;OACpD,MAAM;OACN,QAAQ;OACR,OAAO;OACP,KAAK;OACN,CAAC;MACA;SACF;IACA;;EAEM,CAAA"}
@@ -1,83 +1,82 @@
1
1
  import { WidgetWrapper as e } from "../WidgetWrapper.js";
2
2
  import { ArrowRight as t, Circle as n, FolderKanban as r } from "lucide-react";
3
3
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { Badge as o, Button as s } from "@burdenoff/fe-libs/ui";
4
+ import { Badge as o, Button as s, IllustratedEmptyState as c } from "@burdenoff/fe-libs/ui";
5
5
  //#region src/pages/dashboard/widgets/ProjectsWidget.tsx
6
- var c = {
6
+ var l = {
7
7
  ACTIVE: "bg-status-success-bg",
8
8
  INACTIVE: "bg-text-tertiary",
9
9
  ARCHIVED: "bg-status-warning-bg"
10
- }, l = {
10
+ }, u = {
11
11
  ACTIVE: "default",
12
12
  INACTIVE: "secondary",
13
13
  ARCHIVED: "outline"
14
14
  };
15
- function u({ workspaceData: u, isLoading: d, navigate: f }) {
16
- let p = u?.projects.items ?? [], m = u?.projects.total ?? 0, h = p.filter((e) => e.status === "ACTIVE").length, g = p.filter((e) => e.status === "INACTIVE").length;
15
+ function d({ workspaceData: d, isLoading: f, navigate: p }) {
16
+ let m = d?.projects.items ?? [], h = d?.projects.total ?? 0, g = m.filter((e) => e.status === "ACTIVE").length, _ = m.filter((e) => e.status === "INACTIVE").length;
17
17
  return /* @__PURE__ */ i(e, {
18
18
  title: "Projects",
19
19
  icon: /* @__PURE__ */ i(r, { className: "size-4" }),
20
20
  size: "medium",
21
- isLoading: d,
22
- unavailable: !u,
21
+ isLoading: f,
22
+ unavailable: !d,
23
23
  headerAction: /* @__PURE__ */ a(s, {
24
24
  variant: "ghost",
25
25
  size: "sm",
26
26
  className: "text-xs",
27
- onClick: () => f("/workspaces/projects"),
27
+ onClick: () => p("/workspaces/projects"),
28
28
  children: ["View all ", /* @__PURE__ */ i(t, { className: "ml-1 size-3" })]
29
29
  }),
30
- children: p.length === 0 ? /* @__PURE__ */ a("div", {
31
- className: "text-center py-4",
32
- children: [/* @__PURE__ */ i("p", {
33
- className: "text-sm text-text-secondary mb-2",
34
- children: "No projects yet"
35
- }), /* @__PURE__ */ i(s, {
30
+ children: m.length === 0 ? /* @__PURE__ */ i(c, {
31
+ illustration: "empty-data",
32
+ title: "No projects yet",
33
+ className: "py-4",
34
+ action: /* @__PURE__ */ i(s, {
36
35
  variant: "outline",
37
36
  size: "sm",
38
- onClick: () => f("/workspaces/projects"),
37
+ onClick: () => p("/workspaces/projects"),
39
38
  children: "Create a project"
40
- })]
39
+ })
41
40
  }) : /* @__PURE__ */ a("div", {
42
41
  className: "space-y-3",
43
- children: [m > 0 && /* @__PURE__ */ a("div", {
42
+ children: [h > 0 && /* @__PURE__ */ a("div", {
44
43
  className: "flex items-center gap-3 text-xs text-text-secondary",
45
44
  children: [
46
45
  /* @__PURE__ */ a("span", {
47
46
  className: "flex items-center gap-1",
48
47
  children: [
49
- /* @__PURE__ */ i(n, { className: "size-2 fill-status-success-bg text-status-success-bg" }),
50
- h,
48
+ /* @__PURE__ */ i(n, { className: `size-2 fill-status-success-bg text-status-success-bg ${g > 0 ? "motion-safe:animate-vc-glow-pulse" : ""}` }),
49
+ g,
51
50
  " active"
52
51
  ]
53
52
  }),
54
- g > 0 && /* @__PURE__ */ a("span", {
53
+ _ > 0 && /* @__PURE__ */ a("span", {
55
54
  className: "flex items-center gap-1",
56
55
  children: [
57
56
  /* @__PURE__ */ i(n, { className: "size-2 fill-text-tertiary text-text-tertiary" }),
58
- g,
57
+ _,
59
58
  " inactive"
60
59
  ]
61
60
  }),
62
61
  /* @__PURE__ */ a("span", {
63
62
  className: "ml-auto font-medium",
64
- children: [m, " total"]
63
+ children: [h, " total"]
65
64
  })
66
65
  ]
67
66
  }), /* @__PURE__ */ i("div", {
68
67
  className: "space-y-2",
69
- children: p.slice(0, 4).map((e) => /* @__PURE__ */ a("button", {
68
+ children: m.slice(0, 4).map((e) => /* @__PURE__ */ a("button", {
70
69
  type: "button",
71
70
  className: "w-full flex items-center justify-between p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left",
72
- onClick: () => f(`/workspaces/${e.workspaceId}/projects`),
71
+ onClick: () => p(`/workspaces/${e.workspaceId}/projects`),
73
72
  children: [/* @__PURE__ */ a("div", {
74
73
  className: "flex items-center gap-2 min-w-0",
75
- children: [/* @__PURE__ */ i(n, { className: `size-2 ${c[e.status] || "bg-text-tertiary"} fill-current` }), /* @__PURE__ */ i("span", {
74
+ children: [/* @__PURE__ */ i(n, { className: `size-2 ${l[e.status] || "bg-text-tertiary"} fill-current ${e.status === "ACTIVE" ? "motion-safe:animate-vc-glow-pulse" : ""}` }), /* @__PURE__ */ i("span", {
76
75
  className: "text-sm font-medium text-text-primary truncate",
77
76
  children: e.name
78
77
  })]
79
78
  }), /* @__PURE__ */ i(o, {
80
- variant: l[e.status] || "outline",
79
+ variant: u[e.status] || "outline",
81
80
  className: "text-[10px] shrink-0",
82
81
  children: e.key
83
82
  })]
@@ -87,6 +86,6 @@ function u({ workspaceData: u, isLoading: d, navigate: f }) {
87
86
  });
88
87
  }
89
88
  //#endregion
90
- export { u as ProjectsWidget };
89
+ export { d as ProjectsWidget };
91
90
 
92
91
  //# sourceMappingURL=ProjectsWidget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/ProjectsWidget.tsx"],"sourcesContent":["import { FolderKanban, ArrowRight, Circle } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst statusColors: Record<string, string> = {\n ACTIVE: 'bg-status-success-bg',\n INACTIVE: 'bg-text-tertiary',\n ARCHIVED: 'bg-status-warning-bg',\n};\n\nconst statusVariant: Record<string, 'default' | 'secondary' | 'outline'> = {\n ACTIVE: 'default',\n INACTIVE: 'secondary',\n ARCHIVED: 'outline',\n};\n\nexport function ProjectsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const projects = workspaceData?.projects.items ?? [];\n const total = workspaceData?.projects.total ?? 0;\n\n // Status breakdown\n const activeCount = projects.filter((p) => p.status === 'ACTIVE').length;\n const inactiveCount = projects.filter((p) => p.status === 'INACTIVE').length;\n\n return (\n <WidgetWrapper\n title=\"Projects\"\n icon={<FolderKanban className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/workspaces/projects')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {projects.length === 0 ? (\n <div className=\"text-center py-4\">\n <p className=\"text-sm text-text-secondary mb-2\">No projects yet</p>\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/workspaces/projects')}>\n Create a project\n </Button>\n </div>\n ) : (\n <div className=\"space-y-3\">\n {total > 0 && (\n <div className=\"flex items-center gap-3 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Circle className=\"size-2 fill-status-success-bg text-status-success-bg\" />\n {activeCount} active\n </span>\n {inactiveCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <Circle className=\"size-2 fill-text-tertiary text-text-tertiary\" />\n {inactiveCount} inactive\n </span>\n )}\n <span className=\"ml-auto font-medium\">{total} total</span>\n </div>\n )}\n <div className=\"space-y-2\">\n {projects.slice(0, 4).map((proj) => (\n <button\n key={proj.id}\n type=\"button\"\n className=\"w-full flex items-center justify-between p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left\"\n onClick={() => navigate(`/workspaces/${proj.workspaceId}/projects`)}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <Circle\n className={`size-2 ${statusColors[proj.status] || 'bg-text-tertiary'} fill-current`}\n />\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {proj.name}\n </span>\n </div>\n <Badge\n variant={statusVariant[proj.status] || 'outline'}\n className=\"text-[10px] shrink-0\"\n >\n {proj.key}\n </Badge>\n </button>\n ))}\n </div>\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAuC;CAC3C,QAAQ;CACR,UAAU;CACV,UAAU;CACX,EAEK,IAAqE;CACzE,QAAQ;CACR,UAAU;CACV,UAAU;CACX;AAED,SAAgB,EAAe,EAAE,kBAAe,cAAW,eAAyB;CAClF,IAAM,IAAW,GAAe,SAAS,SAAS,EAAE,EAC9C,IAAQ,GAAe,SAAS,SAAS,GAGzC,IAAc,EAAS,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,QAC5D,IAAgB,EAAS,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC;AAEtE,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAc,WAAU,UAAW,CAAA;EACzC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,uBAAuB;aAJjD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAS,WAAW,IACnB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAmC;IAAmB,CAAA,EACnE,kBAAC,GAAD;IAAQ,SAAQ;IAAU,MAAK;IAAK,eAAe,EAAS,uBAAuB;cAAE;IAE5E,CAAA,CACL;OAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,IAAQ,KACP,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACE,kBAAC,GAAD,EAAQ,WAAU,wDAAyD,CAAA;OAC1E;OAAY;OACR;;KACN,IAAgB,KACf,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACE,kBAAC,GAAD,EAAQ,WAAU,gDAAiD,CAAA;OAClE;OAAc;OACV;;KAET,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CAAuC,GAAM,SAAa;;KACtD;OAER,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAS,MAAM,GAAG,EAAE,CAAC,KAAK,MACzB,kBAAC,UAAD;KAEE,MAAK;KACL,WAAU;KACV,eAAe,EAAS,eAAe,EAAK,YAAY,WAAW;eAJrE,CAME,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EACE,WAAW,UAAU,EAAa,EAAK,WAAW,mBAAmB,gBACrE,CAAA,EACF,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAK;OACD,CAAA,CACH;SACN,kBAAC,GAAD;MACE,SAAS,EAAc,EAAK,WAAW;MACvC,WAAU;gBAET,EAAK;MACA,CAAA,CACD;OAnBF,EAAK,GAmBH,CACT;IACE,CAAA,CACF;;EAEM,CAAA"}
1
+ {"version":3,"file":"ProjectsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/ProjectsWidget.tsx"],"sourcesContent":["import { FolderKanban, ArrowRight, Circle } from 'lucide-react';\nimport { Badge, Button, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst statusColors: Record<string, string> = {\n ACTIVE: 'bg-status-success-bg',\n INACTIVE: 'bg-text-tertiary',\n ARCHIVED: 'bg-status-warning-bg',\n};\n\nconst statusVariant: Record<string, 'default' | 'secondary' | 'outline'> = {\n ACTIVE: 'default',\n INACTIVE: 'secondary',\n ARCHIVED: 'outline',\n};\n\nexport function ProjectsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const projects = workspaceData?.projects.items ?? [];\n const total = workspaceData?.projects.total ?? 0;\n\n // Status breakdown\n const activeCount = projects.filter((p) => p.status === 'ACTIVE').length;\n const inactiveCount = projects.filter((p) => p.status === 'INACTIVE').length;\n\n return (\n <WidgetWrapper\n title=\"Projects\"\n icon={<FolderKanban className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/workspaces/projects')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {projects.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No projects yet\"\n className=\"py-4\"\n action={\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/workspaces/projects')}>\n Create a project\n </Button>\n }\n />\n ) : (\n <div className=\"space-y-3\">\n {total > 0 && (\n <div className=\"flex items-center gap-3 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Circle\n className={`size-2 fill-status-success-bg text-status-success-bg ${\n activeCount > 0 ? 'motion-safe:animate-vc-glow-pulse' : ''\n }`}\n />\n {activeCount} active\n </span>\n {inactiveCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <Circle className=\"size-2 fill-text-tertiary text-text-tertiary\" />\n {inactiveCount} inactive\n </span>\n )}\n <span className=\"ml-auto font-medium\">{total} total</span>\n </div>\n )}\n <div className=\"space-y-2\">\n {projects.slice(0, 4).map((proj) => (\n <button\n key={proj.id}\n type=\"button\"\n className=\"w-full flex items-center justify-between p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left\"\n onClick={() => navigate(`/workspaces/${proj.workspaceId}/projects`)}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <Circle\n className={`size-2 ${statusColors[proj.status] || 'bg-text-tertiary'} fill-current ${\n proj.status === 'ACTIVE' ? 'motion-safe:animate-vc-glow-pulse' : ''\n }`}\n />\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {proj.name}\n </span>\n </div>\n <Badge\n variant={statusVariant[proj.status] || 'outline'}\n className=\"text-[10px] shrink-0\"\n >\n {proj.key}\n </Badge>\n </button>\n ))}\n </div>\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAuC;CAC3C,QAAQ;CACR,UAAU;CACV,UAAU;CACX,EAEK,IAAqE;CACzE,QAAQ;CACR,UAAU;CACV,UAAU;CACX;AAED,SAAgB,EAAe,EAAE,kBAAe,cAAW,eAAyB;CAClF,IAAM,IAAW,GAAe,SAAS,SAAS,EAAE,EAC9C,IAAQ,GAAe,SAAS,SAAS,GAGzC,IAAc,EAAS,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,QAC5D,IAAgB,EAAS,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC;AAEtE,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAc,WAAU,UAAW,CAAA;EACzC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,uBAAuB;aAJjD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAS,WAAW,IACnB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,WAAU;GACV,QACE,kBAAC,GAAD;IAAQ,SAAQ;IAAU,MAAK;IAAK,eAAe,EAAS,uBAAuB;cAAE;IAE5E,CAAA;GAEX,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,IAAQ,KACP,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACE,kBAAC,GAAD,EACE,WAAW,wDACT,IAAc,IAAI,sCAAsC,MAE1D,CAAA;OACD;OAAY;OACR;;KACN,IAAgB,KACf,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACE,kBAAC,GAAD,EAAQ,WAAU,gDAAiD,CAAA;OAClE;OAAc;OACV;;KAET,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CAAuC,GAAM,SAAa;;KACtD;OAER,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAS,MAAM,GAAG,EAAE,CAAC,KAAK,MACzB,kBAAC,UAAD;KAEE,MAAK;KACL,WAAU;KACV,eAAe,EAAS,eAAe,EAAK,YAAY,WAAW;eAJrE,CAME,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EACE,WAAW,UAAU,EAAa,EAAK,WAAW,mBAAmB,gBACnE,EAAK,WAAW,WAAW,sCAAsC,MAEnE,CAAA,EACF,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAK;OACD,CAAA,CACH;SACN,kBAAC,GAAD;MACE,SAAS,EAAc,EAAK,WAAW;MACvC,WAAU;gBAET,EAAK;MACA,CAAA,CACD;OArBF,EAAK,GAqBH,CACT;IACE,CAAA,CACF;;EAEM,CAAA"}
@@ -1,10 +1,10 @@
1
1
  import { WidgetWrapper as e } from "../WidgetWrapper.js";
2
2
  import { Activity as t, ArrowRight as n } from "lucide-react";
3
3
  import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
- import { Button as a } from "@burdenoff/fe-libs/ui";
5
- import { formatRelativeTime as o } from "@burdenoff/fe-libs/shared/utils";
4
+ import { Button as a, IllustratedEmptyState as o } from "@burdenoff/fe-libs/ui";
5
+ import { formatRelativeTime as s } from "@burdenoff/fe-libs/shared/utils";
6
6
  //#region src/pages/dashboard/widgets/RecentActivityWidget.tsx
7
- var s = {
7
+ var c = {
8
8
  "workspace.created": "Created workspace",
9
9
  "workspace.updated": "Updated workspace",
10
10
  "project.created": "Created project",
@@ -18,7 +18,7 @@ var s = {
18
18
  "workflow.completed": "Completed workflow",
19
19
  "event.created": "Created event",
20
20
  "comment.added": "Added comment"
21
- }, c = {
21
+ }, l = {
22
22
  workspace: "bg-status-info-bg-subtle text-status-info-text",
23
23
  project: "bg-status-success-bg-subtle text-status-success-text",
24
24
  member: "bg-accent-purple-subtle text-accent-purple",
@@ -27,34 +27,30 @@ var s = {
27
27
  workflow: "bg-accent-orange-subtle text-accent-orange",
28
28
  calendar: "bg-accent-pink-subtle text-accent-pink"
29
29
  };
30
- function l({ workspaceData: l, isLoading: u, navigate: d }) {
31
- let f = l?.recentActivities ?? [];
30
+ function u({ workspaceData: u, isLoading: d, navigate: f }) {
31
+ let p = u?.recentActivities ?? [];
32
32
  return /* @__PURE__ */ r(e, {
33
33
  title: "Recent Activity",
34
34
  icon: /* @__PURE__ */ r(t, { className: "size-4" }),
35
35
  size: "large",
36
- isLoading: u,
37
- unavailable: !l,
36
+ isLoading: d,
37
+ unavailable: !u,
38
38
  headerAction: /* @__PURE__ */ i(a, {
39
39
  variant: "ghost",
40
40
  size: "sm",
41
41
  className: "text-xs",
42
- onClick: () => d("/workspaces/activity"),
42
+ onClick: () => f("/workspaces/activity"),
43
43
  children: ["View all ", /* @__PURE__ */ r(n, { className: "ml-1 size-3" })]
44
44
  }),
45
- children: f.length === 0 ? /* @__PURE__ */ i("div", {
46
- className: "text-center py-6",
47
- children: [/* @__PURE__ */ r("p", {
48
- className: "text-sm text-text-secondary",
49
- children: "No recent activity"
50
- }), /* @__PURE__ */ r("p", {
51
- className: "text-xs text-text-secondary mt-1",
52
- children: "Activity will appear here as you use the platform"
53
- })]
45
+ children: p.length === 0 ? /* @__PURE__ */ r(o, {
46
+ illustration: "empty-data",
47
+ title: "No recent activity",
48
+ description: "Activity will appear here as you use the platform",
49
+ className: "py-6"
54
50
  }) : /* @__PURE__ */ r("div", {
55
51
  className: "space-y-1",
56
- children: f.map((e, t) => {
57
- let n = e.resourceType || "workspace", a = c[n] || "bg-bg-sunken text-text-secondary", l = o(new Date(e.timestamp));
52
+ children: p.map((e, t) => {
53
+ let n = e.resourceType || "workspace", a = l[n] || "bg-bg-sunken text-text-secondary", o = s(new Date(e.timestamp));
58
54
  return /* @__PURE__ */ i("div", {
59
55
  className: "flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 transition-colors",
60
56
  children: [/* @__PURE__ */ r("div", {
@@ -64,10 +60,10 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
64
60
  className: "min-w-0 flex-1",
65
61
  children: [/* @__PURE__ */ r("p", {
66
62
  className: "text-sm text-text-primary truncate",
67
- children: e.description || s[e.action] || e.action
63
+ children: e.description || c[e.action] || e.action
68
64
  }), /* @__PURE__ */ r("p", {
69
65
  className: "text-xs text-text-secondary",
70
- children: l
66
+ children: o
71
67
  })]
72
68
  })]
73
69
  }, e.id || t);
@@ -76,6 +72,6 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
76
72
  });
77
73
  }
78
74
  //#endregion
79
- export { l as RecentActivityWidget };
75
+ export { u as RecentActivityWidget };
80
76
 
81
77
  //# sourceMappingURL=RecentActivityWidget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RecentActivityWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/RecentActivityWidget.tsx"],"sourcesContent":["import { Activity, ArrowRight } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\nimport { formatRelativeTime } from '@burdenoff/fe-libs/shared/utils';\n\nconst actionLabels: Record<string, string> = {\n 'workspace.created': 'Created workspace',\n 'workspace.updated': 'Updated workspace',\n 'project.created': 'Created project',\n 'project.updated': 'Updated project',\n 'member.added': 'Added member',\n 'member.removed': 'Removed member',\n 'file.uploaded': 'Uploaded file',\n 'tag.created': 'Created tag',\n 'tag.assigned': 'Assigned tag',\n 'workflow.started': 'Started workflow',\n 'workflow.completed': 'Completed workflow',\n 'event.created': 'Created event',\n 'comment.added': 'Added comment',\n};\n\nconst entityIcons: Record<string, string> = {\n workspace: 'bg-status-info-bg-subtle text-status-info-text',\n project: 'bg-status-success-bg-subtle text-status-success-text',\n member: 'bg-accent-purple-subtle text-accent-purple',\n file: 'bg-status-warning-bg-subtle text-status-warning-text',\n tag: 'bg-accent-cyan-subtle text-accent-cyan',\n workflow: 'bg-accent-orange-subtle text-accent-orange',\n calendar: 'bg-accent-pink-subtle text-accent-pink',\n};\n\nexport function RecentActivityWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const activities = workspaceData?.recentActivities ?? [];\n\n return (\n <WidgetWrapper\n title=\"Recent Activity\"\n icon={<Activity className=\"size-4\" />}\n size=\"large\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/workspaces/activity')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {activities.length === 0 ? (\n <div className=\"text-center py-6\">\n <p className=\"text-sm text-text-secondary\">No recent activity</p>\n <p className=\"text-xs text-text-secondary mt-1\">\n Activity will appear here as you use the platform\n </p>\n </div>\n ) : (\n <div className=\"space-y-1\">\n {activities.map((activity, idx) => {\n const resourceType = activity.resourceType || 'workspace';\n const colorClass = entityIcons[resourceType] || 'bg-bg-sunken text-text-secondary';\n const timeAgo = formatRelativeTime(new Date(activity.timestamp));\n return (\n <div\n key={activity.id || idx}\n className=\"flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 transition-colors\"\n >\n <div\n className={`rounded-full size-7 flex items-center justify-center text-xs font-bold shrink-0 ${colorClass}`}\n >\n {resourceType.charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm text-text-primary truncate\">\n {activity.description || actionLabels[activity.action] || activity.action}\n </p>\n <p className=\"text-xs text-text-secondary\">{timeAgo}</p>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;;AAMA,IAAM,IAAuC;CAC3C,qBAAqB;CACrB,qBAAqB;CACrB,mBAAmB;CACnB,mBAAmB;CACnB,gBAAgB;CAChB,kBAAkB;CAClB,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAChB,oBAAoB;CACpB,sBAAsB;CACtB,iBAAiB;CACjB,iBAAiB;CAClB,EAEK,IAAsC;CAC1C,WAAW;CACX,SAAS;CACT,QAAQ;CACR,MAAM;CACN,KAAK;CACL,UAAU;CACV,UAAU;CACX;AAED,SAAgB,EAAqB,EAAE,kBAAe,cAAW,eAAyB;CACxF,IAAM,IAAa,GAAe,oBAAoB,EAAE;AAExD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,uBAAuB;aAJjD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAW,WAAW,IACrB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAAsB,CAAA,EACjE,kBAAC,KAAD;IAAG,WAAU;cAAmC;IAE5C,CAAA,CACA;OAEN,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAW,KAAK,GAAU,MAAQ;IACjC,IAAM,IAAe,EAAS,gBAAgB,aACxC,IAAa,EAAY,MAAiB,oCAC1C,IAAU,EAAmB,IAAI,KAAK,EAAS,UAAU,CAAC;AAChE,WACE,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MACE,WAAW,mFAAmF;gBAE7F,EAAa,OAAO,EAAE,CAAC,aAAa;MACjC,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAS,eAAe,EAAa,EAAS,WAAW,EAAS;OACjE,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAA+B;OAAY,CAAA,CACpD;QACF;OAdC,EAAS,MAAM,EAchB;KAER;GACE,CAAA;EAEM,CAAA"}
1
+ {"version":3,"file":"RecentActivityWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/RecentActivityWidget.tsx"],"sourcesContent":["import { Activity, ArrowRight } from 'lucide-react';\nimport { Button, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\nimport { formatRelativeTime } from '@burdenoff/fe-libs/shared/utils';\n\nconst actionLabels: Record<string, string> = {\n 'workspace.created': 'Created workspace',\n 'workspace.updated': 'Updated workspace',\n 'project.created': 'Created project',\n 'project.updated': 'Updated project',\n 'member.added': 'Added member',\n 'member.removed': 'Removed member',\n 'file.uploaded': 'Uploaded file',\n 'tag.created': 'Created tag',\n 'tag.assigned': 'Assigned tag',\n 'workflow.started': 'Started workflow',\n 'workflow.completed': 'Completed workflow',\n 'event.created': 'Created event',\n 'comment.added': 'Added comment',\n};\n\nconst entityIcons: Record<string, string> = {\n workspace: 'bg-status-info-bg-subtle text-status-info-text',\n project: 'bg-status-success-bg-subtle text-status-success-text',\n member: 'bg-accent-purple-subtle text-accent-purple',\n file: 'bg-status-warning-bg-subtle text-status-warning-text',\n tag: 'bg-accent-cyan-subtle text-accent-cyan',\n workflow: 'bg-accent-orange-subtle text-accent-orange',\n calendar: 'bg-accent-pink-subtle text-accent-pink',\n};\n\nexport function RecentActivityWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const activities = workspaceData?.recentActivities ?? [];\n\n return (\n <WidgetWrapper\n title=\"Recent Activity\"\n icon={<Activity className=\"size-4\" />}\n size=\"large\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/workspaces/activity')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {activities.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No recent activity\"\n description=\"Activity will appear here as you use the platform\"\n className=\"py-6\"\n />\n ) : (\n <div className=\"space-y-1\">\n {activities.map((activity, idx) => {\n const resourceType = activity.resourceType || 'workspace';\n const colorClass = entityIcons[resourceType] || 'bg-bg-sunken text-text-secondary';\n const timeAgo = formatRelativeTime(new Date(activity.timestamp));\n return (\n <div\n key={activity.id || idx}\n className=\"flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 transition-colors\"\n >\n <div\n className={`rounded-full size-7 flex items-center justify-center text-xs font-bold shrink-0 ${colorClass}`}\n >\n {resourceType.charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm text-text-primary truncate\">\n {activity.description || actionLabels[activity.action] || activity.action}\n </p>\n <p className=\"text-xs text-text-secondary\">{timeAgo}</p>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;;AAMA,IAAM,IAAuC;CAC3C,qBAAqB;CACrB,qBAAqB;CACrB,mBAAmB;CACnB,mBAAmB;CACnB,gBAAgB;CAChB,kBAAkB;CAClB,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAChB,oBAAoB;CACpB,sBAAsB;CACtB,iBAAiB;CACjB,iBAAiB;CAClB,EAEK,IAAsC;CAC1C,WAAW;CACX,SAAS;CACT,QAAQ;CACR,MAAM;CACN,KAAK;CACL,UAAU;CACV,UAAU;CACX;AAED,SAAgB,EAAqB,EAAE,kBAAe,cAAW,eAAyB;CACxF,IAAM,IAAa,GAAe,oBAAoB,EAAE;AAExD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,uBAAuB;aAJjD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAW,WAAW,IACrB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,WAAU;GACV,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAW,KAAK,GAAU,MAAQ;IACjC,IAAM,IAAe,EAAS,gBAAgB,aACxC,IAAa,EAAY,MAAiB,oCAC1C,IAAU,EAAmB,IAAI,KAAK,EAAS,UAAU,CAAC;AAChE,WACE,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MACE,WAAW,mFAAmF;gBAE7F,EAAa,OAAO,EAAE,CAAC,aAAa;MACjC,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAS,eAAe,EAAa,EAAS,WAAW,EAAS;OACjE,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAA+B;OAAY,CAAA,CACpD;QACF;OAdC,EAAS,MAAM,EAchB;KAER;GACE,CAAA;EAEM,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { WidgetWrapper as e } from "../WidgetWrapper.js";
2
- import { Activity as t, ArrowRight as n, Terminal as r } from "lucide-react";
3
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { Badge as o, Button as s } from "@burdenoff/fe-libs/ui";
2
+ import { ArrowRight as t, Terminal as n } from "lucide-react";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
+ import { Badge as a, Button as o, IllustratedEmptyState as s } from "@burdenoff/fe-libs/ui";
5
5
  //#region src/pages/dashboard/widgets/SessionsWidget.tsx
6
6
  var c = {
7
7
  RUNNING: "bg-status-success-bg text-status-success-text",
@@ -9,8 +9,8 @@ var c = {
9
9
  STARTING: "bg-status-warning-bg text-status-warning-text",
10
10
  STOPPED: "bg-text-tertiary/20 text-text-tertiary",
11
11
  ERROR: "bg-status-error-bg text-status-error-text"
12
- };
13
- function l(e) {
12
+ }, l = new Set(["RUNNING", "ACTIVE"]);
13
+ function u(e) {
14
14
  if (!e) return "";
15
15
  let t = Date.now() - new Date(e).getTime(), n = Math.floor(t / 6e4);
16
16
  if (n < 1) return "just now";
@@ -21,51 +21,49 @@ function l(e) {
21
21
  day: "numeric"
22
22
  });
23
23
  }
24
- function u({ workspaceData: u, isLoading: d, navigate: f }) {
25
- let p = u?.activeSessions ?? [];
26
- return /* @__PURE__ */ i(e, {
24
+ function d({ workspaceData: d, isLoading: f, navigate: p }) {
25
+ let m = d?.activeSessions ?? [];
26
+ return /* @__PURE__ */ r(e, {
27
27
  title: "Active Sessions",
28
- icon: /* @__PURE__ */ i(r, { className: "size-4" }),
28
+ icon: /* @__PURE__ */ r(n, { className: "size-4" }),
29
29
  size: "medium",
30
- isLoading: d,
31
- unavailable: !u,
32
- headerAction: /* @__PURE__ */ a(s, {
30
+ isLoading: f,
31
+ unavailable: !d,
32
+ headerAction: /* @__PURE__ */ i(o, {
33
33
  variant: "ghost",
34
34
  size: "sm",
35
35
  className: "text-xs",
36
- onClick: () => f("/vibecontrols/sessions"),
37
- children: ["View all ", /* @__PURE__ */ i(n, { className: "ml-1 size-3" })]
36
+ onClick: () => p("/vibecontrols/sessions"),
37
+ children: ["View all ", /* @__PURE__ */ r(t, { className: "ml-1 size-3" })]
38
38
  }),
39
- children: p.length === 0 ? /* @__PURE__ */ a("div", {
40
- className: "text-center py-4",
41
- children: [/* @__PURE__ */ i(t, { className: "mx-auto mb-2 size-5 text-text-secondary" }), /* @__PURE__ */ i("p", {
42
- className: "text-sm text-text-secondary",
43
- children: "No active sessions"
44
- })]
45
- }) : /* @__PURE__ */ i("ul", {
39
+ children: m.length === 0 ? /* @__PURE__ */ r(s, {
40
+ illustration: "empty-sessions",
41
+ title: "No active sessions",
42
+ className: "py-6"
43
+ }) : /* @__PURE__ */ r("ul", {
46
44
  className: "space-y-1.5",
47
- children: p.slice(0, 5).map((e) => /* @__PURE__ */ i("li", { children: /* @__PURE__ */ a("button", {
45
+ children: m.slice(0, 5).map((e) => /* @__PURE__ */ r("li", { children: /* @__PURE__ */ i("button", {
48
46
  type: "button",
49
- onClick: () => f(`/vibecontrols/sessions/${e.id}`),
47
+ onClick: () => p(`/vibecontrols/sessions/${e.id}`),
50
48
  className: "flex w-full items-center justify-between gap-2 rounded-md p-2 text-left transition-colors hover:bg-accent/5",
51
- children: [/* @__PURE__ */ a("div", {
49
+ children: [/* @__PURE__ */ i("div", {
52
50
  className: "min-w-0 flex-1",
53
- children: [/* @__PURE__ */ i("p", {
51
+ children: [/* @__PURE__ */ r("p", {
54
52
  className: "truncate text-sm font-medium text-text-primary",
55
53
  children: e.name || `Session ${e.id.slice(0, 8)}`
56
- }), e.agent?.name ? /* @__PURE__ */ i("p", {
54
+ }), e.agent?.name ? /* @__PURE__ */ r("p", {
57
55
  className: "truncate text-[11px] text-text-secondary",
58
56
  children: e.agent.name
59
57
  }) : null]
60
- }), /* @__PURE__ */ a("div", {
58
+ }), /* @__PURE__ */ i("div", {
61
59
  className: "flex flex-col items-end gap-1",
62
- children: [/* @__PURE__ */ i(o, {
60
+ children: [/* @__PURE__ */ r(a, {
63
61
  variant: "outline",
64
- className: `text-[10px] ${c[e.status] ?? ""}`,
62
+ className: `text-[10px] ${c[e.status] ?? ""} ${l.has(e.status) ? "motion-safe:animate-vc-glow-pulse" : ""}`,
65
63
  children: e.status.toLowerCase()
66
- }), e.startedAt ? /* @__PURE__ */ i("span", {
64
+ }), e.startedAt ? /* @__PURE__ */ r("span", {
67
65
  className: "text-[10px] text-text-secondary",
68
- children: l(e.startedAt)
66
+ children: u(e.startedAt)
69
67
  }) : null]
70
68
  })]
71
69
  }) }, e.id))
@@ -73,6 +71,6 @@ function u({ workspaceData: u, isLoading: d, navigate: f }) {
73
71
  });
74
72
  }
75
73
  //#endregion
76
- export { u as SessionsWidget };
74
+ export { d as SessionsWidget };
77
75
 
78
76
  //# sourceMappingURL=SessionsWidget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/SessionsWidget.tsx"],"sourcesContent":["import { Terminal, ArrowRight, Activity } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst STATUS_BADGE: Record<string, string> = {\n RUNNING: 'bg-status-success-bg text-status-success-text',\n ACTIVE: 'bg-status-success-bg text-status-success-text',\n STARTING: 'bg-status-warning-bg text-status-warning-text',\n STOPPED: 'bg-text-tertiary/20 text-text-tertiary',\n ERROR: 'bg-status-error-bg text-status-error-text',\n};\n\nfunction formatRelative(dateString: string | null | undefined): string {\n if (!dateString) return '';\n const diffMs = Date.now() - new Date(dateString).getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return `${diffMin}m`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return `${diffHr}h`;\n return new Date(dateString).toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n });\n}\n\nexport function SessionsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const sessions = workspaceData?.activeSessions ?? [];\n\n return (\n <WidgetWrapper\n title=\"Active Sessions\"\n icon={<Terminal className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/vibecontrols/sessions')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {sessions.length === 0 ? (\n <div className=\"text-center py-4\">\n <Activity className=\"mx-auto mb-2 size-5 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">No active sessions</p>\n </div>\n ) : (\n <ul className=\"space-y-1.5\">\n {sessions.slice(0, 5).map((s) => (\n <li key={s.id}>\n <button\n type=\"button\"\n onClick={() => navigate(`/vibecontrols/sessions/${s.id}`)}\n className=\"flex w-full items-center justify-between gap-2 rounded-md p-2 text-left transition-colors hover:bg-accent/5\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {s.name || `Session ${s.id.slice(0, 8)}`}\n </p>\n {s.agent?.name ? (\n <p className=\"truncate text-[11px] text-text-secondary\">{s.agent.name}</p>\n ) : null}\n </div>\n <div className=\"flex flex-col items-end gap-1\">\n <Badge\n variant=\"outline\"\n className={`text-[10px] ${STATUS_BADGE[s.status] ?? ''}`}\n >\n {s.status.toLowerCase()}\n </Badge>\n {s.startedAt ? (\n <span className=\"text-[10px] text-text-secondary\">\n {formatRelative(s.startedAt)}\n </span>\n ) : null}\n </div>\n </button>\n </li>\n ))}\n </ul>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAuC;CAC3C,SAAS;CACT,QAAQ;CACR,UAAU;CACV,SAAS;CACT,OAAO;CACR;AAED,SAAS,EAAe,GAA+C;AACrE,KAAI,CAAC,EAAY,QAAO;CACxB,IAAM,IAAS,KAAK,KAAK,GAAG,IAAI,KAAK,EAAW,CAAC,SAAS,EACpD,IAAU,KAAK,MAAM,IAAS,IAAM;AAC1C,KAAI,IAAU,EAAG,QAAO;AACxB,KAAI,IAAU,GAAI,QAAO,GAAG,EAAQ;CACpC,IAAM,IAAS,KAAK,MAAM,IAAU,GAAG;AAEvC,QADI,IAAS,KAAW,GAAG,EAAO,KAC3B,IAAI,KAAK,EAAW,CAAC,mBAAmB,KAAA,GAAW;EACxD,OAAO;EACP,KAAK;EACN,CAAC;;AAGJ,SAAgB,EAAe,EAAE,kBAAe,cAAW,eAAyB;CAClF,IAAM,IAAW,GAAe,kBAAkB,EAAE;AAEpD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,yBAAyB;aAJnD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAS,WAAW,IACnB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAU,WAAU,2CAA4C,CAAA,EAChE,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAAsB,CAAA,CAC7D;OAEN,kBAAC,MAAD;GAAI,WAAU;aACX,EAAS,MAAM,GAAG,EAAE,CAAC,KAAK,MACzB,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAS,0BAA0B,EAAE,KAAK;IACzD,WAAU;cAHZ,CAKE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAE,QAAQ,WAAW,EAAE,GAAG,MAAM,GAAG,EAAE;MACpC,CAAA,EACH,EAAE,OAAO,OACR,kBAAC,KAAD;MAAG,WAAU;gBAA4C,EAAE,MAAM;MAAS,CAAA,GACxE,KACA;QACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,SAAQ;MACR,WAAW,eAAe,EAAa,EAAE,WAAW;gBAEnD,EAAE,OAAO,aAAa;MACjB,CAAA,EACP,EAAE,YACD,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAe,EAAE,UAAU;MACvB,CAAA,GACL,KACA;OACC;OACN,EA5BI,EAAE,GA4BN,CACL;GACC,CAAA;EAEO,CAAA"}
1
+ {"version":3,"file":"SessionsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/SessionsWidget.tsx"],"sourcesContent":["import { Terminal, ArrowRight } from 'lucide-react';\nimport { Badge, Button, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst STATUS_BADGE: Record<string, string> = {\n RUNNING: 'bg-status-success-bg text-status-success-text',\n ACTIVE: 'bg-status-success-bg text-status-success-text',\n STARTING: 'bg-status-warning-bg text-status-warning-text',\n STOPPED: 'bg-text-tertiary/20 text-text-tertiary',\n ERROR: 'bg-status-error-bg text-status-error-text',\n};\n\n// Live statuses get a subtle opacity pulse (reduced-motion-safe, no movement).\nconst LIVE_STATUSES = new Set(['RUNNING', 'ACTIVE']);\n\nfunction formatRelative(dateString: string | null | undefined): string {\n if (!dateString) return '';\n const diffMs = Date.now() - new Date(dateString).getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return `${diffMin}m`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return `${diffHr}h`;\n return new Date(dateString).toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n });\n}\n\nexport function SessionsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const sessions = workspaceData?.activeSessions ?? [];\n\n return (\n <WidgetWrapper\n title=\"Active Sessions\"\n icon={<Terminal className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/vibecontrols/sessions')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {sessions.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-sessions\"\n title=\"No active sessions\"\n className=\"py-6\"\n />\n ) : (\n <ul className=\"space-y-1.5\">\n {sessions.slice(0, 5).map((s) => (\n <li key={s.id}>\n <button\n type=\"button\"\n onClick={() => navigate(`/vibecontrols/sessions/${s.id}`)}\n className=\"flex w-full items-center justify-between gap-2 rounded-md p-2 text-left transition-colors hover:bg-accent/5\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {s.name || `Session ${s.id.slice(0, 8)}`}\n </p>\n {s.agent?.name ? (\n <p className=\"truncate text-[11px] text-text-secondary\">{s.agent.name}</p>\n ) : null}\n </div>\n <div className=\"flex flex-col items-end gap-1\">\n <Badge\n variant=\"outline\"\n className={`text-[10px] ${STATUS_BADGE[s.status] ?? ''} ${\n LIVE_STATUSES.has(s.status) ? 'motion-safe:animate-vc-glow-pulse' : ''\n }`}\n >\n {s.status.toLowerCase()}\n </Badge>\n {s.startedAt ? (\n <span className=\"text-[10px] text-text-secondary\">\n {formatRelative(s.startedAt)}\n </span>\n ) : null}\n </div>\n </button>\n </li>\n ))}\n </ul>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAuC;CAC3C,SAAS;CACT,QAAQ;CACR,UAAU;CACV,SAAS;CACT,OAAO;CACR,EAGK,IAAgB,IAAI,IAAI,CAAC,WAAW,SAAS,CAAC;AAEpD,SAAS,EAAe,GAA+C;AACrE,KAAI,CAAC,EAAY,QAAO;CACxB,IAAM,IAAS,KAAK,KAAK,GAAG,IAAI,KAAK,EAAW,CAAC,SAAS,EACpD,IAAU,KAAK,MAAM,IAAS,IAAM;AAC1C,KAAI,IAAU,EAAG,QAAO;AACxB,KAAI,IAAU,GAAI,QAAO,GAAG,EAAQ;CACpC,IAAM,IAAS,KAAK,MAAM,IAAU,GAAG;AAEvC,QADI,IAAS,KAAW,GAAG,EAAO,KAC3B,IAAI,KAAK,EAAW,CAAC,mBAAmB,KAAA,GAAW;EACxD,OAAO;EACP,KAAK;EACN,CAAC;;AAGJ,SAAgB,EAAe,EAAE,kBAAe,cAAW,eAAyB;CAClF,IAAM,IAAW,GAAe,kBAAkB,EAAE;AAEpD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,yBAAyB;aAJnD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAS,WAAW,IACnB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,WAAU;GACV,CAAA,GAEF,kBAAC,MAAD;GAAI,WAAU;aACX,EAAS,MAAM,GAAG,EAAE,CAAC,KAAK,MACzB,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAS,0BAA0B,EAAE,KAAK;IACzD,WAAU;cAHZ,CAKE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAE,QAAQ,WAAW,EAAE,GAAG,MAAM,GAAG,EAAE;MACpC,CAAA,EACH,EAAE,OAAO,OACR,kBAAC,KAAD;MAAG,WAAU;gBAA4C,EAAE,MAAM;MAAS,CAAA,GACxE,KACA;QACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,SAAQ;MACR,WAAW,eAAe,EAAa,EAAE,WAAW,GAAG,GACrD,EAAc,IAAI,EAAE,OAAO,GAAG,sCAAsC;gBAGrE,EAAE,OAAO,aAAa;MACjB,CAAA,EACP,EAAE,YACD,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAe,EAAE,UAAU;MACvB,CAAA,GACL,KACA;OACC;OACN,EA9BI,EAAE,GA8BN,CACL;GACC,CAAA;EAEO,CAAA"}
@@ -1,9 +1,9 @@
1
1
  import { WidgetWrapper as e } from "../WidgetWrapper.js";
2
2
  import { ArrowRight as t, Calendar as n, Clock as r } from "lucide-react";
3
3
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { Badge as o, Button as s } from "@burdenoff/fe-libs/ui";
4
+ import { Badge as o, Button as s, IllustratedEmptyState as c } from "@burdenoff/fe-libs/ui";
5
5
  //#region src/pages/dashboard/widgets/UpcomingEventsWidget.tsx
6
- function c(e) {
6
+ function l(e) {
7
7
  let t = new Date(e), n = /* @__PURE__ */ new Date(), r = t.toDateString() === n.toDateString(), i = new Date(n);
8
8
  i.setDate(i.getDate() + 1);
9
9
  let a = t.toDateString() === i.toDateString();
@@ -20,39 +20,37 @@ function c(e) {
20
20
  minute: "2-digit"
21
21
  });
22
22
  }
23
- function l({ workspaceData: l, isLoading: u, navigate: d }) {
24
- let f = l?.upcomingEvents ?? [];
23
+ function u({ workspaceData: u, isLoading: d, navigate: f }) {
24
+ let p = u?.upcomingEvents ?? [];
25
25
  return /* @__PURE__ */ i(e, {
26
26
  title: "Upcoming Events",
27
27
  icon: /* @__PURE__ */ i(n, { className: "size-4" }),
28
28
  size: "medium",
29
- isLoading: u,
30
- unavailable: !l,
29
+ isLoading: d,
30
+ unavailable: !u,
31
31
  headerAction: /* @__PURE__ */ a(s, {
32
32
  variant: "ghost",
33
33
  size: "sm",
34
34
  className: "text-xs",
35
- onClick: () => d("/calendar"),
35
+ onClick: () => f("/calendar"),
36
36
  children: ["View all ", /* @__PURE__ */ i(t, { className: "ml-1 size-3" })]
37
37
  }),
38
- children: f.length === 0 ? /* @__PURE__ */ a("div", {
39
- className: "text-center py-4",
40
- children: [/* @__PURE__ */ i("p", {
41
- className: "text-sm text-text-secondary",
42
- children: "No upcoming events"
43
- }), /* @__PURE__ */ i(s, {
38
+ children: p.length === 0 ? /* @__PURE__ */ i(c, {
39
+ illustration: "empty-data",
40
+ title: "No upcoming events",
41
+ className: "py-4",
42
+ action: /* @__PURE__ */ i(s, {
44
43
  variant: "outline",
45
44
  size: "sm",
46
- className: "mt-2",
47
- onClick: () => d("/calendar"),
45
+ onClick: () => f("/calendar"),
48
46
  children: "Schedule an event"
49
- })]
47
+ })
50
48
  }) : /* @__PURE__ */ i("div", {
51
49
  className: "space-y-2",
52
- children: f.map((e) => /* @__PURE__ */ a("button", {
50
+ children: p.map((e) => /* @__PURE__ */ a("button", {
53
51
  type: "button",
54
52
  className: "w-full flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left",
55
- onClick: () => d("/calendar"),
53
+ onClick: () => f("/calendar"),
56
54
  children: [
57
55
  /* @__PURE__ */ i("div", {
58
56
  className: "rounded-md bg-accent-pink-subtle text-accent-pink p-1.5 shrink-0",
@@ -65,7 +63,7 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
65
63
  children: e.title
66
64
  }), /* @__PURE__ */ i("p", {
67
65
  className: "text-xs text-text-secondary",
68
- children: c(e.startTime)
66
+ children: l(e.startTime)
69
67
  })]
70
68
  }),
71
69
  e.allDay && /* @__PURE__ */ i(o, {
@@ -79,6 +77,6 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
79
77
  });
80
78
  }
81
79
  //#endregion
82
- export { l as UpcomingEventsWidget };
80
+ export { u as UpcomingEventsWidget };
83
81
 
84
82
  //# sourceMappingURL=UpcomingEventsWidget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UpcomingEventsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/UpcomingEventsWidget.tsx"],"sourcesContent":["import { Calendar, ArrowRight, Clock } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nfunction formatEventDate(dateStr: string): string {\n const d = new Date(dateStr);\n const now = new Date();\n const isToday = d.toDateString() === now.toDateString();\n const tomorrow = new Date(now);\n tomorrow.setDate(tomorrow.getDate() + 1);\n const isTomorrow = d.toDateString() === tomorrow.toDateString();\n\n if (isToday)\n return `Today at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n if (isTomorrow)\n return `Tomorrow at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n return d.toLocaleDateString([], {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function UpcomingEventsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const events = workspaceData?.upcomingEvents ?? [];\n\n return (\n <WidgetWrapper\n title=\"Upcoming Events\"\n icon={<Calendar className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button variant=\"ghost\" size=\"sm\" className=\"text-xs\" onClick={() => navigate('/calendar')}>\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {events.length === 0 ? (\n <div className=\"text-center py-4\">\n <p className=\"text-sm text-text-secondary\">No upcoming events</p>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"mt-2\"\n onClick={() => navigate('/calendar')}\n >\n Schedule an event\n </Button>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {events.map((event) => (\n <button\n key={event.id}\n type=\"button\"\n className=\"w-full flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left\"\n onClick={() => navigate('/calendar')}\n >\n <div className=\"rounded-md bg-accent-pink-subtle text-accent-pink p-1.5 shrink-0\">\n <Clock className=\"size-3.5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary truncate\">{event.title}</p>\n <p className=\"text-xs text-text-secondary\">{formatEventDate(event.startTime)}</p>\n </div>\n {event.allDay && (\n <Badge variant=\"secondary\" className=\"text-[10px] shrink-0\">\n All day\n </Badge>\n )}\n </button>\n ))}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAS,EAAgB,GAAyB;CAChD,IAAM,IAAI,IAAI,KAAK,EAAQ,EACrB,oBAAM,IAAI,MAAM,EAChB,IAAU,EAAE,cAAc,KAAK,EAAI,cAAc,EACjD,IAAW,IAAI,KAAK,EAAI;AAC9B,GAAS,QAAQ,EAAS,SAAS,GAAG,EAAE;CACxC,IAAM,IAAa,EAAE,cAAc,KAAK,EAAS,cAAc;AAM/D,QAJI,IACK,YAAY,EAAE,mBAAmB,EAAE,EAAE;EAAE,MAAM;EAAW,QAAQ;EAAW,CAAC,KACjF,IACK,eAAe,EAAE,mBAAmB,EAAE,EAAE;EAAE,MAAM;EAAW,QAAQ;EAAW,CAAC,KACjF,EAAE,mBAAmB,EAAE,EAAE;EAC9B,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT,CAAC;;AAGJ,SAAgB,EAAqB,EAAE,kBAAe,cAAW,eAAyB;CACxF,IAAM,IAAS,GAAe,kBAAkB,EAAE;AAElD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GAAQ,SAAQ;GAAQ,MAAK;GAAK,WAAU;GAAU,eAAe,EAAS,YAAY;aAA1F,CAA4F,aACjF,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAO,WAAW,IACjB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAAsB,CAAA,EACjE,kBAAC,GAAD;IACE,SAAQ;IACR,MAAK;IACL,WAAU;IACV,eAAe,EAAS,YAAY;cACrC;IAEQ,CAAA,CACL;OAEN,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAO,KAAK,MACX,kBAAC,UAAD;IAEE,MAAK;IACL,WAAU;IACV,eAAe,EAAS,YAAY;cAJtC;KAME,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAO,WAAU,YAAa,CAAA;MAC1B,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAkD,EAAM;OAAU,CAAA,EAC/E,kBAAC,KAAD;OAAG,WAAU;iBAA+B,EAAgB,EAAM,UAAU;OAAK,CAAA,CAC7E;;KACL,EAAM,UACL,kBAAC,GAAD;MAAO,SAAQ;MAAY,WAAU;gBAAuB;MAEpD,CAAA;KAEH;MAjBF,EAAM,GAiBJ,CACT;GACE,CAAA;EAEM,CAAA"}
1
+ {"version":3,"file":"UpcomingEventsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/UpcomingEventsWidget.tsx"],"sourcesContent":["import { Calendar, ArrowRight, Clock } from 'lucide-react';\nimport { Badge, Button, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nfunction formatEventDate(dateStr: string): string {\n const d = new Date(dateStr);\n const now = new Date();\n const isToday = d.toDateString() === now.toDateString();\n const tomorrow = new Date(now);\n tomorrow.setDate(tomorrow.getDate() + 1);\n const isTomorrow = d.toDateString() === tomorrow.toDateString();\n\n if (isToday)\n return `Today at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n if (isTomorrow)\n return `Tomorrow at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n return d.toLocaleDateString([], {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function UpcomingEventsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const events = workspaceData?.upcomingEvents ?? [];\n\n return (\n <WidgetWrapper\n title=\"Upcoming Events\"\n icon={<Calendar className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button variant=\"ghost\" size=\"sm\" className=\"text-xs\" onClick={() => navigate('/calendar')}>\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {events.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No upcoming events\"\n className=\"py-4\"\n action={\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/calendar')}>\n Schedule an event\n </Button>\n }\n />\n ) : (\n <div className=\"space-y-2\">\n {events.map((event) => (\n <button\n key={event.id}\n type=\"button\"\n className=\"w-full flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left\"\n onClick={() => navigate('/calendar')}\n >\n <div className=\"rounded-md bg-accent-pink-subtle text-accent-pink p-1.5 shrink-0\">\n <Clock className=\"size-3.5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary truncate\">{event.title}</p>\n <p className=\"text-xs text-text-secondary\">{formatEventDate(event.startTime)}</p>\n </div>\n {event.allDay && (\n <Badge variant=\"secondary\" className=\"text-[10px] shrink-0\">\n All day\n </Badge>\n )}\n </button>\n ))}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAS,EAAgB,GAAyB;CAChD,IAAM,IAAI,IAAI,KAAK,EAAQ,EACrB,oBAAM,IAAI,MAAM,EAChB,IAAU,EAAE,cAAc,KAAK,EAAI,cAAc,EACjD,IAAW,IAAI,KAAK,EAAI;AAC9B,GAAS,QAAQ,EAAS,SAAS,GAAG,EAAE;CACxC,IAAM,IAAa,EAAE,cAAc,KAAK,EAAS,cAAc;AAM/D,QAJI,IACK,YAAY,EAAE,mBAAmB,EAAE,EAAE;EAAE,MAAM;EAAW,QAAQ;EAAW,CAAC,KACjF,IACK,eAAe,EAAE,mBAAmB,EAAE,EAAE;EAAE,MAAM;EAAW,QAAQ;EAAW,CAAC,KACjF,EAAE,mBAAmB,EAAE,EAAE;EAC9B,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT,CAAC;;AAGJ,SAAgB,EAAqB,EAAE,kBAAe,cAAW,eAAyB;CACxF,IAAM,IAAS,GAAe,kBAAkB,EAAE;AAElD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GAAQ,SAAQ;GAAQ,MAAK;GAAK,WAAU;GAAU,eAAe,EAAS,YAAY;aAA1F,CAA4F,aACjF,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAO,WAAW,IACjB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,WAAU;GACV,QACE,kBAAC,GAAD;IAAQ,SAAQ;IAAU,MAAK;IAAK,eAAe,EAAS,YAAY;cAAE;IAEjE,CAAA;GAEX,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAO,KAAK,MACX,kBAAC,UAAD;IAEE,MAAK;IACL,WAAU;IACV,eAAe,EAAS,YAAY;cAJtC;KAME,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAO,WAAU,YAAa,CAAA;MAC1B,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAkD,EAAM;OAAU,CAAA,EAC/E,kBAAC,KAAD;OAAG,WAAU;iBAA+B,EAAgB,EAAM,UAAU;OAAK,CAAA,CAC7E;;KACL,EAAM,UACL,kBAAC,GAAD;MAAO,SAAQ;MAAY,WAAU;gBAAuB;MAEpD,CAAA;KAEH;MAjBF,EAAM,GAiBJ,CACT;GACE,CAAA;EAEM,CAAA"}