@burdenoff/microfe-workspaces 2026.519.1 → 2026.528.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 (234) hide show
  1. package/dist/WorkspacesRoot.js +4 -1
  2. package/dist/WorkspacesRoot.js.map +1 -1
  3. package/dist/WorkspacesRoutes.js +4 -4
  4. package/dist/WorkspacesRoutes.js.map +1 -1
  5. package/dist/components/CreateProjectDialog.js +1 -1
  6. package/dist/components/CreateProjectDialog.js.map +1 -1
  7. package/dist/components/CreateWorkspaceDialog.js +2 -2
  8. package/dist/components/CreateWorkspaceDialog.js.map +1 -1
  9. package/dist/components/InviteMemberDialog.js +2 -2
  10. package/dist/components/InviteMemberDialog.js.map +1 -1
  11. package/dist/components/MemberListItem.js +71 -86
  12. package/dist/components/MemberListItem.js.map +1 -1
  13. package/dist/components/ProjectCard.js +12 -10
  14. package/dist/components/ProjectCard.js.map +1 -1
  15. package/dist/components/WorkspaceCard.js.map +1 -1
  16. package/dist/components/WorkspacesErrorBoundary.js +12 -4
  17. package/dist/components/WorkspacesErrorBoundary.js.map +1 -1
  18. package/dist/components/tags/ProjectTagsWidget.js +248 -0
  19. package/dist/components/tags/ProjectTagsWidget.js.map +1 -0
  20. package/dist/generated/global-operations.js +9 -1
  21. package/dist/generated/global-operations.js.map +1 -1
  22. package/dist/hooks/useOrgsWithPermission.js +55 -0
  23. package/dist/hooks/useOrgsWithPermission.js.map +1 -0
  24. package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
  25. package/dist/hooks/useWorkspacesPageView.js +6 -4
  26. package/dist/hooks/useWorkspacesPageView.js.map +1 -1
  27. package/dist/pages/CreateWorkspacePage.js +173 -149
  28. package/dist/pages/CreateWorkspacePage.js.map +1 -1
  29. package/dist/pages/InviteAcceptancePage.js +28 -28
  30. package/dist/pages/InviteAcceptancePage.js.map +1 -1
  31. package/dist/pages/MembersListPage.js +380 -352
  32. package/dist/pages/MembersListPage.js.map +1 -1
  33. package/dist/pages/ProjectDetailPage.js +96 -97
  34. package/dist/pages/ProjectDetailPage.js.map +1 -1
  35. package/dist/pages/ProjectsListPage.js +307 -304
  36. package/dist/pages/ProjectsListPage.js.map +1 -1
  37. package/dist/pages/WorkspaceSettingsPage.js +94 -91
  38. package/dist/pages/WorkspaceSettingsPage.js.map +1 -1
  39. package/dist/pages/WorkspacesListPage.js +1 -1
  40. package/dist/pages/WorkspacesListPage.js.map +1 -1
  41. package/dist/pages/dashboard/DashboardCustomizer.js +68 -68
  42. package/dist/pages/dashboard/DashboardCustomizer.js.map +1 -1
  43. package/dist/pages/dashboard/DashboardGrid.js +52 -41
  44. package/dist/pages/dashboard/DashboardGrid.js.map +1 -1
  45. package/dist/pages/dashboard/DashboardPage.js +74 -65
  46. package/dist/pages/dashboard/DashboardPage.js.map +1 -1
  47. package/dist/pages/dashboard/WidgetWrapper.js +3 -3
  48. package/dist/pages/dashboard/WidgetWrapper.js.map +1 -1
  49. package/dist/pages/dashboard/config.js +126 -30
  50. package/dist/pages/dashboard/config.js.map +1 -1
  51. package/dist/pages/dashboard/hooks/useDashboardData.js +39 -2
  52. package/dist/pages/dashboard/hooks/useDashboardData.js.map +1 -1
  53. package/dist/pages/dashboard/widgets/AgentsWidget.js +109 -0
  54. package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -0
  55. package/dist/pages/dashboard/widgets/GroupsWidget.js +6 -5
  56. package/dist/pages/dashboard/widgets/GroupsWidget.js.map +1 -1
  57. package/dist/pages/dashboard/widgets/MembersWidget.js +6 -6
  58. package/dist/pages/dashboard/widgets/MembersWidget.js.map +1 -1
  59. package/dist/pages/dashboard/widgets/ProjectsWidget.js +8 -7
  60. package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
  61. package/dist/pages/dashboard/widgets/QuickActionsWidget.js +72 -18
  62. package/dist/pages/dashboard/widgets/QuickActionsWidget.js.map +1 -1
  63. package/dist/pages/dashboard/widgets/RecentActivityWidget.js +3 -3
  64. package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
  65. package/dist/pages/dashboard/widgets/SessionsWidget.js +78 -0
  66. package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -0
  67. package/dist/pages/dashboard/widgets/StorageWidget.js +35 -20
  68. package/dist/pages/dashboard/widgets/StorageWidget.js.map +1 -1
  69. package/dist/pages/dashboard/widgets/TagCloudWidget.js +2 -2
  70. package/dist/pages/dashboard/widgets/TagCloudWidget.js.map +1 -1
  71. package/dist/pages/dashboard/widgets/TipsWidget.js +81 -22
  72. package/dist/pages/dashboard/widgets/TipsWidget.js.map +1 -1
  73. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +6 -5
  74. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
  75. package/dist/pages/dashboard/widgets/VibesWidget.js +64 -0
  76. package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -0
  77. package/dist/pages/dashboard/widgets/WelcomeWidget.js +5 -5
  78. package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
  79. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js +3 -3
  80. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
  81. package/dist/pages/dashboard/widgets/WorkspacesWidget.js +6 -5
  82. package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
  83. package/dist/providers/WorkspacesProvider.js +1 -1
  84. package/dist/providers/WorkspacesProvider.js.map +1 -1
  85. package/dist/store/workspacesStore.js.map +1 -1
  86. package/dist/utils/formatters.js +21 -16
  87. package/dist/utils/formatters.js.map +1 -1
  88. package/dist/utils/telemetryError.js +1 -1
  89. package/dist/utils/telemetryError.js.map +1 -1
  90. package/package.json +7 -7
  91. package/dist/WorkspacesRoot.d.ts +0 -35
  92. package/dist/WorkspacesRoot.d.ts.map +0 -1
  93. package/dist/WorkspacesRoutes.d.ts +0 -10
  94. package/dist/WorkspacesRoutes.d.ts.map +0 -1
  95. package/dist/components/CreateProjectDialog.d.ts +0 -6
  96. package/dist/components/CreateProjectDialog.d.ts.map +0 -1
  97. package/dist/components/CreateWorkspaceDialog.d.ts +0 -2
  98. package/dist/components/CreateWorkspaceDialog.d.ts.map +0 -1
  99. package/dist/components/InviteMemberDialog.d.ts +0 -7
  100. package/dist/components/InviteMemberDialog.d.ts.map +0 -1
  101. package/dist/components/MemberListItem.d.ts +0 -11
  102. package/dist/components/MemberListItem.d.ts.map +0 -1
  103. package/dist/components/ProjectCard.d.ts +0 -13
  104. package/dist/components/ProjectCard.d.ts.map +0 -1
  105. package/dist/components/WorkspaceCard.d.ts +0 -8
  106. package/dist/components/WorkspaceCard.d.ts.map +0 -1
  107. package/dist/components/WorkspacesErrorBoundary.d.ts +0 -27
  108. package/dist/components/WorkspacesErrorBoundary.d.ts.map +0 -1
  109. package/dist/components/index.d.ts +0 -8
  110. package/dist/components/index.d.ts.map +0 -1
  111. package/dist/constants/permissions.d.ts +0 -33
  112. package/dist/constants/permissions.d.ts.map +0 -1
  113. package/dist/generated/global-operations.d.ts +0 -279
  114. package/dist/generated/global-operations.d.ts.map +0 -1
  115. package/dist/generated/global-types.d.ts +0 -23527
  116. package/dist/generated/global-types.d.ts.map +0 -1
  117. package/dist/generated/wspace-operations.d.ts +0 -2300
  118. package/dist/generated/wspace-operations.d.ts.map +0 -1
  119. package/dist/generated/wspace-types.d.ts +0 -57851
  120. package/dist/generated/wspace-types.d.ts.map +0 -1
  121. package/dist/hooks/index.d.ts +0 -8
  122. package/dist/hooks/index.d.ts.map +0 -1
  123. package/dist/hooks/useMemberMutations.d.ts +0 -61
  124. package/dist/hooks/useMemberMutations.d.ts.map +0 -1
  125. package/dist/hooks/useProjectMutations.d.ts +0 -26
  126. package/dist/hooks/useProjectMutations.d.ts.map +0 -1
  127. package/dist/hooks/useProjects.d.ts +0 -16
  128. package/dist/hooks/useProjects.d.ts.map +0 -1
  129. package/dist/hooks/useScopedNavigation.d.ts +0 -4
  130. package/dist/hooks/useScopedNavigation.d.ts.map +0 -1
  131. package/dist/hooks/useTenants.d.ts +0 -13
  132. package/dist/hooks/useTenants.d.ts.map +0 -1
  133. package/dist/hooks/useWorkspaceActivity.d.ts +0 -12
  134. package/dist/hooks/useWorkspaceActivity.d.ts.map +0 -1
  135. package/dist/hooks/useWorkspaceMembers.d.ts +0 -24
  136. package/dist/hooks/useWorkspaceMembers.d.ts.map +0 -1
  137. package/dist/hooks/useWorkspaceMutations.d.ts +0 -36
  138. package/dist/hooks/useWorkspaceMutations.d.ts.map +0 -1
  139. package/dist/hooks/useWorkspacePermissions.d.ts +0 -29
  140. package/dist/hooks/useWorkspacePermissions.d.ts.map +0 -1
  141. package/dist/hooks/useWorkspaceRoles.d.ts +0 -8
  142. package/dist/hooks/useWorkspaceRoles.d.ts.map +0 -1
  143. package/dist/hooks/useWorkspaces.d.ts +0 -21
  144. package/dist/hooks/useWorkspaces.d.ts.map +0 -1
  145. package/dist/hooks/useWorkspacesEventEmitter.d.ts +0 -18
  146. package/dist/hooks/useWorkspacesEventEmitter.d.ts.map +0 -1
  147. package/dist/hooks/useWorkspacesPageView.d.ts +0 -27
  148. package/dist/hooks/useWorkspacesPageView.d.ts.map +0 -1
  149. package/dist/index.d.ts +0 -33
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/pages/ActivityListPage.d.ts +0 -2
  152. package/dist/pages/ActivityListPage.d.ts.map +0 -1
  153. package/dist/pages/CreateWorkspacePage.d.ts +0 -2
  154. package/dist/pages/CreateWorkspacePage.d.ts.map +0 -1
  155. package/dist/pages/InviteAcceptancePage.d.ts +0 -6
  156. package/dist/pages/InviteAcceptancePage.d.ts.map +0 -1
  157. package/dist/pages/MembersListPage.d.ts +0 -2
  158. package/dist/pages/MembersListPage.d.ts.map +0 -1
  159. package/dist/pages/ProjectDetailPage.d.ts +0 -2
  160. package/dist/pages/ProjectDetailPage.d.ts.map +0 -1
  161. package/dist/pages/ProjectsListPage.d.ts +0 -2
  162. package/dist/pages/ProjectsListPage.d.ts.map +0 -1
  163. package/dist/pages/WorkspaceDetailPage.d.ts +0 -2
  164. package/dist/pages/WorkspaceDetailPage.d.ts.map +0 -1
  165. package/dist/pages/WorkspaceSettingsPage.d.ts +0 -2
  166. package/dist/pages/WorkspaceSettingsPage.d.ts.map +0 -1
  167. package/dist/pages/WorkspacesListPage.d.ts +0 -2
  168. package/dist/pages/WorkspacesListPage.d.ts.map +0 -1
  169. package/dist/pages/dashboard/DashboardCustomizer.d.ts +0 -12
  170. package/dist/pages/dashboard/DashboardCustomizer.d.ts.map +0 -1
  171. package/dist/pages/dashboard/DashboardGrid.d.ts +0 -8
  172. package/dist/pages/dashboard/DashboardGrid.d.ts.map +0 -1
  173. package/dist/pages/dashboard/DashboardPage.d.ts +0 -14
  174. package/dist/pages/dashboard/DashboardPage.d.ts.map +0 -1
  175. package/dist/pages/dashboard/WidgetWrapper.d.ts +0 -17
  176. package/dist/pages/dashboard/WidgetWrapper.d.ts.map +0 -1
  177. package/dist/pages/dashboard/config.d.ts +0 -9
  178. package/dist/pages/dashboard/config.d.ts.map +0 -1
  179. package/dist/pages/dashboard/hooks/useDashboardData.d.ts +0 -9
  180. package/dist/pages/dashboard/hooks/useDashboardData.d.ts.map +0 -1
  181. package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts +0 -4
  182. package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts.map +0 -1
  183. package/dist/pages/dashboard/types.d.ts +0 -145
  184. package/dist/pages/dashboard/types.d.ts.map +0 -1
  185. package/dist/pages/dashboard/widgets/GroupsWidget.d.ts +0 -4
  186. package/dist/pages/dashboard/widgets/GroupsWidget.d.ts.map +0 -1
  187. package/dist/pages/dashboard/widgets/MembersWidget.d.ts +0 -4
  188. package/dist/pages/dashboard/widgets/MembersWidget.d.ts.map +0 -1
  189. package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts +0 -4
  190. package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts.map +0 -1
  191. package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts +0 -4
  192. package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts.map +0 -1
  193. package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts +0 -4
  194. package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts.map +0 -1
  195. package/dist/pages/dashboard/widgets/StorageWidget.d.ts +0 -4
  196. package/dist/pages/dashboard/widgets/StorageWidget.d.ts.map +0 -1
  197. package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts +0 -4
  198. package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts.map +0 -1
  199. package/dist/pages/dashboard/widgets/SystemHealthWidget.js +0 -59
  200. package/dist/pages/dashboard/widgets/SystemHealthWidget.js.map +0 -1
  201. package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts +0 -4
  202. package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts.map +0 -1
  203. package/dist/pages/dashboard/widgets/TipsWidget.d.ts +0 -4
  204. package/dist/pages/dashboard/widgets/TipsWidget.d.ts.map +0 -1
  205. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts +0 -4
  206. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts.map +0 -1
  207. package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts +0 -4
  208. package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts.map +0 -1
  209. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts +0 -4
  210. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts.map +0 -1
  211. package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts +0 -4
  212. package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts.map +0 -1
  213. package/dist/providers/WorkspacesProvider.d.ts +0 -13
  214. package/dist/providers/WorkspacesProvider.d.ts.map +0 -1
  215. package/dist/store/workspacesStore.d.ts +0 -82
  216. package/dist/store/workspacesStore.d.ts.map +0 -1
  217. package/dist/types/index.d.ts +0 -280
  218. package/dist/types/index.d.ts.map +0 -1
  219. package/dist/utils/formatters.d.ts +0 -60
  220. package/dist/utils/formatters.d.ts.map +0 -1
  221. package/dist/utils/i18n.d.ts +0 -13
  222. package/dist/utils/i18n.d.ts.map +0 -1
  223. package/dist/utils/index.d.ts +0 -3
  224. package/dist/utils/index.d.ts.map +0 -1
  225. package/dist/utils/nativeBridge.d.ts +0 -3
  226. package/dist/utils/nativeBridge.d.ts.map +0 -1
  227. package/dist/utils/projectTags.d.ts +0 -6
  228. package/dist/utils/projectTags.d.ts.map +0 -1
  229. package/dist/utils/slug.d.ts +0 -13
  230. package/dist/utils/slug.d.ts.map +0 -1
  231. package/dist/utils/telemetryError.d.ts +0 -2
  232. package/dist/utils/telemetryError.d.ts.map +0 -1
  233. package/dist/utils/tokenHelpers.d.ts +0 -114
  234. package/dist/utils/tokenHelpers.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useDashboardData.js","names":[],"sources":["../../../../src/pages/dashboard/hooks/useDashboardData.ts"],"sourcesContent":["/**\n * Dashboard Data Hooks\n *\n * Three parallel queries: workspace gateway (features + projects), global gateway.\n * Uses graphqlFetch from fe-libs with React Query for caching.\n *\n * IMPORTANT: Workspace/org/member data lives in the global tenant service\n * (global gateway), NOT in the workspace service (workspace gateway).\n * The workspace gateway is used for workspace-scoped features like\n * activity, calendar, tags, groups, projects, and workflows.\n *\n * All GraphQL operations are defined in src/operations/ and generated via codegen.\n * Document nodes are imported and converted to strings via print() for graphqlFetch.\n */\nimport { useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useActiveContext } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n DashboardProjectsDocument,\n DashboardWorkspaceDataDocument,\n} from '../../../generated/wspace-operations';\nimport { DashboardGlobalDataDocument } from '../../../generated/global-operations';\nimport type { WorkspaceDashboardData, GlobalDashboardData } from '../types';\n\nconst BYTES_PER_GB = 1024 ** 3;\n\n// ─── Hooks ────────────────────────────────────────────────────────────────────\n\nexport function useProjectsDashboardData(authToken?: string | null) {\n const { workspaceId } = useActiveContext();\n\n return useQuery({\n queryKey: ['dashboard', 'projects', workspaceId],\n enabled: !!authToken && !!workspaceId,\n queryFn: async (): Promise<WorkspaceDashboardData['projects']> => {\n const result = await graphqlFetch<{\n projects: WorkspaceDashboardData['projects'];\n }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n workspaceToken: true,\n query: print(DashboardProjectsDocument),\n variables: { filter: { workspaceId } },\n });\n\n return result.data?.projects ?? { items: [], total: 0 };\n },\n staleTime: 2 * 60 * 1000,\n gcTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: true,\n });\n}\n\nexport function useWorkspaceDashboardData(authToken?: string | null) {\n const { workspaceId } = useActiveContext();\n\n return useQuery({\n queryKey: ['dashboard', 'workspace', workspaceId],\n enabled: !!authToken && !!workspaceId,\n queryFn: async (): Promise<WorkspaceDashboardData> => {\n const result = await graphqlFetch<{\n getRecentActivities: WorkspaceDashboardData['recentActivities'];\n upcomingEvents: WorkspaceDashboardData['upcomingEvents'];\n getTags: WorkspaceDashboardData['tags'];\n myGroups: {\n edges: Array<{ node: { id: string; name: string; description?: string } }>;\n totalCount: number;\n };\n dashboardSummary: WorkspaceDashboardData['workflowStats'];\n workspaceResourceUsage: { currentStorageGb: number } | null;\n workspaceResourceLimits: { maxStorageGb?: number | null } | null;\n }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n workspaceToken: true,\n query: print(DashboardWorkspaceDataDocument),\n });\n\n // Gracefully handle partial failures — the gateway may return data for some\n // subgraphs and errors for others due to individual services being down.\n const data = result.data;\n const storageUsage = data?.workspaceResourceUsage\n ? {\n usedBytes: Math.round(data.workspaceResourceUsage.currentStorageGb * BYTES_PER_GB),\n totalBytes: Math.round(\n (data.workspaceResourceLimits?.maxStorageGb ?? 0) * BYTES_PER_GB\n ),\n fileCount: null,\n }\n : null;\n\n return {\n // Workspace data comes from the global gateway (see useGlobalDashboardData)\n // and is merged in at the DashboardPage level.\n workspaces: { items: [], total: 0 },\n // Projects fetched separately via useProjectsDashboardData to avoid\n // being poisoned by other subgraph errors in the combined query.\n projects: { items: [], total: 0 },\n recentActivities: data?.getRecentActivities ?? [],\n upcomingEvents: data?.upcomingEvents ?? [],\n tags: data?.getTags ?? { items: [], total: 0 },\n groups: {\n items: (data?.myGroups?.edges ?? []).map((e) => ({\n id: e.node.id,\n name: e.node.name,\n description: e.node.description,\n })),\n totalCount: data?.myGroups?.totalCount ?? 0,\n },\n workflowStats: data?.dashboardSummary ?? null,\n storageUsage,\n };\n },\n staleTime: 2 * 60 * 1000, // 2 minutes — dashboard data changes moderately\n gcTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: true,\n });\n}\n\nexport function useGlobalDashboardData(authToken?: string | null) {\n return useQuery({\n queryKey: ['dashboard', 'global'],\n enabled: !!authToken,\n queryFn: async (): Promise<GlobalDashboardData> => {\n const result = await graphqlFetch<{\n currentUser: GlobalDashboardData['currentUser'];\n myDashboardPreferences: Record<string, unknown> | null;\n myWorkspaces: {\n items: Array<{\n id: string;\n name: string;\n status: string;\n type: string;\n createdAt: string;\n memberCount: number;\n }>;\n total: number;\n };\n myOrganizations: {\n items: Array<{\n id: string;\n name: string;\n status: string;\n type: string;\n createdAt: string;\n }>;\n total: number;\n };\n }>({\n gateway: 'global',\n authToken: authToken || undefined,\n query: print(DashboardGlobalDataDocument),\n });\n\n const data = result.data;\n\n return {\n currentUser: data?.currentUser ?? null,\n dashboardPreferences: data?.myDashboardPreferences\n ? (data.myDashboardPreferences as unknown as GlobalDashboardData['dashboardPreferences'])\n : null,\n workspaces: data?.myWorkspaces ?? { items: [], total: 0 },\n organizations: data?.myOrganizations ?? { items: [], total: 0 },\n };\n },\n staleTime: 5 * 60 * 1000, // 5 minutes — user info and prefs change rarely\n gcTime: 10 * 60 * 1000,\n retry: 1,\n });\n}\n"],"mappings":";;;;;;;AAyBA,IAAM,IAAe,QAAQ;AAI7B,SAAgB,EAAyB,GAA2B;CAClE,IAAM,EAAE,mBAAgB,GAAkB;AAE1C,QAAO,EAAS;EACd,UAAU;GAAC;GAAa;GAAY;GAAY;EAChD,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC;EAC1B,SAAS,aACQ,MAAM,EAElB;GACD,SAAS;GACT,WAAW,KAAa,KAAA;GACxB,gBAAgB;GAChB,OAAO,EAAM,EAA0B;GACvC,WAAW,EAAE,QAAQ,EAAE,gBAAa,EAAE;GACvC,CAAC,EAEY,MAAM,YAAY;GAAE,OAAO,EAAE;GAAE,OAAO;GAAG;EAEzD,WAAW,MAAS;EACpB,QAAQ,MAAS;EACjB,OAAO;EACP,sBAAsB;EACvB,CAAC;;AAGJ,SAAgB,EAA0B,GAA2B;CACnE,IAAM,EAAE,mBAAgB,GAAkB;AAE1C,QAAO,EAAS;EACd,UAAU;GAAC;GAAa;GAAa;GAAY;EACjD,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC;EAC1B,SAAS,YAA6C;GAqBpD,IAAM,KApBS,MAAM,EAWlB;IACD,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,gBAAgB;IAChB,OAAO,EAAM,EAA+B;IAC7C,CAAC,EAIkB,MACd,IAAe,GAAM,yBACvB;IACE,WAAW,KAAK,MAAM,EAAK,uBAAuB,mBAAmB,EAAa;IAClF,YAAY,KAAK,OACd,EAAK,yBAAyB,gBAAgB,KAAK,EACrD;IACD,WAAW;IACZ,GACD;AAEJ,UAAO;IAGL,YAAY;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAGnC,UAAU;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IACjC,kBAAkB,GAAM,uBAAuB,EAAE;IACjD,gBAAgB,GAAM,kBAAkB,EAAE;IAC1C,MAAM,GAAM,WAAW;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAC9C,QAAQ;KACN,QAAQ,GAAM,UAAU,SAAS,EAAE,EAAE,KAAK,OAAO;MAC/C,IAAI,EAAE,KAAK;MACX,MAAM,EAAE,KAAK;MACb,aAAa,EAAE,KAAK;MACrB,EAAE;KACH,YAAY,GAAM,UAAU,cAAc;KAC3C;IACD,eAAe,GAAM,oBAAoB;IACzC;IACD;;EAEH,WAAW,MAAS;EACpB,QAAQ,MAAS;EACjB,OAAO;EACP,sBAAsB;EACvB,CAAC;;AAGJ,SAAgB,EAAuB,GAA2B;AAChE,QAAO,EAAS;EACd,UAAU,CAAC,aAAa,SAAS;EACjC,SAAS,CAAC,CAAC;EACX,SAAS,YAA0C;GA+BjD,IAAM,KA9BS,MAAM,EAwBlB;IACD,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA4B;IAC1C,CAAC,EAEkB;AAEpB,UAAO;IACL,aAAa,GAAM,eAAe;IAClC,sBAAsB,GAAM,yBACvB,EAAK,yBACN;IACJ,YAAY,GAAM,gBAAgB;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IACzD,eAAe,GAAM,mBAAmB;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAChE;;EAEH,WAAW,MAAS;EACpB,QAAQ,MAAU;EAClB,OAAO;EACR,CAAC"}
1
+ {"version":3,"file":"useDashboardData.js","names":[],"sources":["../../../../src/pages/dashboard/hooks/useDashboardData.ts"],"sourcesContent":["/**\n * Dashboard Data Hooks\n *\n * Three parallel queries: workspace gateway (features + projects), global gateway.\n * Uses graphqlFetch from fe-libs with React Query for caching.\n *\n * IMPORTANT: Workspace/org/member data lives in the global tenant service\n * (global gateway), NOT in the workspace service (workspace gateway).\n * The workspace gateway is used for workspace-scoped features like\n * activity, calendar, tags, groups, projects, and workflows.\n *\n * All GraphQL operations are defined in src/operations/ and generated via codegen.\n * Document nodes are imported and converted to strings via print() for graphqlFetch.\n */\nimport { useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useActiveContext } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n DashboardProjectsDocument,\n DashboardWorkspaceDataDocument,\n} from '../../../generated/wspace-operations';\nimport { DashboardGlobalDataDocument } from '../../../generated/global-operations';\nimport type {\n WorkspaceDashboardData,\n GlobalDashboardData,\n VibeSummary,\n SessionSummary,\n AgentFleetSummary,\n} from '../types';\n\nconst BYTES_PER_GB = 1024 ** 3;\n\n// ─── Hooks ────────────────────────────────────────────────────────────────────\n\nexport function useProjectsDashboardData(authToken?: string | null) {\n const { workspaceId } = useActiveContext();\n\n return useQuery({\n queryKey: ['dashboard', 'projects', workspaceId],\n enabled: !!authToken && !!workspaceId,\n queryFn: async (): Promise<WorkspaceDashboardData['projects']> => {\n const result = await graphqlFetch<{\n projects: WorkspaceDashboardData['projects'];\n }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n workspaceToken: true,\n query: print(DashboardProjectsDocument),\n variables: { filter: { workspaceId } },\n });\n\n return result.data?.projects ?? { items: [], total: 0 };\n },\n staleTime: 2 * 60 * 1000,\n gcTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: true,\n });\n}\n\nexport function useWorkspaceDashboardData(authToken?: string | null) {\n const { workspaceId } = useActiveContext();\n\n return useQuery({\n queryKey: ['dashboard', 'workspace', workspaceId],\n enabled: !!authToken && !!workspaceId,\n queryFn: async (): Promise<WorkspaceDashboardData> => {\n const result = await graphqlFetch<{\n getRecentActivities: WorkspaceDashboardData['recentActivities'];\n upcomingEvents: WorkspaceDashboardData['upcomingEvents'];\n getTags: WorkspaceDashboardData['tags'];\n myGroups: {\n edges: Array<{ node: { id: string; name: string; description?: string } }>;\n totalCount: number;\n };\n dashboardSummary: WorkspaceDashboardData['workflowStats'];\n workspaceResourceUsage: { currentStorageGb: number } | null;\n workspaceResourceLimits: { maxStorageGb?: number | null } | null;\n }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n workspaceToken: true,\n query: print(DashboardWorkspaceDataDocument),\n });\n\n // Gracefully handle partial failures — the gateway may return data for some\n // subgraphs and errors for others due to individual services being down.\n const data = result.data;\n const storageUsage = data?.workspaceResourceUsage\n ? {\n usedBytes: Math.round(data.workspaceResourceUsage.currentStorageGb * BYTES_PER_GB),\n totalBytes: Math.round(\n (data.workspaceResourceLimits?.maxStorageGb ?? 0) * BYTES_PER_GB\n ),\n fileCount: null,\n }\n : null;\n\n return {\n // Workspace data comes from the global gateway (see useGlobalDashboardData)\n // and is merged in at the DashboardPage level.\n workspaces: { items: [], total: 0 },\n // Projects fetched separately via useProjectsDashboardData to avoid\n // being poisoned by other subgraph errors in the combined query.\n projects: { items: [], total: 0 },\n recentActivities: data?.getRecentActivities ?? [],\n upcomingEvents: data?.upcomingEvents ?? [],\n tags: data?.getTags ?? { items: [], total: 0 },\n groups: {\n items: (data?.myGroups?.edges ?? []).map((e) => ({\n id: e.node.id,\n name: e.node.name,\n description: e.node.description,\n })),\n totalCount: data?.myGroups?.totalCount ?? 0,\n },\n workflowStats: data?.dashboardSummary ?? null,\n storageUsage,\n };\n },\n staleTime: 2 * 60 * 1000, // 2 minutes — dashboard data changes moderately\n gcTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: true,\n });\n}\n\n// ─── VibeControls-specific dashboard data ────────────────────────────────────\n// Issued as raw GraphQL strings to avoid coupling to codegen for the new\n// `recentVibes` + `agentFleetSummary` queries (added in wspace-vibecontrols-svc).\n// Falls back to empty state if any field is missing in the deployed schema,\n// so the dashboard degrades gracefully during schema rollout.\n\nconst VIBECONTROLS_DASHBOARD_QUERY = `\n query VibeControlsDashboardData {\n recentVibes(limit: 5) {\n id\n name\n status\n workspaceId\n updatedAt\n }\n activeSessions(pagination: { limit: 5 }) {\n items {\n id\n name\n status\n agentName\n startedAt\n vibeId\n }\n }\n agentFleetSummary {\n total\n online\n offline\n degraded\n lastSeenAt\n }\n }\n`;\n\ninterface VibecontrolsDashboardResponse {\n recentVibes?: VibeSummary[] | null;\n activeSessions?: { items?: SessionSummary[] | null } | null;\n agentFleetSummary?: AgentFleetSummary | null;\n}\n\nexport interface VibecontrolsDashboardData {\n recentVibes: VibeSummary[];\n activeSessions: SessionSummary[];\n agentFleet: AgentFleetSummary | null;\n}\n\nexport function useVibecontrolsDashboardData(authToken?: string | null, enabled = false) {\n const { workspaceId } = useActiveContext();\n\n return useQuery({\n queryKey: ['dashboard', 'vibecontrols', workspaceId],\n enabled: !!authToken && !!workspaceId && enabled,\n queryFn: async (): Promise<VibecontrolsDashboardData> => {\n try {\n const result = await graphqlFetch<VibecontrolsDashboardResponse>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n workspaceToken: true,\n query: VIBECONTROLS_DASHBOARD_QUERY,\n });\n const data = result.data;\n return {\n recentVibes: data?.recentVibes ?? [],\n activeSessions: data?.activeSessions?.items ?? [],\n agentFleet: data?.agentFleetSummary ?? null,\n };\n } catch {\n // Schema may not yet be deployed in this environment — render empty.\n return { recentVibes: [], activeSessions: [], agentFleet: null };\n }\n },\n staleTime: 60 * 1000,\n gcTime: 5 * 60 * 1000,\n retry: 0,\n refetchOnWindowFocus: true,\n });\n}\n\nexport function useGlobalDashboardData(authToken?: string | null) {\n return useQuery({\n queryKey: ['dashboard', 'global'],\n enabled: !!authToken,\n queryFn: async (): Promise<GlobalDashboardData> => {\n const result = await graphqlFetch<{\n currentUser: GlobalDashboardData['currentUser'];\n myDashboardPreferences: Record<string, unknown> | null;\n myWorkspaces: {\n items: Array<{\n id: string;\n name: string;\n status: string;\n type: string;\n createdAt: string;\n memberCount: number;\n }>;\n total: number;\n };\n myOrganizations: {\n items: Array<{\n id: string;\n name: string;\n status: string;\n type: string;\n createdAt: string;\n }>;\n total: number;\n };\n }>({\n gateway: 'global',\n authToken: authToken || undefined,\n query: print(DashboardGlobalDataDocument),\n });\n\n const data = result.data;\n\n return {\n currentUser: data?.currentUser ?? null,\n dashboardPreferences: data?.myDashboardPreferences\n ? (data.myDashboardPreferences as unknown as GlobalDashboardData['dashboardPreferences'])\n : null,\n workspaces: data?.myWorkspaces ?? { items: [], total: 0 },\n organizations: data?.myOrganizations ?? { items: [], total: 0 },\n };\n },\n staleTime: 5 * 60 * 1000, // 5 minutes — user info and prefs change rarely\n gcTime: 10 * 60 * 1000,\n retry: 1,\n });\n}\n"],"mappings":";;;;;;;AA+BA,IAAM,IAAe,QAAQ;AAI7B,SAAgB,EAAyB,GAA2B;CAClE,IAAM,EAAE,mBAAgB,GAAkB;AAE1C,QAAO,EAAS;EACd,UAAU;GAAC;GAAa;GAAY;GAAY;EAChD,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC;EAC1B,SAAS,aACQ,MAAM,EAElB;GACD,SAAS;GACT,WAAW,KAAa,KAAA;GACxB,gBAAgB;GAChB,OAAO,EAAM,EAA0B;GACvC,WAAW,EAAE,QAAQ,EAAE,gBAAa,EAAE;GACvC,CAAC,EAEY,MAAM,YAAY;GAAE,OAAO,EAAE;GAAE,OAAO;GAAG;EAEzD,WAAW,MAAS;EACpB,QAAQ,MAAS;EACjB,OAAO;EACP,sBAAsB;EACvB,CAAC;;AAGJ,SAAgB,EAA0B,GAA2B;CACnE,IAAM,EAAE,mBAAgB,GAAkB;AAE1C,QAAO,EAAS;EACd,UAAU;GAAC;GAAa;GAAa;GAAY;EACjD,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC;EAC1B,SAAS,YAA6C;GAqBpD,IAAM,KApBS,MAAM,EAWlB;IACD,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,gBAAgB;IAChB,OAAO,EAAM,EAA+B;IAC7C,CAAC,EAIkB,MACd,IAAe,GAAM,yBACvB;IACE,WAAW,KAAK,MAAM,EAAK,uBAAuB,mBAAmB,EAAa;IAClF,YAAY,KAAK,OACd,EAAK,yBAAyB,gBAAgB,KAAK,EACrD;IACD,WAAW;IACZ,GACD;AAEJ,UAAO;IAGL,YAAY;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAGnC,UAAU;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IACjC,kBAAkB,GAAM,uBAAuB,EAAE;IACjD,gBAAgB,GAAM,kBAAkB,EAAE;IAC1C,MAAM,GAAM,WAAW;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAC9C,QAAQ;KACN,QAAQ,GAAM,UAAU,SAAS,EAAE,EAAE,KAAK,OAAO;MAC/C,IAAI,EAAE,KAAK;MACX,MAAM,EAAE,KAAK;MACb,aAAa,EAAE,KAAK;MACrB,EAAE;KACH,YAAY,GAAM,UAAU,cAAc;KAC3C;IACD,eAAe,GAAM,oBAAoB;IACzC;IACD;;EAEH,WAAW,MAAS;EACpB,QAAQ,MAAS;EACjB,OAAO;EACP,sBAAsB;EACvB,CAAC;;AASJ,IAAM,IAA+B;AAyCrC,SAAgB,EAA6B,GAA2B,IAAU,IAAO;CACvF,IAAM,EAAE,mBAAgB,GAAkB;AAE1C,QAAO,EAAS;EACd,UAAU;GAAC;GAAa;GAAgB;GAAY;EACpD,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC,KAAe;EACzC,SAAS,YAAgD;AACvD,OAAI;IAOF,IAAM,KANS,MAAM,EAA4C;KAC/D,SAAS;KACT,WAAW,KAAa,KAAA;KACxB,gBAAgB;KAChB,OAAO;KACR,CAAC,EACkB;AACpB,WAAO;KACL,aAAa,GAAM,eAAe,EAAE;KACpC,gBAAgB,GAAM,gBAAgB,SAAS,EAAE;KACjD,YAAY,GAAM,qBAAqB;KACxC;WACK;AAEN,WAAO;KAAE,aAAa,EAAE;KAAE,gBAAgB,EAAE;KAAE,YAAY;KAAM;;;EAGpE,WAAW,KAAK;EAChB,QAAQ,MAAS;EACjB,OAAO;EACP,sBAAsB;EACvB,CAAC;;AAGJ,SAAgB,EAAuB,GAA2B;AAChE,QAAO,EAAS;EACd,UAAU,CAAC,aAAa,SAAS;EACjC,SAAS,CAAC,CAAC;EACX,SAAS,YAA0C;GA+BjD,IAAM,KA9BS,MAAM,EAwBlB;IACD,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA4B;IAC1C,CAAC,EAEkB;AAEpB,UAAO;IACL,aAAa,GAAM,eAAe;IAClC,sBAAsB,GAAM,yBACvB,EAAK,yBACN;IACJ,YAAY,GAAM,gBAAgB;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IACzD,eAAe,GAAM,mBAAmB;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAChE;;EAEH,WAAW,MAAS;EACpB,QAAQ,MAAU;EAClB,OAAO;EACR,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { WidgetWrapper as e } from "../WidgetWrapper.js";
2
+ import { AlertTriangle as t, ArrowRight as n, Bot as r, Wifi as i, WifiOff as a } from "lucide-react";
3
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
4
+ import { Button as c } from "@burdenoff/fe-libs/ui";
5
+ //#region src/pages/dashboard/widgets/AgentsWidget.tsx
6
+ function l({ workspaceData: l, isLoading: u, navigate: d }) {
7
+ let f = l?.agentFleet ?? null, p = f?.total ?? 0;
8
+ return /* @__PURE__ */ o(e, {
9
+ title: "Agent Fleet",
10
+ icon: /* @__PURE__ */ o(r, { className: "size-4" }),
11
+ size: "small",
12
+ isLoading: u,
13
+ unavailable: !l,
14
+ headerAction: /* @__PURE__ */ s(c, {
15
+ variant: "ghost",
16
+ size: "sm",
17
+ className: "text-xs",
18
+ onClick: () => d("/vibecontrols/agents"),
19
+ children: ["Open ", /* @__PURE__ */ o(n, { className: "ml-1 size-3" })]
20
+ }),
21
+ children: !f || p === 0 ? /* @__PURE__ */ s("div", {
22
+ className: "text-center py-3",
23
+ children: [/* @__PURE__ */ o("p", {
24
+ className: "text-sm text-muted-foreground mb-2",
25
+ children: "No agents connected"
26
+ }), /* @__PURE__ */ o(c, {
27
+ variant: "outline",
28
+ size: "sm",
29
+ onClick: () => d("/vibecontrols/agents/new"),
30
+ children: "Connect agent"
31
+ })]
32
+ }) : /* @__PURE__ */ s("div", {
33
+ className: "space-y-3",
34
+ children: [
35
+ /* @__PURE__ */ s("p", {
36
+ className: "text-2xl font-semibold text-text-primary",
37
+ children: [p, /* @__PURE__ */ o("span", {
38
+ className: "ml-1 text-xs font-normal text-muted-foreground",
39
+ children: "total"
40
+ })]
41
+ }),
42
+ /* @__PURE__ */ s("div", {
43
+ className: "grid grid-cols-3 gap-2 text-center",
44
+ children: [
45
+ /* @__PURE__ */ s("div", {
46
+ className: "rounded-md bg-status-success-bg/30 p-2",
47
+ children: [
48
+ /* @__PURE__ */ o(i, { className: "mx-auto size-4 text-status-success-text" }),
49
+ /* @__PURE__ */ o("p", {
50
+ className: "mt-1 text-sm font-semibold text-text-primary",
51
+ children: f.online
52
+ }),
53
+ /* @__PURE__ */ o("p", {
54
+ className: "text-[10px] text-muted-foreground",
55
+ children: "online"
56
+ })
57
+ ]
58
+ }),
59
+ /* @__PURE__ */ s("div", {
60
+ className: "rounded-md bg-status-warning-bg/30 p-2",
61
+ children: [
62
+ /* @__PURE__ */ o(t, { className: "mx-auto size-4 text-status-warning-text" }),
63
+ /* @__PURE__ */ o("p", {
64
+ className: "mt-1 text-sm font-semibold text-text-primary",
65
+ children: f.degraded
66
+ }),
67
+ /* @__PURE__ */ o("p", {
68
+ className: "text-[10px] text-muted-foreground",
69
+ children: "degraded"
70
+ })
71
+ ]
72
+ }),
73
+ /* @__PURE__ */ s("div", {
74
+ className: "rounded-md bg-text-tertiary/10 p-2",
75
+ children: [
76
+ /* @__PURE__ */ o(a, { className: "mx-auto size-4 text-text-tertiary" }),
77
+ /* @__PURE__ */ o("p", {
78
+ className: "mt-1 text-sm font-semibold text-text-primary",
79
+ children: f.offline
80
+ }),
81
+ /* @__PURE__ */ o("p", {
82
+ className: "text-[10px] text-muted-foreground",
83
+ children: "offline"
84
+ })
85
+ ]
86
+ })
87
+ ]
88
+ }),
89
+ f.lastSeenAt ? /* @__PURE__ */ s("p", {
90
+ className: "text-[11px] text-muted-foreground text-center",
91
+ children: [
92
+ "Last seen",
93
+ " ",
94
+ new Date(f.lastSeenAt).toLocaleString(void 0, {
95
+ hour: "2-digit",
96
+ minute: "2-digit",
97
+ month: "short",
98
+ day: "numeric"
99
+ })
100
+ ]
101
+ }) : null
102
+ ]
103
+ })
104
+ });
105
+ }
106
+ //#endregion
107
+ export { l as AgentsWidget };
108
+
109
+ //# sourceMappingURL=AgentsWidget.js.map
@@ -0,0 +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-muted-foreground 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-muted-foreground\">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-muted-foreground\">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-muted-foreground\">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-muted-foreground\">offline</p>\n </div>\n </div>\n {fleet.lastSeenAt ? (\n <p className=\"text-[11px] text-muted-foreground 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;cAAqC;IAAuB,CAAA,EACzE,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;gBAAiD;MAAY,CAAA,CAC3E;;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;mBAAoC;SAAU,CAAA;QACvD;;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;mBAAoC;SAAY,CAAA;QACzD;;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;mBAAoC;SAAW,CAAA;QACxD;;MACF;;IACL,EAAM,aACL,kBAAC,KAAD;KAAG,WAAU;eAAb;MAA6D;MACjD;MACT,IAAI,KAAK,EAAM,WAAW,CAAC,eAAe,KAAA,GAAW;OACpD,MAAM;OACN,QAAQ;OACR,OAAO;OACP,KAAK;OACN,CAAC;MACA;SACF;IACA;;EAEM,CAAA"}
@@ -7,7 +7,7 @@ function o({ workspaceData: o, isLoading: s, navigate: c }) {
7
7
  let l = o?.groups.items ?? [], u = o?.groups.totalCount ?? 0;
8
8
  return /* @__PURE__ */ r(e, {
9
9
  title: "Groups",
10
- icon: /* @__PURE__ */ r(n, { className: "h-4 w-4" }),
10
+ icon: /* @__PURE__ */ r(n, { className: "size-4" }),
11
11
  size: "small",
12
12
  isLoading: s,
13
13
  unavailable: !o,
@@ -16,7 +16,7 @@ function o({ workspaceData: o, isLoading: s, navigate: c }) {
16
16
  size: "sm",
17
17
  className: "text-xs",
18
18
  onClick: () => c("/groups"),
19
- children: /* @__PURE__ */ r(t, { className: "h-3 w-3" })
19
+ children: /* @__PURE__ */ r(t, { className: "size-3" })
20
20
  }),
21
21
  children: l.length === 0 ? /* @__PURE__ */ r("div", {
22
22
  className: "text-center py-3",
@@ -26,11 +26,12 @@ function o({ workspaceData: o, isLoading: s, navigate: c }) {
26
26
  })
27
27
  }) : /* @__PURE__ */ i("div", {
28
28
  className: "space-y-1.5",
29
- children: [l.slice(0, 4).map((e) => /* @__PURE__ */ i("div", {
30
- className: "flex items-center gap-2 p-1.5 rounded hover:bg-accent/5 cursor-pointer transition-colors",
29
+ children: [l.slice(0, 4).map((e) => /* @__PURE__ */ i("button", {
30
+ type: "button",
31
+ className: "w-full flex items-center gap-2 p-1.5 rounded hover:bg-accent/5 cursor-pointer transition-colors text-left",
31
32
  onClick: () => c("/groups"),
32
33
  children: [/* @__PURE__ */ r("div", {
33
- className: "h-7 w-7 rounded-full bg-accent-purple-subtle text-accent-purple flex items-center justify-center text-xs font-bold shrink-0",
34
+ className: "size-7 rounded-full bg-accent-purple-subtle text-accent-purple flex items-center justify-center text-xs font-bold shrink-0",
34
35
  children: e.name.charAt(0).toUpperCase()
35
36
  }), /* @__PURE__ */ i("div", {
36
37
  className: "min-w-0",
@@ -1 +1 @@
1
- {"version":3,"file":"GroupsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/GroupsWidget.tsx"],"sourcesContent":["import { Users, ArrowRight } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nexport function GroupsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const groups = workspaceData?.groups.items ?? [];\n const total = workspaceData?.groups.totalCount ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Groups\"\n icon={<Users className=\"h-4 w-4\" />}\n size=\"small\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button variant=\"ghost\" size=\"sm\" className=\"text-xs\" onClick={() => navigate('/groups')}>\n <ArrowRight className=\"h-3 w-3\" />\n </Button>\n }\n >\n {groups.length === 0 ? (\n <div className=\"text-center py-3\">\n <p className=\"text-xs text-muted-foreground\">No groups yet</p>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n {groups.slice(0, 4).map((group) => (\n <div\n key={group.id}\n className=\"flex items-center gap-2 p-1.5 rounded hover:bg-accent/5 cursor-pointer transition-colors\"\n onClick={() => navigate('/groups')}\n >\n <div className=\"h-7 w-7 rounded-full bg-accent-purple-subtle text-accent-purple flex items-center justify-center text-xs font-bold shrink-0\">\n {group.name.charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">{group.name}</p>\n {group.description && (\n <p className=\"text-[11px] text-muted-foreground truncate\">{group.description}</p>\n )}\n </div>\n </div>\n ))}\n {total > 4 && (\n <p className=\"text-[11px] text-muted-foreground text-center\">\n +{total - 4} more groups\n </p>\n )}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,EAAa,EAAE,kBAAe,cAAW,eAAyB;CAChF,IAAM,IAAS,GAAe,OAAO,SAAS,EAAE,EAC1C,IAAQ,GAAe,OAAO,cAAc;AAElD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;EACnC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GAAQ,SAAQ;GAAQ,MAAK;GAAK,WAAU;GAAU,eAAe,EAAS,UAAU;aACtF,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;GAC3B,CAAA;YAGV,EAAO,WAAW,IACjB,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,KAAD;IAAG,WAAU;cAAgC;IAAiB,CAAA;GAC1D,CAAA,GAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,EAAO,MAAM,GAAG,EAAE,CAAC,KAAK,MACvB,kBAAC,OAAD;IAEE,WAAU;IACV,eAAe,EAAS,UAAU;cAHpC,CAKE,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAM,KAAK,OAAO,EAAE,CAAC,aAAa;KAC/B,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAkD,EAAM;MAAS,CAAA,EAC7E,EAAM,eACL,kBAAC,KAAD;MAAG,WAAU;gBAA8C,EAAM;MAAgB,CAAA,CAE/E;OACF;MAbC,EAAM,GAaP,CACN,EACD,IAAQ,KACP,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6D;KACzD,IAAQ;KAAE;KACV;MAEF;;EAEM,CAAA"}
1
+ {"version":3,"file":"GroupsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/GroupsWidget.tsx"],"sourcesContent":["import { Users, ArrowRight } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nexport function GroupsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const groups = workspaceData?.groups.items ?? [];\n const total = workspaceData?.groups.totalCount ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Groups\"\n icon={<Users className=\"size-4\" />}\n size=\"small\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button variant=\"ghost\" size=\"sm\" className=\"text-xs\" onClick={() => navigate('/groups')}>\n <ArrowRight className=\"size-3\" />\n </Button>\n }\n >\n {groups.length === 0 ? (\n <div className=\"text-center py-3\">\n <p className=\"text-xs text-muted-foreground\">No groups yet</p>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n {groups.slice(0, 4).map((group) => (\n <button\n key={group.id}\n type=\"button\"\n className=\"w-full flex items-center gap-2 p-1.5 rounded hover:bg-accent/5 cursor-pointer transition-colors text-left\"\n onClick={() => navigate('/groups')}\n >\n <div className=\"size-7 rounded-full bg-accent-purple-subtle text-accent-purple flex items-center justify-center text-xs font-bold shrink-0\">\n {group.name.charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">{group.name}</p>\n {group.description && (\n <p className=\"text-[11px] text-muted-foreground truncate\">{group.description}</p>\n )}\n </div>\n </button>\n ))}\n {total > 4 && (\n <p className=\"text-[11px] text-muted-foreground text-center\">\n +{total - 4} more groups\n </p>\n )}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,EAAa,EAAE,kBAAe,cAAW,eAAyB;CAChF,IAAM,IAAS,GAAe,OAAO,SAAS,EAAE,EAC1C,IAAQ,GAAe,OAAO,cAAc;AAElD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAO,WAAU,UAAW,CAAA;EAClC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GAAQ,SAAQ;GAAQ,MAAK;GAAK,WAAU;GAAU,eAAe,EAAS,UAAU;aACtF,kBAAC,GAAD,EAAY,WAAU,UAAW,CAAA;GAC1B,CAAA;YAGV,EAAO,WAAW,IACjB,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,KAAD;IAAG,WAAU;cAAgC;IAAiB,CAAA;GAC1D,CAAA,GAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,EAAO,MAAM,GAAG,EAAE,CAAC,KAAK,MACvB,kBAAC,UAAD;IAEE,MAAK;IACL,WAAU;IACV,eAAe,EAAS,UAAU;cAJpC,CAME,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAM,KAAK,OAAO,EAAE,CAAC,aAAa;KAC/B,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAkD,EAAM;MAAS,CAAA,EAC7E,EAAM,eACL,kBAAC,KAAD;MAAG,WAAU;gBAA8C,EAAM;MAAgB,CAAA,CAE/E;OACC;MAdF,EAAM,GAcJ,CACT,EACD,IAAQ,KACP,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6D;KACzD,IAAQ;KAAE;KACV;MAEF;;EAEM,CAAA"}
@@ -7,7 +7,7 @@ function s({ workspaceData: s, globalData: c, isLoading: l, navigate: u }) {
7
7
  let d = c?.workspaces?.items ?? s?.workspaces.items ?? [], f = d.reduce((e, t) => e + (t.memberCount ?? 0), 0), p = c?.workspaces?.total ?? s?.workspaces.total ?? 0;
8
8
  return /* @__PURE__ */ i(e, {
9
9
  title: "Members",
10
- icon: /* @__PURE__ */ i(r, { className: "h-4 w-4" }),
10
+ icon: /* @__PURE__ */ i(r, { className: "size-4" }),
11
11
  size: "small",
12
12
  isLoading: l,
13
13
  unavailable: !s && !c,
@@ -16,7 +16,7 @@ function s({ workspaceData: s, globalData: c, isLoading: l, navigate: u }) {
16
16
  size: "sm",
17
17
  className: "text-xs",
18
18
  onClick: () => u("/workspaces/members"),
19
- children: /* @__PURE__ */ i(t, { className: "h-3 w-3" })
19
+ children: /* @__PURE__ */ i(t, { className: "size-3" })
20
20
  }),
21
21
  children: /* @__PURE__ */ a("div", {
22
22
  className: "space-y-3",
@@ -41,17 +41,17 @@ function s({ workspaceData: s, globalData: c, isLoading: l, navigate: u }) {
41
41
  variant: "outline",
42
42
  size: "sm",
43
43
  className: "w-full text-xs",
44
- onClick: () => u("/workspaces/members"),
45
- children: [/* @__PURE__ */ i(n, { className: "h-3 w-3 mr-1.5" }), "Invite a member"]
44
+ onClick: () => u("/workspaces/members?invite=true"),
45
+ children: [/* @__PURE__ */ i(n, { className: "size-3 mr-1.5" }), "Invite a member"]
46
46
  }),
47
47
  d.length > 0 && /* @__PURE__ */ a("div", {
48
48
  className: "flex -space-x-2 justify-center",
49
49
  children: [d.slice(0, 5).map((e) => /* @__PURE__ */ i("div", {
50
- className: "h-8 w-8 rounded-full bg-primary/10 text-primary flex items-center justify-center text-xs font-bold border-2 border-bg-surface",
50
+ className: "size-8 rounded-full bg-primary/10 text-primary flex items-center justify-center text-xs font-bold border-2 border-bg-surface",
51
51
  title: e.name,
52
52
  children: e.name.charAt(0).toUpperCase()
53
53
  }, e.id)), p > 5 && /* @__PURE__ */ a("div", {
54
- className: "h-8 w-8 rounded-full bg-muted text-muted-foreground flex items-center justify-center text-xs font-bold border-2 border-bg-surface",
54
+ className: "size-8 rounded-full bg-muted text-muted-foreground flex items-center justify-center text-xs font-bold border-2 border-bg-surface",
55
55
  children: ["+", p - 5]
56
56
  })]
57
57
  })
@@ -1 +1 @@
1
- {"version":3,"file":"MembersWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/MembersWidget.tsx"],"sourcesContent":["import { Users, UserPlus, ArrowRight } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nexport function MembersWidget({ workspaceData, globalData, isLoading, navigate }: WidgetProps) {\n // Member count comes from globalData.workspaces (each workspace has memberCount)\n const workspaces = globalData?.workspaces?.items ?? workspaceData?.workspaces.items ?? [];\n const totalMembers = workspaces.reduce(\n (sum, ws) => sum + ((ws as { memberCount?: number }).memberCount ?? 0),\n 0\n );\n const totalWorkspaces = globalData?.workspaces?.total ?? workspaceData?.workspaces.total ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Members\"\n icon={<Users className=\"h-4 w-4\" />}\n size=\"small\"\n isLoading={isLoading}\n unavailable={!workspaceData && !globalData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/workspaces/members')}\n >\n <ArrowRight className=\"h-3 w-3\" />\n </Button>\n }\n >\n <div className=\"space-y-3\">\n <div className=\"text-center\">\n <p className=\"text-3xl font-bold text-text-primary\">{totalMembers}</p>\n <p className=\"text-xs text-muted-foreground\">\n {totalMembers === 1 ? 'Member' : 'Members'} across {totalWorkspaces}{' '}\n {totalWorkspaces === 1 ? 'workspace' : 'workspaces'}\n </p>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full text-xs\"\n onClick={() => navigate('/workspaces/members')}\n >\n <UserPlus className=\"h-3 w-3 mr-1.5\" />\n Invite a member\n </Button>\n {workspaces.length > 0 && (\n <div className=\"flex -space-x-2 justify-center\">\n {workspaces.slice(0, 5).map((ws) => (\n <div\n key={ws.id}\n className=\"h-8 w-8 rounded-full bg-primary/10 text-primary flex items-center justify-center text-xs font-bold border-2 border-bg-surface\"\n title={ws.name}\n >\n {ws.name.charAt(0).toUpperCase()}\n </div>\n ))}\n {totalWorkspaces > 5 && (\n <div className=\"h-8 w-8 rounded-full bg-muted text-muted-foreground flex items-center justify-center text-xs font-bold border-2 border-bg-surface\">\n +{totalWorkspaces - 5}\n </div>\n )}\n </div>\n )}\n </div>\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,EAAc,EAAE,kBAAe,eAAY,cAAW,eAAyB;CAE7F,IAAM,IAAa,GAAY,YAAY,SAAS,GAAe,WAAW,SAAS,EAAE,EACnF,IAAe,EAAW,QAC7B,GAAK,MAAO,KAAQ,EAAgC,eAAe,IACpE,EACD,EACK,IAAkB,GAAY,YAAY,SAAS,GAAe,WAAW,SAAS;AAE5F,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;EACnC,MAAK;EACM;EACX,aAAa,CAAC,KAAiB,CAAC;EAChC,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,sBAAsB;aAE9C,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;GAC3B,CAAA;YAGX,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAwC;MAAiB,CAAA,EACtE,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACG,MAAiB,IAAI,WAAW;OAAU;OAAS;OAAiB;OACpE,MAAoB,IAAI,cAAc;OACrC;QACA;;IACN,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,WAAU;KACV,eAAe,EAAS,sBAAsB;eAJhD,CAME,kBAAC,GAAD,EAAU,WAAU,kBAAmB,CAAA,EAAA,kBAEhC;;IACR,EAAW,SAAS,KACnB,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,EAAW,MAAM,GAAG,EAAE,CAAC,KAAK,MAC3B,kBAAC,OAAD;MAEE,WAAU;MACV,OAAO,EAAG;gBAET,EAAG,KAAK,OAAO,EAAE,CAAC,aAAa;MAC5B,EALC,EAAG,GAKJ,CACN,EACD,IAAkB,KACjB,kBAAC,OAAD;MAAK,WAAU;gBAAf,CAAmJ,KAC/I,IAAkB,EAChB;QAEJ;;IAEJ;;EACQ,CAAA"}
1
+ {"version":3,"file":"MembersWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/MembersWidget.tsx"],"sourcesContent":["import { Users, UserPlus, ArrowRight } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nexport function MembersWidget({ workspaceData, globalData, isLoading, navigate }: WidgetProps) {\n // Member count comes from globalData.workspaces (each workspace has memberCount)\n const workspaces = globalData?.workspaces?.items ?? workspaceData?.workspaces.items ?? [];\n const totalMembers = workspaces.reduce(\n (sum, ws) => sum + ((ws as { memberCount?: number }).memberCount ?? 0),\n 0\n );\n const totalWorkspaces = globalData?.workspaces?.total ?? workspaceData?.workspaces.total ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Members\"\n icon={<Users className=\"size-4\" />}\n size=\"small\"\n isLoading={isLoading}\n unavailable={!workspaceData && !globalData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/workspaces/members')}\n >\n <ArrowRight className=\"size-3\" />\n </Button>\n }\n >\n <div className=\"space-y-3\">\n <div className=\"text-center\">\n <p className=\"text-3xl font-bold text-text-primary\">{totalMembers}</p>\n <p className=\"text-xs text-muted-foreground\">\n {totalMembers === 1 ? 'Member' : 'Members'} across {totalWorkspaces}{' '}\n {totalWorkspaces === 1 ? 'workspace' : 'workspaces'}\n </p>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full text-xs\"\n onClick={() => navigate('/workspaces/members?invite=true')}\n >\n <UserPlus className=\"size-3 mr-1.5\" />\n Invite a member\n </Button>\n {workspaces.length > 0 && (\n <div className=\"flex -space-x-2 justify-center\">\n {workspaces.slice(0, 5).map((ws) => (\n <div\n key={ws.id}\n className=\"size-8 rounded-full bg-primary/10 text-primary flex items-center justify-center text-xs font-bold border-2 border-bg-surface\"\n title={ws.name}\n >\n {ws.name.charAt(0).toUpperCase()}\n </div>\n ))}\n {totalWorkspaces > 5 && (\n <div className=\"size-8 rounded-full bg-muted text-muted-foreground flex items-center justify-center text-xs font-bold border-2 border-bg-surface\">\n +{totalWorkspaces - 5}\n </div>\n )}\n </div>\n )}\n </div>\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,EAAc,EAAE,kBAAe,eAAY,cAAW,eAAyB;CAE7F,IAAM,IAAa,GAAY,YAAY,SAAS,GAAe,WAAW,SAAS,EAAE,EACnF,IAAe,EAAW,QAC7B,GAAK,MAAO,KAAQ,EAAgC,eAAe,IACpE,EACD,EACK,IAAkB,GAAY,YAAY,SAAS,GAAe,WAAW,SAAS;AAE5F,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAO,WAAU,UAAW,CAAA;EAClC,MAAK;EACM;EACX,aAAa,CAAC,KAAiB,CAAC;EAChC,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,sBAAsB;aAE9C,kBAAC,GAAD,EAAY,WAAU,UAAW,CAAA;GAC1B,CAAA;YAGX,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAwC;MAAiB,CAAA,EACtE,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACG,MAAiB,IAAI,WAAW;OAAU;OAAS;OAAiB;OACpE,MAAoB,IAAI,cAAc;OACrC;QACA;;IACN,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,WAAU;KACV,eAAe,EAAS,kCAAkC;eAJ5D,CAME,kBAAC,GAAD,EAAU,WAAU,iBAAkB,CAAA,EAAA,kBAE/B;;IACR,EAAW,SAAS,KACnB,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,EAAW,MAAM,GAAG,EAAE,CAAC,KAAK,MAC3B,kBAAC,OAAD;MAEE,WAAU;MACV,OAAO,EAAG;gBAET,EAAG,KAAK,OAAO,EAAE,CAAC,aAAa;MAC5B,EALC,EAAG,GAKJ,CACN,EACD,IAAkB,KACjB,kBAAC,OAAD;MAAK,WAAU;gBAAf,CAAkJ,KAC9I,IAAkB,EAChB;QAEJ;;IAEJ;;EACQ,CAAA"}
@@ -16,7 +16,7 @@ function u({ workspaceData: u, isLoading: d, navigate: f }) {
16
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;
17
17
  return /* @__PURE__ */ i(e, {
18
18
  title: "Projects",
19
- icon: /* @__PURE__ */ i(r, { className: "h-4 w-4" }),
19
+ icon: /* @__PURE__ */ i(r, { className: "size-4" }),
20
20
  size: "medium",
21
21
  isLoading: d,
22
22
  unavailable: !u,
@@ -25,7 +25,7 @@ function u({ workspaceData: u, isLoading: d, navigate: f }) {
25
25
  size: "sm",
26
26
  className: "text-xs",
27
27
  onClick: () => f("/workspaces/projects"),
28
- children: ["View all ", /* @__PURE__ */ i(t, { className: "ml-1 h-3 w-3" })]
28
+ children: ["View all ", /* @__PURE__ */ i(t, { className: "ml-1 size-3" })]
29
29
  }),
30
30
  children: p.length === 0 ? /* @__PURE__ */ a("div", {
31
31
  className: "text-center py-4",
@@ -46,7 +46,7 @@ function u({ workspaceData: u, isLoading: d, navigate: f }) {
46
46
  /* @__PURE__ */ a("span", {
47
47
  className: "flex items-center gap-1",
48
48
  children: [
49
- /* @__PURE__ */ i(n, { className: "h-2 w-2 fill-status-success-bg text-status-success-bg" }),
49
+ /* @__PURE__ */ i(n, { className: "size-2 fill-status-success-bg text-status-success-bg" }),
50
50
  h,
51
51
  " active"
52
52
  ]
@@ -54,7 +54,7 @@ function u({ workspaceData: u, isLoading: d, navigate: f }) {
54
54
  g > 0 && /* @__PURE__ */ a("span", {
55
55
  className: "flex items-center gap-1",
56
56
  children: [
57
- /* @__PURE__ */ i(n, { className: "h-2 w-2 fill-text-tertiary text-text-tertiary" }),
57
+ /* @__PURE__ */ i(n, { className: "size-2 fill-text-tertiary text-text-tertiary" }),
58
58
  g,
59
59
  " inactive"
60
60
  ]
@@ -66,12 +66,13 @@ function u({ workspaceData: u, isLoading: d, navigate: f }) {
66
66
  ]
67
67
  }), /* @__PURE__ */ i("div", {
68
68
  className: "space-y-2",
69
- children: p.slice(0, 4).map((e) => /* @__PURE__ */ a("div", {
70
- className: "flex items-center justify-between p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors",
69
+ children: p.slice(0, 4).map((e) => /* @__PURE__ */ a("button", {
70
+ type: "button",
71
+ className: "w-full flex items-center justify-between p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left",
71
72
  onClick: () => f(`/workspaces/${e.workspaceId}/projects`),
72
73
  children: [/* @__PURE__ */ a("div", {
73
74
  className: "flex items-center gap-2 min-w-0",
74
- children: [/* @__PURE__ */ i(n, { className: `h-2 w-2 ${c[e.status] || "bg-text-tertiary"} fill-current` }), /* @__PURE__ */ i("span", {
75
+ children: [/* @__PURE__ */ i(n, { className: `size-2 ${c[e.status] || "bg-text-tertiary"} fill-current` }), /* @__PURE__ */ i("span", {
75
76
  className: "text-sm font-medium text-text-primary truncate",
76
77
  children: e.name
77
78
  })]
@@ -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=\"h-4 w-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 h-3 w-3\" />\n </Button>\n }\n >\n {projects.length === 0 ? (\n <div className=\"text-center py-4\">\n <p className=\"text-sm text-muted-foreground 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-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Circle className=\"h-2 w-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=\"h-2 w-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 <div\n key={proj.id}\n className=\"flex items-center justify-between p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors\"\n onClick={() => navigate(`/workspaces/${proj.workspaceId}/projects`)}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <Circle\n className={`h-2 w-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 </div>\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,WAAY,CAAA;EAC1C,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,gBAAiB,CAAA,CACzC;;YAGV,EAAS,WAAW,IACnB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAqC;IAAmB,CAAA,EACrE,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,yDAA0D,CAAA;OAC3E;OAAY;OACR;;KACN,IAAgB,KACf,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACE,kBAAC,GAAD,EAAQ,WAAU,iDAAkD,CAAA;OACnE;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,OAAD;KAEE,WAAU;KACV,eAAe,EAAS,eAAe,EAAK,YAAY,WAAW;eAHrE,CAKE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EACE,WAAW,WAAW,EAAa,EAAK,WAAW,mBAAmB,gBACtE,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,CACJ;OAlBC,EAAK,GAkBN,CACN;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 } 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-muted-foreground 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-muted-foreground\">\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;cAAqC;IAAmB,CAAA,EACrE,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,72 +1,126 @@
1
1
  import { WidgetWrapper as e } from "../WidgetWrapper.js";
2
- import { Calendar as t, FileText as n, FolderKanban as r, Plus as i, Tags as a, Upload as o, UserPlus as s, Zap as c } from "lucide-react";
3
- import { jsx as l, jsxs as u } from "react/jsx-runtime";
4
- import { Button as d } from "@burdenoff/fe-libs/ui";
2
+ import { Bot as t, Calendar as n, Cog as r, FileText as i, FolderKanban as a, Plus as o, Sparkles as s, Tags as c, Terminal as l, Upload as u, UserPlus as d, Zap as f } from "lucide-react";
3
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
4
+ import { Button as h } from "@burdenoff/fe-libs/ui";
5
5
  //#region src/pages/dashboard/widgets/QuickActionsWidget.tsx
6
- var f = [
6
+ var g = [
7
7
  {
8
8
  id: "create-workspace",
9
9
  label: "New Workspace",
10
- icon: i,
10
+ icon: o,
11
11
  path: "/workspaces/list",
12
12
  color: "text-accent-blue"
13
13
  },
14
14
  {
15
15
  id: "create-project",
16
16
  label: "New Project",
17
- icon: r,
17
+ icon: a,
18
18
  path: "/workspaces/projects",
19
19
  color: "text-status-success-text"
20
20
  },
21
21
  {
22
22
  id: "invite-member",
23
23
  label: "Invite Member",
24
- icon: s,
24
+ icon: d,
25
25
  path: "/workspaces/members",
26
26
  color: "text-accent-purple"
27
27
  },
28
28
  {
29
29
  id: "upload-file",
30
30
  label: "Upload File",
31
- icon: o,
31
+ icon: u,
32
32
  path: "/files",
33
33
  color: "text-status-warning-text"
34
34
  },
35
35
  {
36
36
  id: "new-event",
37
37
  label: "New Event",
38
- icon: t,
38
+ icon: n,
39
39
  path: "/calendar",
40
40
  color: "text-accent-pink"
41
41
  },
42
42
  {
43
43
  id: "manage-tags",
44
44
  label: "Manage Tags",
45
- icon: a,
45
+ icon: c,
46
46
  path: "/tags",
47
47
  color: "text-accent-cyan"
48
48
  },
49
49
  {
50
50
  id: "view-workflows",
51
51
  label: "Workflows",
52
- icon: n,
52
+ icon: i,
53
53
  path: "/workflows",
54
54
  color: "text-accent-orange"
55
+ },
56
+ {
57
+ id: "settings",
58
+ label: "Settings",
59
+ icon: r,
60
+ path: "/settings",
61
+ color: "text-text-secondary"
62
+ }
63
+ ], _ = [
64
+ {
65
+ id: "new-vibe",
66
+ label: "New Vibe",
67
+ icon: s,
68
+ path: "/vibecontrols/vibes/new",
69
+ color: "text-accent-blue"
70
+ },
71
+ {
72
+ id: "view-sessions",
73
+ label: "Sessions",
74
+ icon: l,
75
+ path: "/vibecontrols/sessions",
76
+ color: "text-status-success-text"
77
+ },
78
+ {
79
+ id: "connect-agent",
80
+ label: "Connect Agent",
81
+ icon: t,
82
+ path: "/vibecontrols/agents/new",
83
+ color: "text-accent-purple"
84
+ },
85
+ {
86
+ id: "invite-member",
87
+ label: "Invite Member",
88
+ icon: d,
89
+ path: "/workspaces/members",
90
+ color: "text-accent-pink"
91
+ },
92
+ {
93
+ id: "upload-file",
94
+ label: "Upload File",
95
+ icon: u,
96
+ path: "/files",
97
+ color: "text-status-warning-text"
98
+ },
99
+ {
100
+ id: "settings",
101
+ label: "Settings",
102
+ icon: r,
103
+ path: "/settings",
104
+ color: "text-accent-cyan"
55
105
  }
56
106
  ];
57
- function p({ navigate: t, isLoading: n }) {
58
- return /* @__PURE__ */ l(e, {
107
+ function v(e) {
108
+ return e === "vibecontrols" ? _ : g;
109
+ }
110
+ function y({ navigate: t, isLoading: n, productId: r }) {
111
+ let i = v(r);
112
+ return /* @__PURE__ */ p(e, {
59
113
  title: "Quick Actions",
60
- icon: /* @__PURE__ */ l(c, { className: "h-4 w-4" }),
114
+ icon: /* @__PURE__ */ p(f, { className: "size-4" }),
61
115
  size: "medium",
62
116
  isLoading: n,
63
- children: /* @__PURE__ */ l("div", {
117
+ children: /* @__PURE__ */ p("div", {
64
118
  className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-2",
65
- children: f.map((e) => /* @__PURE__ */ u(d, {
119
+ children: i.map((e) => /* @__PURE__ */ m(h, {
66
120
  variant: "outline",
67
121
  className: "flex flex-col items-center gap-1.5 h-auto py-3 px-2 text-xs hover:bg-accent/5 transition-colors",
68
122
  onClick: () => t(e.path),
69
- children: [/* @__PURE__ */ l(e.icon, { className: `h-5 w-5 ${e.color}` }), /* @__PURE__ */ l("span", {
123
+ children: [/* @__PURE__ */ p(e.icon, { className: `size-5 ${e.color}` }), /* @__PURE__ */ p("span", {
70
124
  className: "text-text-secondary font-medium",
71
125
  children: e.label
72
126
  })]
@@ -75,6 +129,6 @@ function p({ navigate: t, isLoading: n }) {
75
129
  });
76
130
  }
77
131
  //#endregion
78
- export { p as QuickActionsWidget };
132
+ export { y as QuickActionsWidget };
79
133
 
80
134
  //# sourceMappingURL=QuickActionsWidget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QuickActionsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/QuickActionsWidget.tsx"],"sourcesContent":["import { Zap, Plus, Upload, UserPlus, FolderKanban, Calendar, FileText, Tags } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst QUICK_ACTIONS = [\n {\n id: 'create-workspace',\n label: 'New Workspace',\n icon: Plus,\n path: '/workspaces/list',\n color: 'text-accent-blue',\n },\n {\n id: 'create-project',\n label: 'New Project',\n icon: FolderKanban,\n path: '/workspaces/projects',\n color: 'text-status-success-text',\n },\n {\n id: 'invite-member',\n label: 'Invite Member',\n icon: UserPlus,\n path: '/workspaces/members',\n color: 'text-accent-purple',\n },\n {\n id: 'upload-file',\n label: 'Upload File',\n icon: Upload,\n path: '/files',\n color: 'text-status-warning-text',\n },\n {\n id: 'new-event',\n label: 'New Event',\n icon: Calendar,\n path: '/calendar',\n color: 'text-accent-pink',\n },\n { id: 'manage-tags', label: 'Manage Tags', icon: Tags, path: '/tags', color: 'text-accent-cyan' },\n {\n id: 'view-workflows',\n label: 'Workflows',\n icon: FileText,\n path: '/workflows',\n color: 'text-accent-orange',\n },\n];\n\nexport function QuickActionsWidget({ navigate, isLoading }: WidgetProps) {\n return (\n <WidgetWrapper\n title=\"Quick Actions\"\n icon={<Zap className=\"h-4 w-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n >\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-2\">\n {QUICK_ACTIONS.map((action) => (\n <Button\n key={action.id}\n variant=\"outline\"\n className=\"flex flex-col items-center gap-1.5 h-auto py-3 px-2 text-xs hover:bg-accent/5 transition-colors\"\n onClick={() => navigate(action.path)}\n >\n <action.icon className={`h-5 w-5 ${action.color}`} />\n <span className=\"text-text-secondary font-medium\">{action.label}</span>\n </Button>\n ))}\n </div>\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAgB;CACpB;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EAAE,IAAI;EAAe,OAAO;EAAe,MAAM;EAAM,MAAM;EAAS,OAAO;EAAoB;CACjG;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACF;AAED,SAAgB,EAAmB,EAAE,aAAU,gBAA0B;AACvE,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;EACjC,MAAK;EACM;YAEX,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAc,KAAK,MAClB,kBAAC,GAAD;IAEE,SAAQ;IACR,WAAU;IACV,eAAe,EAAS,EAAO,KAAK;cAJtC,CAME,kBAAC,EAAO,MAAR,EAAa,WAAW,WAAW,EAAO,SAAW,CAAA,EACrD,kBAAC,QAAD;KAAM,WAAU;eAAmC,EAAO;KAAa,CAAA,CAChE;MAPF,EAAO,GAOL,CACT;GACE,CAAA;EACQ,CAAA"}
1
+ {"version":3,"file":"QuickActionsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/QuickActionsWidget.tsx"],"sourcesContent":["import type { LucideIcon } from 'lucide-react';\nimport {\n Zap,\n Plus,\n Upload,\n UserPlus,\n FolderKanban,\n Calendar,\n FileText,\n Tags,\n Bot,\n Terminal,\n Sparkles,\n Cog,\n} from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\ninterface QuickAction {\n id: string;\n label: string;\n icon: LucideIcon;\n path: string;\n color: string;\n}\n\nconst WORKSPACES_QUICK_ACTIONS: QuickAction[] = [\n {\n id: 'create-workspace',\n label: 'New Workspace',\n icon: Plus,\n path: '/workspaces/list',\n color: 'text-accent-blue',\n },\n {\n id: 'create-project',\n label: 'New Project',\n icon: FolderKanban,\n path: '/workspaces/projects',\n color: 'text-status-success-text',\n },\n {\n id: 'invite-member',\n label: 'Invite Member',\n icon: UserPlus,\n path: '/workspaces/members',\n color: 'text-accent-purple',\n },\n {\n id: 'upload-file',\n label: 'Upload File',\n icon: Upload,\n path: '/files',\n color: 'text-status-warning-text',\n },\n {\n id: 'new-event',\n label: 'New Event',\n icon: Calendar,\n path: '/calendar',\n color: 'text-accent-pink',\n },\n {\n id: 'manage-tags',\n label: 'Manage Tags',\n icon: Tags,\n path: '/tags',\n color: 'text-accent-cyan',\n },\n {\n id: 'view-workflows',\n label: 'Workflows',\n icon: FileText,\n path: '/workflows',\n color: 'text-accent-orange',\n },\n {\n id: 'settings',\n label: 'Settings',\n icon: Cog,\n path: '/settings',\n color: 'text-text-secondary',\n },\n];\n\nconst VIBECONTROLS_QUICK_ACTIONS: QuickAction[] = [\n {\n id: 'new-vibe',\n label: 'New Vibe',\n icon: Sparkles,\n path: '/vibecontrols/vibes/new',\n color: 'text-accent-blue',\n },\n {\n id: 'view-sessions',\n label: 'Sessions',\n icon: Terminal,\n path: '/vibecontrols/sessions',\n color: 'text-status-success-text',\n },\n {\n id: 'connect-agent',\n label: 'Connect Agent',\n icon: Bot,\n path: '/vibecontrols/agents/new',\n color: 'text-accent-purple',\n },\n {\n id: 'invite-member',\n label: 'Invite Member',\n icon: UserPlus,\n path: '/workspaces/members',\n color: 'text-accent-pink',\n },\n {\n id: 'upload-file',\n label: 'Upload File',\n icon: Upload,\n path: '/files',\n color: 'text-status-warning-text',\n },\n {\n id: 'settings',\n label: 'Settings',\n icon: Cog,\n path: '/settings',\n color: 'text-accent-cyan',\n },\n];\n\nfunction pickActions(productId?: string): QuickAction[] {\n if (productId === 'vibecontrols') return VIBECONTROLS_QUICK_ACTIONS;\n return WORKSPACES_QUICK_ACTIONS;\n}\n\nexport function QuickActionsWidget({ navigate, isLoading, productId }: WidgetProps) {\n const actions = pickActions(productId);\n return (\n <WidgetWrapper\n title=\"Quick Actions\"\n icon={<Zap className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n >\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-2\">\n {actions.map((action) => (\n <Button\n key={action.id}\n variant=\"outline\"\n className=\"flex flex-col items-center gap-1.5 h-auto py-3 px-2 text-xs hover:bg-accent/5 transition-colors\"\n onClick={() => navigate(action.path)}\n >\n <action.icon className={`size-5 ${action.color}`} />\n <span className=\"text-text-secondary font-medium\">{action.label}</span>\n </Button>\n ))}\n </div>\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AA2BA,IAAM,IAA0C;CAC9C;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACF,EAEK,IAA4C;CAChD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACR;CACF;AAED,SAAS,EAAY,GAAmC;AAEtD,QADI,MAAc,iBAAuB,IAClC;;AAGT,SAAgB,EAAmB,EAAE,aAAU,cAAW,gBAA0B;CAClF,IAAM,IAAU,EAAY,EAAU;AACtC,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAK,WAAU,UAAW,CAAA;EAChC,MAAK;EACM;YAEX,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAQ,KAAK,MACZ,kBAAC,GAAD;IAEE,SAAQ;IACR,WAAU;IACV,eAAe,EAAS,EAAO,KAAK;cAJtC,CAME,kBAAC,EAAO,MAAR,EAAa,WAAW,UAAU,EAAO,SAAW,CAAA,EACpD,kBAAC,QAAD;KAAM,WAAU;eAAmC,EAAO;KAAa,CAAA,CAChE;MAPF,EAAO,GAOL,CACT;GACE,CAAA;EACQ,CAAA"}
@@ -31,7 +31,7 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
31
31
  let f = l?.recentActivities ?? [];
32
32
  return /* @__PURE__ */ r(e, {
33
33
  title: "Recent Activity",
34
- icon: /* @__PURE__ */ r(t, { className: "h-4 w-4" }),
34
+ icon: /* @__PURE__ */ r(t, { className: "size-4" }),
35
35
  size: "large",
36
36
  isLoading: u,
37
37
  unavailable: !l,
@@ -40,7 +40,7 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
40
40
  size: "sm",
41
41
  className: "text-xs",
42
42
  onClick: () => d("/workspaces/activity"),
43
- children: ["View all ", /* @__PURE__ */ r(n, { className: "ml-1 h-3 w-3" })]
43
+ children: ["View all ", /* @__PURE__ */ r(n, { className: "ml-1 size-3" })]
44
44
  }),
45
45
  children: f.length === 0 ? /* @__PURE__ */ i("div", {
46
46
  className: "text-center py-6",
@@ -58,7 +58,7 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
58
58
  return /* @__PURE__ */ i("div", {
59
59
  className: "flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 transition-colors",
60
60
  children: [/* @__PURE__ */ r("div", {
61
- className: `rounded-full h-7 w-7 flex items-center justify-center text-xs font-bold shrink-0 ${a}`,
61
+ className: `rounded-full size-7 flex items-center justify-center text-xs font-bold shrink-0 ${a}`,
62
62
  children: n.charAt(0).toUpperCase()
63
63
  }), /* @__PURE__ */ i("div", {
64
64
  className: "min-w-0 flex-1",
@@ -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=\"h-4 w-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 h-3 w-3\" />\n </Button>\n }\n >\n {activities.length === 0 ? (\n <div className=\"text-center py-6\">\n <p className=\"text-sm text-muted-foreground\">No recent activity</p>\n <p className=\"text-xs text-muted-foreground 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 h-7 w-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-muted-foreground\">{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,WAAY,CAAA;EACtC,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,gBAAiB,CAAA,CACzC;;YAGV,EAAW,WAAW,IACrB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAgC;IAAsB,CAAA,EACnE,kBAAC,KAAD;IAAG,WAAU;cAAqC;IAE9C,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,oFAAoF;gBAE9F,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;iBAAiC;OAAY,CAAA,CACtD;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 } 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-muted-foreground\">No recent activity</p>\n <p className=\"text-xs text-muted-foreground 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-muted-foreground\">{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;cAAgC;IAAsB,CAAA,EACnE,kBAAC,KAAD;IAAG,WAAU;cAAqC;IAE9C,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;iBAAiC;OAAY,CAAA,CACtD;QACF;OAdC,EAAS,MAAM,EAchB;KAER;GACE,CAAA;EAEM,CAAA"}