@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":"WorkspacesListPage.js","names":[],"sources":["../../src/pages/WorkspacesListPage.tsx"],"sourcesContent":["import { Plus, Grid3X3, List as ListIcon, Search } from 'lucide-react';\nimport { Button, Input, Skeleton } from '@burdenoff/fe-libs/ui';\nimport { useNavigate } from 'react-router-dom';\nimport { useWorkspacesStore } from '../store/workspacesStore';\nimport { useMyWorkspaces } from '../hooks/useWorkspaces';\nimport { WorkspaceCard } from '../components/WorkspaceCard';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useDebounce } from '@burdenoff/fe-libs/shared/hooks';\nimport { PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\nimport { useState, useEffect } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport { useScopedNavigation } from '../hooks/useScopedNavigation';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\n\nexport function WorkspacesListPage() {\n useWorkspacesPageView('workspaces.list');\n const { t } = useI18n();\n\n const navigate = useNavigate();\n const { basePath = '/' } = useWorkspacesContext();\n const { withCurrentSearch } = useScopedNavigation();\n const { viewMode, setViewMode, workspaceFilters, setWorkspaceFilters } = useWorkspacesStore();\n\n // Navigate to unified workspace creation page\n const handleCreateWorkspace = () => {\n navigate(withCurrentSearch(`${basePath}/new`));\n };\n\n const [searchValue, setSearchValue] = useState(workspaceFilters.search || '');\n const debouncedSearch = useDebounce(searchValue, 500);\n\n // Update filters when debounced search changes\n useEffect(() => {\n if (debouncedSearch !== workspaceFilters.search) {\n setWorkspaceFilters({ search: debouncedSearch });\n }\n }, [debouncedSearch, workspaceFilters.search, setWorkspaceFilters]);\n\n const { data: rawData, isLoading, error } = useMyWorkspaces();\n\n // Client-side search filtering (myWorkspaces doesn't accept filter args)\n const data = rawData\n ? {\n ...rawData,\n items: debouncedSearch\n ? rawData.items.filter((ws) =>\n ws.name.toLowerCase().includes(debouncedSearch.toLowerCase())\n )\n : rawData.items,\n total: debouncedSearch\n ? rawData.items.filter((ws) =>\n ws.name.toLowerCase().includes(debouncedSearch.toLowerCase())\n ).length\n : rawData.total,\n }\n : undefined;\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchValue(e.target.value);\n };\n\n if (error) {\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n <div className=\"flex flex-col items-center justify-center py-12\">\n <p className=\"text-destructive text-lg font-semibold\">\n {tWithFallback(t, 'workspacesList.loadError', 'Error loading workspaces')}\n </p>\n <p className=\"text-muted-foreground text-sm mt-2\">\n {error instanceof Error\n ? error.message\n : tWithFallback(t, 'workspacesList.unknownError', 'Unknown error')}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header with title + actions */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n <div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tWithFallback(t, 'workspacesList.title', 'Workspaces')}\n </h1>\n <p className=\"text-sm sm:text-base text-muted-foreground\">\n {tWithFallback(t, 'workspacesList.description', 'Manage and organize your workspaces')}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n {/* View mode toggle */}\n <Button\n variant={viewMode === 'grid' ? 'default' : 'outline'}\n size=\"icon\"\n onClick={() => setViewMode('grid')}\n className=\"hidden sm:flex\"\n aria-label={tWithFallback(\n t,\n 'workspacesList.gridViewAriaLabel',\n 'Show workspaces in grid view'\n )}\n title={tWithFallback(t, 'workspacesList.gridViewTitle', 'Grid view')}\n >\n <Grid3X3 size={20} />\n </Button>\n <Button\n variant={viewMode === 'list' ? 'default' : 'outline'}\n size=\"icon\"\n onClick={() => setViewMode('list')}\n className=\"hidden sm:flex\"\n aria-label={tWithFallback(\n t,\n 'workspacesList.listViewAriaLabel',\n 'Show workspaces in list view'\n )}\n title={tWithFallback(t, 'workspacesList.listViewTitle', 'List view')}\n >\n <ListIcon size={20} />\n </Button>\n {/* Create button - requires workspace:create permission */}\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.WORKSPACE_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'workspacesList.createDeniedTooltip',\n \"You don't have permission to create workspaces\"\n )}\n >\n <Button onClick={handleCreateWorkspace} className=\"gap-2\">\n <Plus size={20} />\n <span className=\"hidden sm:inline\">\n {tWithFallback(t, 'workspacesList.createButton', 'Create Workspace')}\n </span>\n <span className=\"sm:hidden\">\n {tWithFallback(t, 'workspacesList.createButtonShort', 'Create')}\n </span>\n </Button>\n </PermissionButton>\n </div>\n </div>\n\n {/* Search */}\n <div className=\"relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground\"\n size={20}\n />\n <Input\n placeholder={tWithFallback(t, 'workspacesList.searchPlaceholder', 'Search workspaces...')}\n value={searchValue}\n onChange={handleSearchChange}\n className=\"pl-[3.25rem]\"\n />\n </div>\n\n {/* Content */}\n {isLoading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"space-y-3 p-6 border rounded-lg\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"h-12 w-12 rounded-lg\" />\n <div className=\"space-y-2 flex-1\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n </div>\n <Skeleton className=\"h-3 w-1/3\" />\n </div>\n ))}\n </div>\n ) : data?.items.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"rounded-full bg-muted p-6 mb-4\">\n <Grid3X3 size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'workspacesList.emptyTitle', 'No workspaces found')}\n </h3>\n <p className=\"text-muted-foreground mb-4 max-w-sm\">\n {workspaceFilters.search\n ? tWithFallback(\n t,\n 'workspacesList.emptySearchHint',\n 'Try adjusting your search criteria'\n )\n : tWithFallback(\n t,\n 'workspacesList.emptyCreateHint',\n 'Get started by creating your first workspace'\n )}\n </p>\n {!workspaceFilters.search && (\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.WORKSPACE_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'workspacesList.createDeniedTooltip',\n \"You don't have permission to create workspaces\"\n )}\n >\n <Button onClick={handleCreateWorkspace} className=\"gap-2\">\n <Plus size={20} />\n {tWithFallback(\n t,\n 'workspacesList.createFirstButton',\n 'Create Your First Workspace'\n )}\n </Button>\n </PermissionButton>\n )}\n </div>\n ) : (\n <>\n {/* View */}\n {viewMode === 'list' ? (\n <div className=\"space-y-3\">\n {data?.items.map((workspace) => (\n <WorkspaceCard key={workspace.id} workspace={workspace} />\n ))}\n </div>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {data?.items.map((workspace) => (\n <WorkspaceCard key={workspace.id} workspace={workspace} />\n ))}\n </div>\n )}\n\n {/* Pagination info */}\n {data && data.total > 0 && (\n <div className=\"flex items-center justify-between text-sm text-muted-foreground\">\n <p>\n {tWithFallback(t, 'workspacesList.showing', 'Showing')} {data.items.length}{' '}\n {tWithFallback(t, 'workspacesList.of', 'of')} {data.total}{' '}\n {data.total !== 1\n ? tWithFallback(t, 'workspacesList.workspaces', 'workspaces')\n : tWithFallback(t, 'workspacesList.workspace', 'workspace')}\n </p>\n {data.hasMore && (\n <p className=\"text-xs\">\n {tWithFallback(\n t,\n 'workspacesList.moreAvailable',\n 'More workspaces available - pagination coming soon'\n )}\n </p>\n )}\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"WorkspacesListPage.js","names":[],"sources":["../../src/pages/WorkspacesListPage.tsx"],"sourcesContent":["import { Plus, Grid3X3, List as ListIcon, Search } from 'lucide-react';\nimport { Button, Input, Skeleton } from '@burdenoff/fe-libs/ui';\nimport { useNavigate } from 'react-router-dom';\nimport { useWorkspacesStore } from '../store/workspacesStore';\nimport { useMyWorkspaces } from '../hooks/useWorkspaces';\nimport { WorkspaceCard } from '../components/WorkspaceCard';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useDebounce } from '@burdenoff/fe-libs/shared/hooks';\nimport { PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\nimport { useState, useEffect } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport { useScopedNavigation } from '../hooks/useScopedNavigation';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\n\nexport function WorkspacesListPage() {\n useWorkspacesPageView('workspaces.list');\n const { t } = useI18n();\n\n const navigate = useNavigate();\n const { basePath = '/' } = useWorkspacesContext();\n const { withCurrentSearch } = useScopedNavigation();\n const { viewMode, setViewMode, workspaceFilters, setWorkspaceFilters } = useWorkspacesStore();\n\n // Navigate to unified workspace creation page\n const handleCreateWorkspace = () => {\n navigate(withCurrentSearch(`${basePath}/new`));\n };\n\n const [searchValue, setSearchValue] = useState(workspaceFilters.search || '');\n const debouncedSearch = useDebounce(searchValue, 500);\n\n // Update filters when debounced search changes\n useEffect(() => {\n if (debouncedSearch !== workspaceFilters.search) {\n setWorkspaceFilters({ search: debouncedSearch });\n }\n }, [debouncedSearch, workspaceFilters.search, setWorkspaceFilters]);\n\n const { data: rawData, isLoading, error } = useMyWorkspaces();\n\n // Client-side search filtering (myWorkspaces doesn't accept filter args)\n const data = rawData\n ? {\n ...rawData,\n items: debouncedSearch\n ? rawData.items.filter((ws) =>\n ws.name.toLowerCase().includes(debouncedSearch.toLowerCase())\n )\n : rawData.items,\n total: debouncedSearch\n ? rawData.items.filter((ws) =>\n ws.name.toLowerCase().includes(debouncedSearch.toLowerCase())\n ).length\n : rawData.total,\n }\n : undefined;\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchValue(e.target.value);\n };\n\n if (error) {\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n <div className=\"flex flex-col items-center justify-center py-12\">\n <p className=\"text-destructive text-lg font-semibold\">\n {tWithFallback(t, 'workspacesList.loadError', 'Error loading workspaces')}\n </p>\n <p className=\"text-muted-foreground text-sm mt-2\">\n {error instanceof Error\n ? error.message\n : tWithFallback(t, 'workspacesList.unknownError', 'Unknown error')}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header with title + actions */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n <div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tWithFallback(t, 'workspacesList.title', 'Workspaces')}\n </h1>\n <p className=\"text-sm sm:text-base text-muted-foreground\">\n {tWithFallback(t, 'workspacesList.description', 'Manage and organize your workspaces')}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n {/* View mode toggle */}\n <Button\n variant={viewMode === 'grid' ? 'default' : 'outline'}\n size=\"icon\"\n onClick={() => setViewMode('grid')}\n className=\"hidden sm:flex\"\n aria-label={tWithFallback(\n t,\n 'workspacesList.gridViewAriaLabel',\n 'Show workspaces in grid view'\n )}\n title={tWithFallback(t, 'workspacesList.gridViewTitle', 'Grid view')}\n >\n <Grid3X3 size={20} />\n </Button>\n <Button\n variant={viewMode === 'list' ? 'default' : 'outline'}\n size=\"icon\"\n onClick={() => setViewMode('list')}\n className=\"hidden sm:flex\"\n aria-label={tWithFallback(\n t,\n 'workspacesList.listViewAriaLabel',\n 'Show workspaces in list view'\n )}\n title={tWithFallback(t, 'workspacesList.listViewTitle', 'List view')}\n >\n <ListIcon size={20} />\n </Button>\n {/* Create button - requires workspace:create permission */}\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.WORKSPACE_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'workspacesList.createDeniedTooltip',\n \"You don't have permission to create workspaces\"\n )}\n >\n <Button onClick={handleCreateWorkspace} className=\"gap-2\">\n <Plus size={20} />\n <span className=\"hidden sm:inline\">\n {tWithFallback(t, 'workspacesList.createButton', 'Create Workspace')}\n </span>\n <span className=\"sm:hidden\">\n {tWithFallback(t, 'workspacesList.createButtonShort', 'Create')}\n </span>\n </Button>\n </PermissionButton>\n </div>\n </div>\n\n {/* Search */}\n <div className=\"relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground\"\n size={20}\n />\n <Input\n placeholder={tWithFallback(t, 'workspacesList.searchPlaceholder', 'Search workspaces...')}\n value={searchValue}\n onChange={handleSearchChange}\n className=\"pl-[3.25rem]\"\n />\n </div>\n\n {/* Content */}\n {isLoading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"space-y-3 p-6 border rounded-lg\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"size-12 rounded-lg\" />\n <div className=\"space-y-2 flex-1\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n </div>\n <Skeleton className=\"h-3 w-1/3\" />\n </div>\n ))}\n </div>\n ) : data?.items.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"rounded-full bg-muted p-6 mb-4\">\n <Grid3X3 size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'workspacesList.emptyTitle', 'No workspaces found')}\n </h3>\n <p className=\"text-muted-foreground mb-4 max-w-sm\">\n {workspaceFilters.search\n ? tWithFallback(\n t,\n 'workspacesList.emptySearchHint',\n 'Try adjusting your search criteria'\n )\n : tWithFallback(\n t,\n 'workspacesList.emptyCreateHint',\n 'Get started by creating your first workspace'\n )}\n </p>\n {!workspaceFilters.search && (\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.WORKSPACE_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'workspacesList.createDeniedTooltip',\n \"You don't have permission to create workspaces\"\n )}\n >\n <Button onClick={handleCreateWorkspace} className=\"gap-2\">\n <Plus size={20} />\n {tWithFallback(\n t,\n 'workspacesList.createFirstButton',\n 'Create Your First Workspace'\n )}\n </Button>\n </PermissionButton>\n )}\n </div>\n ) : (\n <>\n {/* View */}\n {viewMode === 'list' ? (\n <div className=\"space-y-3\">\n {data?.items.map((workspace) => (\n <WorkspaceCard key={workspace.id} workspace={workspace} />\n ))}\n </div>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {data?.items.map((workspace) => (\n <WorkspaceCard key={workspace.id} workspace={workspace} />\n ))}\n </div>\n )}\n\n {/* Pagination info */}\n {data && data.total > 0 && (\n <div className=\"flex items-center justify-between text-sm text-muted-foreground\">\n <p>\n {tWithFallback(t, 'workspacesList.showing', 'Showing')} {data.items.length}{' '}\n {tWithFallback(t, 'workspacesList.of', 'of')} {data.total}{' '}\n {data.total !== 1\n ? tWithFallback(t, 'workspacesList.workspaces', 'workspaces')\n : tWithFallback(t, 'workspacesList.workspace', 'workspace')}\n </p>\n {data.hasMore && (\n <p className=\"text-xs\">\n {tWithFallback(\n t,\n 'workspacesList.moreAvailable',\n 'More workspaces available - pagination coming soon'\n )}\n </p>\n )}\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,SAAgB,IAAqB;AACnC,GAAsB,kBAAkB;CACxC,IAAM,EAAE,SAAM,GAAS,EAEjB,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAsB,EAC3C,EAAE,yBAAsB,GAAqB,EAC7C,EAAE,aAAU,gBAAa,qBAAkB,2BAAwB,GAAoB,EAGvF,UAA8B;AAClC,IAAS,EAAkB,GAAG,EAAS,MAAM,CAAC;IAG1C,CAAC,GAAa,KAAkB,EAAS,EAAiB,UAAU,GAAG,EACvE,IAAkB,EAAY,GAAa,IAAI;AAGrD,SAAgB;AACd,EAAI,MAAoB,EAAiB,UACvC,EAAoB,EAAE,QAAQ,GAAiB,CAAC;IAEjD;EAAC;EAAiB,EAAiB;EAAQ;EAAoB,CAAC;CAEnE,IAAM,EAAE,MAAM,GAAS,cAAW,aAAU,GAAiB,EAGvD,IAAO,IACT;EACE,GAAG;EACH,OAAO,IACH,EAAQ,MAAM,QAAQ,MACpB,EAAG,KAAK,aAAa,CAAC,SAAS,EAAgB,aAAa,CAAC,CAC9D,GACD,EAAQ;EACZ,OAAO,IACH,EAAQ,MAAM,QAAQ,MACpB,EAAG,KAAK,aAAa,CAAC,SAAS,EAAgB,aAAa,CAAC,CAC9D,CAAC,SACF,EAAQ;EACb,GACD,KAAA;AAuBJ,QAjBI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cACV,EAAc,GAAG,4BAA4B,2BAA2B;IACvE,CAAA,EACJ,kBAAC,KAAD;IAAG,WAAU;cACV,aAAiB,QACd,EAAM,UACN,EAAc,GAAG,+BAA+B,gBAAgB;IAClE,CAAA,CACA;;EACF,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAc,GAAG,wBAAwB,aAAa;KACpD,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EAAc,GAAG,8BAA8B,sCAAsC;KACpF,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf;MAEE,kBAAC,GAAD;OACE,SAAS,MAAa,SAAS,YAAY;OAC3C,MAAK;OACL,eAAe,EAAY,OAAO;OAClC,WAAU;OACV,cAAY,EACV,GACA,oCACA,+BACD;OACD,OAAO,EAAc,GAAG,gCAAgC,YAAY;iBAEpE,kBAAC,GAAD,EAAS,MAAM,IAAM,CAAA;OACd,CAAA;MACT,kBAAC,GAAD;OACE,SAAS,MAAa,SAAS,YAAY;OAC3C,MAAK;OACL,eAAe,EAAY,OAAO;OAClC,WAAU;OACV,cAAY,EACV,GACA,oCACA,+BACD;OACD,OAAO,EAAc,GAAG,gCAAgC,YAAY;iBAEpE,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;OACf,CAAA;MAET,kBAAC,GAAD;OACE,YAAY,EAAsB;OAClC,gBAAe;OACf,eAAe,EACb,GACA,sCACA,iDACD;iBAED,kBAAC,GAAD;QAAQ,SAAS;QAAuB,WAAU;kBAAlD;SACE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;SAClB,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAc,GAAG,+BAA+B,mBAAmB;UAC/D,CAAA;SACP,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAc,GAAG,oCAAoC,SAAS;UAC1D,CAAA;SACA;;OACQ,CAAA;MACf;OACF;;GAGN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,WAAU;KACV,MAAM;KACN,CAAA,EACF,kBAAC,GAAD;KACE,aAAa,EAAc,GAAG,oCAAoC,uBAAuB;KACzF,OAAO;KACP,WA/FoB,MAA2C;AACrE,QAAe,EAAE,OAAO,MAAM;;KA+FxB,WAAU;KACV,CAAA,CACE;;GAGL,IACC,kBAAC,OAAD;IAAK,WAAU;cACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,OAAD;KAAa,WAAU;eAAvB,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAU,WAAU,sBAAuB,CAAA,EAC3C,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,EAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,CAC9B;SACF;SACN,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,CAC9B;OATI,EASJ,CACN;IACE,CAAA,GACJ,GAAM,MAAM,WAAW,IACzB,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAS,MAAM;OAAI,WAAU;OAA0B,CAAA;MACnD,CAAA;KACN,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAc,GAAG,6BAA6B,sBAAsB;MAClE,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAiB,SACd,EACE,GACA,kCACA,qCACD,GACD,EACE,GACA,kCACA,+CACD;MACH,CAAA;KACH,CAAC,EAAiB,UACjB,kBAAC,GAAD;MACE,YAAY,EAAsB;MAClC,gBAAe;MACf,eAAe,EACb,GACA,sCACA,iDACD;gBAED,kBAAC,GAAD;OAAQ,SAAS;OAAuB,WAAU;iBAAlD,CACE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EACC,GACA,oCACA,8BACD,CACM;;MACQ,CAAA;KAEjB;QAEN,kBAAA,GAAA,EAAA,UAAA,CAEG,MAAa,SACZ,kBAAC,OAAD;IAAK,WAAU;cACZ,GAAM,MAAM,KAAK,MAChB,kBAAC,GAAD,EAA6C,cAAa,EAAtC,EAAU,GAA4B,CAC1D;IACE,CAAA,GAEN,kBAAC,OAAD;IAAK,WAAU;cACZ,GAAM,MAAM,KAAK,MAChB,kBAAC,GAAD,EAA6C,cAAa,EAAtC,EAAU,GAA4B,CAC1D;IACE,CAAA,EAIP,KAAQ,EAAK,QAAQ,KACpB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD,EAAA,UAAA;KACG,EAAc,GAAG,0BAA0B,UAAU;KAAC;KAAE,EAAK,MAAM;KAAQ;KAC3E,EAAc,GAAG,qBAAqB,KAAK;KAAC;KAAE,EAAK;KAAO;KAC1D,EAAK,UAAU,IAEZ,EAAc,GAAG,4BAA4B,YAAY,GADzD,EAAc,GAAG,6BAA6B,aAAa;KAE7D,EAAA,CAAA,EACH,EAAK,WACJ,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,GACA,gCACA,qDACD;KACC,CAAA,CAEF;MAEP,EAAA,CAAA;GAED"}
@@ -1,24 +1,24 @@
1
1
  import { tWithFallback as e } from "../../utils/i18n.js";
2
- import { DEFAULT_DASHBOARD_WIDGETS as t, WIDGET_DEFINITIONS as n } from "./config.js";
3
- import { nativeImpact as r } from "../../utils/nativeBridge.js";
4
- import { useCallback as i, useEffect as a, useState as o } from "react";
5
- import { ArrowDown as s, ArrowUp as c, GripVertical as l, Loader2 as u, RotateCcw as d, Save as f } from "lucide-react";
6
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
7
- import { Badge as h, Button as g, Separator as _, Sheet as v, SheetContent as y, SheetDescription as b, SheetFooter as x, SheetHeader as S, SheetTitle as C, Switch as w } from "@burdenoff/fe-libs/ui";
8
- import { useI18n as T } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
2
+ import { DEFAULT_DASHBOARD_WIDGETS as t, DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT as n, WIDGET_DEFINITIONS as r, isWidgetAvailable as i } from "./config.js";
3
+ import { nativeImpact as a } from "../../utils/nativeBridge.js";
4
+ import { useCallback as o, useEffect as s, useState as c } from "react";
5
+ import { ArrowDown as l, ArrowUp as u, GripVertical as d, Loader2 as f, RotateCcw as p, Save as m } from "lucide-react";
6
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
7
+ import { Badge as _, Button as v, Separator as y, Sheet as b, SheetContent as x, SheetDescription as S, SheetFooter as C, SheetHeader as w, SheetTitle as T, Switch as E } from "@burdenoff/fe-libs/ui";
8
+ import { useI18n as D } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
9
  //#region src/pages/dashboard/DashboardCustomizer.tsx
10
- function E({ open: E, onOpenChange: D, widgets: O, onSave: k, isSaving: A }) {
11
- let { t: j } = T(), [M, N] = o(O), [P, F] = o(!1);
12
- a(() => {
13
- E && (N([...O]), F(!1));
14
- }, [E, O]);
15
- let I = i((e) => {
16
- N((t) => t.map((t) => t.widgetId === e ? {
10
+ function O({ open: O, onOpenChange: k, widgets: A, onSave: j, isSaving: M, productId: N = "workspaces" }) {
11
+ let { t: P } = D(), [F, I] = c(A), [L, R] = c(!1);
12
+ s(() => {
13
+ O && (I([...A]), R(!1));
14
+ }, [O, A]);
15
+ let z = o((e) => {
16
+ I((t) => t.map((t) => t.widgetId === e ? {
17
17
  ...t,
18
18
  enabled: !t.enabled
19
- } : t)), F(!0);
20
- }, []), L = i((e, t) => {
21
- N((n) => {
19
+ } : t)), R(!0);
20
+ }, []), B = o((e, t) => {
21
+ I((n) => {
22
22
  let r = [...n].sort((e, t) => e.order - t.order), i = r.findIndex((t) => t.widgetId === e);
23
23
  if (i < 0) return n;
24
24
  let a = t === "up" ? i - 1 : i + 1;
@@ -31,97 +31,97 @@ function E({ open: E, onOpenChange: D, widgets: O, onSave: k, isSaving: A }) {
31
31
  ...r[a],
32
32
  order: o
33
33
  }, r;
34
- }), F(!0);
35
- }, []), R = i(() => {
36
- N([...t]), F(!0);
37
- }, []), z = i(async () => {
38
- await k(M), F(!1), D(!1);
34
+ }), R(!0);
35
+ }, []), V = o(() => {
36
+ I([...n[N] ?? t]), R(!0);
37
+ }, [N]), H = o(async () => {
38
+ await j(F), R(!1), k(!1);
39
39
  }, [
40
- M,
41
- k,
42
- D
43
- ]), B = [...M].sort((e, t) => e.order - t.order);
44
- return /* @__PURE__ */ p(v, {
45
- open: E,
46
- onOpenChange: D,
47
- children: /* @__PURE__ */ m(y, {
40
+ F,
41
+ j,
42
+ k
43
+ ]), U = [...F].sort((e, t) => e.order - t.order);
44
+ return /* @__PURE__ */ h(b, {
45
+ open: O,
46
+ onOpenChange: k,
47
+ children: /* @__PURE__ */ g(x, {
48
48
  className: "w-full sm:max-w-md overflow-y-auto",
49
49
  side: "right",
50
50
  children: [
51
- /* @__PURE__ */ m(S, { children: [/* @__PURE__ */ p(C, { children: e(j, "dashboardCustomizer.title", "Customize Dashboard") }), /* @__PURE__ */ p(b, { children: e(j, "dashboardCustomizer.description", "Toggle widgets on or off and reorder them to personalize your dashboard.") })] }),
52
- /* @__PURE__ */ p("div", {
51
+ /* @__PURE__ */ g(w, { children: [/* @__PURE__ */ h(T, { children: e(P, "dashboardCustomizer.title", "Customize Dashboard") }), /* @__PURE__ */ h(S, { children: e(P, "dashboardCustomizer.description", "Toggle widgets on or off and reorder them to personalize your dashboard.") })] }),
52
+ /* @__PURE__ */ h("div", {
53
53
  className: "py-4 space-y-1",
54
- children: B.map((e, t) => {
55
- let i = n[e.widgetId];
56
- return i ? /* @__PURE__ */ m("div", {
54
+ children: U.map((e, t) => {
55
+ let n = r[e.widgetId];
56
+ return !n || !i(n, N) ? null : /* @__PURE__ */ g("div", {
57
57
  className: `flex items-center gap-3 p-3 rounded-lg border transition-colors ${e.enabled ? "border-border-default bg-bg-surface" : "border-transparent bg-muted/30 opacity-60"}`,
58
58
  children: [
59
- /* @__PURE__ */ p(l, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
60
- /* @__PURE__ */ m("div", {
59
+ /* @__PURE__ */ h(d, { className: "size-4 text-muted-foreground shrink-0" }),
60
+ /* @__PURE__ */ g("div", {
61
61
  className: "flex-1 min-w-0",
62
- children: [/* @__PURE__ */ m("div", {
62
+ children: [/* @__PURE__ */ g("div", {
63
63
  className: "flex items-center gap-2",
64
- children: [/* @__PURE__ */ p("span", {
64
+ children: [/* @__PURE__ */ h("span", {
65
65
  className: "text-sm font-medium text-text-primary",
66
- children: i.title
67
- }), /* @__PURE__ */ p(h, {
66
+ children: n.title
67
+ }), /* @__PURE__ */ h(_, {
68
68
  variant: "outline",
69
69
  className: "text-[10px]",
70
- children: i.defaultSize
70
+ children: n.defaultSize
71
71
  })]
72
- }), /* @__PURE__ */ p("p", {
72
+ }), /* @__PURE__ */ h("p", {
73
73
  className: "text-xs text-muted-foreground truncate",
74
- children: i.description
74
+ children: n.description
75
75
  })]
76
76
  }),
77
- /* @__PURE__ */ m("div", {
77
+ /* @__PURE__ */ g("div", {
78
78
  className: "flex items-center gap-1 shrink-0",
79
79
  children: [
80
- /* @__PURE__ */ p(g, {
80
+ /* @__PURE__ */ h(v, {
81
81
  variant: "ghost",
82
82
  size: "sm",
83
- className: "h-7 w-7 p-0",
83
+ className: "size-7 p-0",
84
84
  disabled: t === 0,
85
- onClick: () => L(e.widgetId, "up"),
86
- children: /* @__PURE__ */ p(c, { className: "h-3 w-3" })
85
+ onClick: () => B(e.widgetId, "up"),
86
+ children: /* @__PURE__ */ h(u, { className: "size-3" })
87
87
  }),
88
- /* @__PURE__ */ p(g, {
88
+ /* @__PURE__ */ h(v, {
89
89
  variant: "ghost",
90
90
  size: "sm",
91
- className: "h-7 w-7 p-0",
92
- disabled: t === B.length - 1,
93
- onClick: () => L(e.widgetId, "down"),
94
- children: /* @__PURE__ */ p(s, { className: "h-3 w-3" })
91
+ className: "size-7 p-0",
92
+ disabled: t === U.length - 1,
93
+ onClick: () => B(e.widgetId, "down"),
94
+ children: /* @__PURE__ */ h(l, { className: "size-3" })
95
95
  }),
96
- /* @__PURE__ */ p(w, {
96
+ /* @__PURE__ */ h(E, {
97
97
  checked: e.enabled,
98
98
  onCheckedChange: () => {
99
- r("medium"), I(e.widgetId);
99
+ a("medium"), z(e.widgetId);
100
100
  },
101
- disabled: !i.removable,
101
+ disabled: !n.removable,
102
102
  className: "ml-1"
103
103
  })
104
104
  ]
105
105
  })
106
106
  ]
107
- }, e.widgetId) : null;
107
+ }, e.widgetId);
108
108
  })
109
109
  }),
110
- /* @__PURE__ */ p(_, {}),
111
- /* @__PURE__ */ m(x, {
110
+ /* @__PURE__ */ h(y, {}),
111
+ /* @__PURE__ */ g(C, {
112
112
  className: "flex-row gap-2 pt-4",
113
- children: [/* @__PURE__ */ m(g, {
113
+ children: [/* @__PURE__ */ g(v, {
114
114
  variant: "outline",
115
115
  size: "sm",
116
- onClick: R,
116
+ onClick: V,
117
117
  className: "flex-1",
118
- children: [/* @__PURE__ */ p(d, { className: "h-3 w-3 mr-1.5" }), e(j, "dashboardCustomizer.resetToDefaults", "Reset to defaults")]
119
- }), /* @__PURE__ */ m(g, {
118
+ children: [/* @__PURE__ */ h(p, { className: "size-3 mr-1.5" }), e(P, "dashboardCustomizer.resetToDefaults", "Reset to defaults")]
119
+ }), /* @__PURE__ */ g(v, {
120
120
  size: "sm",
121
- onClick: z,
122
- disabled: !P || A,
121
+ onClick: H,
122
+ disabled: !L || M,
123
123
  className: "flex-1",
124
- children: [A ? /* @__PURE__ */ p(u, { className: "h-3 w-3 mr-1.5 animate-spin" }) : /* @__PURE__ */ p(f, { className: "h-3 w-3 mr-1.5" }), e(j, "dashboardCustomizer.saveLayout", "Save layout")]
124
+ children: [M ? /* @__PURE__ */ h(f, { className: "size-3 mr-1.5 animate-spin" }) : /* @__PURE__ */ h(m, { className: "size-3 mr-1.5" }), e(P, "dashboardCustomizer.saveLayout", "Save layout")]
125
125
  })]
126
126
  })
127
127
  ]
@@ -129,6 +129,6 @@ function E({ open: E, onOpenChange: D, widgets: O, onSave: k, isSaving: A }) {
129
129
  });
130
130
  }
131
131
  //#endregion
132
- export { E as DashboardCustomizer };
132
+ export { O as DashboardCustomizer };
133
133
 
134
134
  //# sourceMappingURL=DashboardCustomizer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardCustomizer.js","names":[],"sources":["../../../src/pages/dashboard/DashboardCustomizer.tsx"],"sourcesContent":["/**\n * DashboardCustomizer — Sheet overlay for customizing dashboard widgets.\n *\n * Allows users to toggle widgets on/off, reorder them, and save their layout.\n */\nimport { useState, useCallback, useEffect } from 'react';\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetFooter,\n Button,\n Switch,\n Badge,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowUp, ArrowDown, RotateCcw, Save, Loader2, GripVertical } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig } from './types';\nimport { WIDGET_DEFINITIONS, DEFAULT_DASHBOARD_WIDGETS } from './config';\nimport { nativeImpact } from '../../utils/nativeBridge';\n\ninterface DashboardCustomizerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n widgets: WidgetConfig[];\n onSave: (widgets: WidgetConfig[]) => Promise<void>;\n isSaving: boolean;\n}\n\nexport function DashboardCustomizer({\n open,\n onOpenChange,\n widgets,\n onSave,\n isSaving,\n}: DashboardCustomizerProps) {\n const { t } = useI18n();\n\n const [localWidgets, setLocalWidgets] = useState<WidgetConfig[]>(widgets);\n const [hasChanges, setHasChanges] = useState(false);\n\n // Sync local state when sheet opens or widgets prop changes while open\n useEffect(() => {\n if (open) {\n setLocalWidgets([...widgets]);\n setHasChanges(false);\n }\n }, [open, widgets]);\n\n const toggleWidget = useCallback((widgetId: string) => {\n setLocalWidgets((prev) =>\n prev.map((w) => (w.widgetId === widgetId ? { ...w, enabled: !w.enabled } : w))\n );\n setHasChanges(true);\n }, []);\n\n const moveWidget = useCallback((widgetId: string, direction: 'up' | 'down') => {\n setLocalWidgets((prev) => {\n const sorted = [...prev].sort((a, b) => a.order - b.order);\n const idx = sorted.findIndex((w) => w.widgetId === widgetId);\n if (idx < 0) return prev;\n\n const swapIdx = direction === 'up' ? idx - 1 : idx + 1;\n if (swapIdx < 0 || swapIdx >= sorted.length) return prev;\n\n // Swap orders\n const tempOrder = sorted[idx].order;\n sorted[idx] = { ...sorted[idx], order: sorted[swapIdx].order };\n sorted[swapIdx] = { ...sorted[swapIdx], order: tempOrder };\n\n return sorted;\n });\n setHasChanges(true);\n }, []);\n\n const resetToDefaults = useCallback(() => {\n setLocalWidgets([...DEFAULT_DASHBOARD_WIDGETS]);\n setHasChanges(true);\n }, []);\n\n const handleSave = useCallback(async () => {\n await onSave(localWidgets);\n setHasChanges(false);\n onOpenChange(false);\n }, [localWidgets, onSave, onOpenChange]);\n\n const sorted = [...localWidgets].sort((a, b) => a.order - b.order);\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent className=\"w-full sm:max-w-md overflow-y-auto\" side=\"right\">\n <SheetHeader>\n <SheetTitle>\n {tWithFallback(t, 'dashboardCustomizer.title', 'Customize Dashboard')}\n </SheetTitle>\n <SheetDescription>\n {tWithFallback(\n t,\n 'dashboardCustomizer.description',\n 'Toggle widgets on or off and reorder them to personalize your dashboard.'\n )}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"py-4 space-y-1\">\n {sorted.map((widget, idx) => {\n const definition = WIDGET_DEFINITIONS[widget.widgetId];\n if (!definition) return null;\n\n return (\n <div\n key={widget.widgetId}\n className={`flex items-center gap-3 p-3 rounded-lg border transition-colors ${\n widget.enabled\n ? 'border-border-default bg-bg-surface'\n : 'border-transparent bg-muted/30 opacity-60'\n }`}\n >\n <GripVertical className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {definition.title}\n </span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {definition.defaultSize}\n </Badge>\n </div>\n <p className=\"text-xs text-muted-foreground truncate\">{definition.description}</p>\n </div>\n\n <div className=\"flex items-center gap-1 shrink-0\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0\"\n disabled={idx === 0}\n onClick={() => moveWidget(widget.widgetId, 'up')}\n >\n <ArrowUp className=\"h-3 w-3\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0\"\n disabled={idx === sorted.length - 1}\n onClick={() => moveWidget(widget.widgetId, 'down')}\n >\n <ArrowDown className=\"h-3 w-3\" />\n </Button>\n <Switch\n checked={widget.enabled}\n onCheckedChange={() => {\n void nativeImpact('medium');\n toggleWidget(widget.widgetId);\n }}\n disabled={!definition.removable}\n className=\"ml-1\"\n />\n </div>\n </div>\n );\n })}\n </div>\n\n <Separator />\n\n <SheetFooter className=\"flex-row gap-2 pt-4\">\n <Button variant=\"outline\" size=\"sm\" onClick={resetToDefaults} className=\"flex-1\">\n <RotateCcw className=\"h-3 w-3 mr-1.5\" />\n {tWithFallback(t, 'dashboardCustomizer.resetToDefaults', 'Reset to defaults')}\n </Button>\n <Button\n size=\"sm\"\n onClick={handleSave}\n disabled={!hasChanges || isSaving}\n className=\"flex-1\"\n >\n {isSaving ? (\n <Loader2 className=\"h-3 w-3 mr-1.5 animate-spin\" />\n ) : (\n <Save className=\"h-3 w-3 mr-1.5\" />\n )}\n {tWithFallback(t, 'dashboardCustomizer.saveLayout', 'Save layout')}\n </Button>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DashboardCustomizer.js","names":[],"sources":["../../../src/pages/dashboard/DashboardCustomizer.tsx"],"sourcesContent":["/**\n * DashboardCustomizer — Sheet overlay for customizing dashboard widgets.\n *\n * Allows users to toggle widgets on/off, reorder them, and save their layout.\n */\nimport { useState, useCallback, useEffect } from 'react';\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetFooter,\n Button,\n Switch,\n Badge,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowUp, ArrowDown, RotateCcw, Save, Loader2, GripVertical } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig } from './types';\nimport {\n WIDGET_DEFINITIONS,\n DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT,\n DEFAULT_DASHBOARD_WIDGETS,\n isWidgetAvailable,\n} from './config';\nimport { nativeImpact } from '../../utils/nativeBridge';\n\ninterface DashboardCustomizerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n widgets: WidgetConfig[];\n onSave: (widgets: WidgetConfig[]) => Promise<void>;\n isSaving: boolean;\n productId?: string;\n}\n\nexport function DashboardCustomizer({\n open,\n onOpenChange,\n widgets,\n onSave,\n isSaving,\n productId = 'workspaces',\n}: DashboardCustomizerProps) {\n const { t } = useI18n();\n\n const [localWidgets, setLocalWidgets] = useState<WidgetConfig[]>(widgets);\n const [hasChanges, setHasChanges] = useState(false);\n\n // Sync local state when sheet opens or widgets prop changes while open\n useEffect(() => {\n if (open) {\n setLocalWidgets([...widgets]);\n setHasChanges(false);\n }\n }, [open, widgets]);\n\n const toggleWidget = useCallback((widgetId: string) => {\n setLocalWidgets((prev) =>\n prev.map((w) => (w.widgetId === widgetId ? { ...w, enabled: !w.enabled } : w))\n );\n setHasChanges(true);\n }, []);\n\n const moveWidget = useCallback((widgetId: string, direction: 'up' | 'down') => {\n setLocalWidgets((prev) => {\n const sorted = [...prev].sort((a, b) => a.order - b.order);\n const idx = sorted.findIndex((w) => w.widgetId === widgetId);\n if (idx < 0) return prev;\n\n const swapIdx = direction === 'up' ? idx - 1 : idx + 1;\n if (swapIdx < 0 || swapIdx >= sorted.length) return prev;\n\n // Swap orders\n const tempOrder = sorted[idx].order;\n sorted[idx] = { ...sorted[idx], order: sorted[swapIdx].order };\n sorted[swapIdx] = { ...sorted[swapIdx], order: tempOrder };\n\n return sorted;\n });\n setHasChanges(true);\n }, []);\n\n const resetToDefaults = useCallback(() => {\n const defaults = DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT[productId] ?? DEFAULT_DASHBOARD_WIDGETS;\n setLocalWidgets([...defaults]);\n setHasChanges(true);\n }, [productId]);\n\n const handleSave = useCallback(async () => {\n await onSave(localWidgets);\n setHasChanges(false);\n onOpenChange(false);\n }, [localWidgets, onSave, onOpenChange]);\n\n const sorted = [...localWidgets].sort((a, b) => a.order - b.order);\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent className=\"w-full sm:max-w-md overflow-y-auto\" side=\"right\">\n <SheetHeader>\n <SheetTitle>\n {tWithFallback(t, 'dashboardCustomizer.title', 'Customize Dashboard')}\n </SheetTitle>\n <SheetDescription>\n {tWithFallback(\n t,\n 'dashboardCustomizer.description',\n 'Toggle widgets on or off and reorder them to personalize your dashboard.'\n )}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"py-4 space-y-1\">\n {sorted.map((widget, idx) => {\n const definition = WIDGET_DEFINITIONS[widget.widgetId];\n if (!definition) return null;\n if (!isWidgetAvailable(definition, productId)) return null;\n\n return (\n <div\n key={widget.widgetId}\n className={`flex items-center gap-3 p-3 rounded-lg border transition-colors ${\n widget.enabled\n ? 'border-border-default bg-bg-surface'\n : 'border-transparent bg-muted/30 opacity-60'\n }`}\n >\n <GripVertical className=\"size-4 text-muted-foreground shrink-0\" />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {definition.title}\n </span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {definition.defaultSize}\n </Badge>\n </div>\n <p className=\"text-xs text-muted-foreground truncate\">{definition.description}</p>\n </div>\n\n <div className=\"flex items-center gap-1 shrink-0\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 p-0\"\n disabled={idx === 0}\n onClick={() => moveWidget(widget.widgetId, 'up')}\n >\n <ArrowUp className=\"size-3\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 p-0\"\n disabled={idx === sorted.length - 1}\n onClick={() => moveWidget(widget.widgetId, 'down')}\n >\n <ArrowDown className=\"size-3\" />\n </Button>\n <Switch\n checked={widget.enabled}\n onCheckedChange={() => {\n void nativeImpact('medium');\n toggleWidget(widget.widgetId);\n }}\n disabled={!definition.removable}\n className=\"ml-1\"\n />\n </div>\n </div>\n );\n })}\n </div>\n\n <Separator />\n\n <SheetFooter className=\"flex-row gap-2 pt-4\">\n <Button variant=\"outline\" size=\"sm\" onClick={resetToDefaults} className=\"flex-1\">\n <RotateCcw className=\"size-3 mr-1.5\" />\n {tWithFallback(t, 'dashboardCustomizer.resetToDefaults', 'Reset to defaults')}\n </Button>\n <Button\n size=\"sm\"\n onClick={handleSave}\n disabled={!hasChanges || isSaving}\n className=\"flex-1\"\n >\n {isSaving ? (\n <Loader2 className=\"size-3 mr-1.5 animate-spin\" />\n ) : (\n <Save className=\"size-3 mr-1.5\" />\n )}\n {tWithFallback(t, 'dashboardCustomizer.saveLayout', 'Save layout')}\n </Button>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":"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"}
@@ -1,55 +1,66 @@
1
1
  import { tWithFallback as e } from "../../utils/i18n.js";
2
- import { WelcomeWidget as t } from "./widgets/WelcomeWidget.js";
3
- import { QuickActionsWidget as n } from "./widgets/QuickActionsWidget.js";
4
- import { WorkspacesWidget as r } from "./widgets/WorkspacesWidget.js";
5
- import { ProjectsWidget as i } from "./widgets/ProjectsWidget.js";
6
- import { RecentActivityWidget as a } from "./widgets/RecentActivityWidget.js";
7
- import { UpcomingEventsWidget as o } from "./widgets/UpcomingEventsWidget.js";
8
- import { WorkflowStatsWidget as s } from "./widgets/WorkflowStatsWidget.js";
9
- import { TagCloudWidget as c } from "./widgets/TagCloudWidget.js";
10
- import { StorageWidget as l } from "./widgets/StorageWidget.js";
11
- import { GroupsWidget as u } from "./widgets/GroupsWidget.js";
12
- import { MembersWidget as d } from "./widgets/MembersWidget.js";
13
- import { SystemHealthWidget as f } from "./widgets/SystemHealthWidget.js";
14
- import { TipsWidget as p } from "./widgets/TipsWidget.js";
15
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
16
- import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
2
+ import { WIDGET_DEFINITIONS as t, isWidgetAvailable as n } from "./config.js";
3
+ import { WelcomeWidget as r } from "./widgets/WelcomeWidget.js";
4
+ import { QuickActionsWidget as i } from "./widgets/QuickActionsWidget.js";
5
+ import { WorkspacesWidget as a } from "./widgets/WorkspacesWidget.js";
6
+ import { ProjectsWidget as o } from "./widgets/ProjectsWidget.js";
7
+ import { RecentActivityWidget as s } from "./widgets/RecentActivityWidget.js";
8
+ import { UpcomingEventsWidget as c } from "./widgets/UpcomingEventsWidget.js";
9
+ import { WorkflowStatsWidget as l } from "./widgets/WorkflowStatsWidget.js";
10
+ import { TagCloudWidget as u } from "./widgets/TagCloudWidget.js";
11
+ import { StorageWidget as d } from "./widgets/StorageWidget.js";
12
+ import { GroupsWidget as f } from "./widgets/GroupsWidget.js";
13
+ import { MembersWidget as p } from "./widgets/MembersWidget.js";
14
+ import { TipsWidget as m } from "./widgets/TipsWidget.js";
15
+ import { VibesWidget as h } from "./widgets/VibesWidget.js";
16
+ import { SessionsWidget as g } from "./widgets/SessionsWidget.js";
17
+ import { AgentsWidget as _ } from "./widgets/AgentsWidget.js";
18
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
19
+ import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
17
20
  //#region src/pages/dashboard/DashboardGrid.tsx
18
- var _ = {
19
- welcome: t,
20
- quickActions: n,
21
- workspaces: r,
22
- projects: i,
23
- activity: a,
24
- calendar: o,
25
- workflows: s,
26
- tags: c,
27
- storage: l,
28
- groups: u,
29
- members: d,
30
- systemHealth: f,
31
- tips: p
21
+ var x = {
22
+ welcome: r,
23
+ quickActions: i,
24
+ workspaces: a,
25
+ projects: o,
26
+ activity: s,
27
+ calendar: c,
28
+ workflows: l,
29
+ tags: u,
30
+ storage: d,
31
+ groups: f,
32
+ members: p,
33
+ tips: m,
34
+ vibes: h,
35
+ sessions: g,
36
+ agents: _
32
37
  };
33
- function v({ widgets: t, ...n }) {
34
- let { t: r } = g(), i = t.filter((e) => e.enabled).sort((e, t) => e.order - t.order);
35
- return i.length === 0 ? /* @__PURE__ */ h("div", {
38
+ function S({ widgets: r, productId: i, ...a }) {
39
+ let { t: o } = b(), s = r.filter((e) => e.enabled).filter((e) => {
40
+ let r = t[e.widgetId];
41
+ return r ? n(r, i) : !1;
42
+ }).sort((e, t) => e.order - t.order);
43
+ return s.length === 0 ? /* @__PURE__ */ y("div", {
36
44
  className: "text-center py-12",
37
- children: [/* @__PURE__ */ m("p", {
45
+ children: [/* @__PURE__ */ v("p", {
38
46
  className: "text-lg text-muted-foreground",
39
- children: e(r, "dashboardGrid.noWidgetsEnabled", "No widgets enabled")
40
- }), /* @__PURE__ */ m("p", {
47
+ children: e(o, "dashboardGrid.noWidgetsEnabled", "No widgets enabled")
48
+ }), /* @__PURE__ */ v("p", {
41
49
  className: "text-sm text-muted-foreground mt-1",
42
- children: e(r, "dashboardGrid.noWidgetsHint", "Click \"Customize\" to add widgets to your dashboard")
50
+ children: e(o, "dashboardGrid.noWidgetsHint", "Click \"Customize\" to add widgets to your dashboard")
43
51
  })]
44
- }) : /* @__PURE__ */ m("div", {
52
+ }) : /* @__PURE__ */ v("div", {
45
53
  className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
46
- children: i.map((e) => {
47
- let t = _[e.widgetId];
48
- return t ? /* @__PURE__ */ m(t, { ...n }, e.widgetId) : null;
54
+ children: s.map((e) => {
55
+ let t = x[e.widgetId];
56
+ return t ? /* @__PURE__ */ v(t, {
57
+ productId: i,
58
+ ...a
59
+ }, e.widgetId) : null;
49
60
  })
50
61
  });
51
62
  }
52
63
  //#endregion
53
- export { v as DashboardGrid };
64
+ export { S as DashboardGrid };
54
65
 
55
66
  //# sourceMappingURL=DashboardGrid.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardGrid.js","names":[],"sources":["../../../src/pages/dashboard/DashboardGrid.tsx"],"sourcesContent":["/**\n * DashboardGrid — Renders the configured widgets in a responsive grid.\n */\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig, WidgetProps } from './types';\nimport { WIDGET_DEFINITIONS } from './config';\n\n// Widget components\nimport { WelcomeWidget } from './widgets/WelcomeWidget';\nimport { QuickActionsWidget } from './widgets/QuickActionsWidget';\nimport { WorkspacesWidget } from './widgets/WorkspacesWidget';\nimport { ProjectsWidget } from './widgets/ProjectsWidget';\nimport { RecentActivityWidget } from './widgets/RecentActivityWidget';\nimport { UpcomingEventsWidget } from './widgets/UpcomingEventsWidget';\nimport { WorkflowStatsWidget } from './widgets/WorkflowStatsWidget';\nimport { TagCloudWidget } from './widgets/TagCloudWidget';\nimport { StorageWidget } from './widgets/StorageWidget';\nimport { GroupsWidget } from './widgets/GroupsWidget';\nimport { MembersWidget } from './widgets/MembersWidget';\nimport { SystemHealthWidget } from './widgets/SystemHealthWidget';\nimport { TipsWidget } from './widgets/TipsWidget';\n\n// Widget component registry\nconst WIDGET_COMPONENTS: Record<string, React.FC<WidgetProps>> = {\n welcome: WelcomeWidget,\n quickActions: QuickActionsWidget,\n workspaces: WorkspacesWidget,\n projects: ProjectsWidget,\n activity: RecentActivityWidget,\n calendar: UpcomingEventsWidget,\n workflows: WorkflowStatsWidget,\n tags: TagCloudWidget,\n storage: StorageWidget,\n groups: GroupsWidget,\n members: MembersWidget,\n systemHealth: SystemHealthWidget,\n tips: TipsWidget,\n};\n\ninterface DashboardGridProps extends WidgetProps {\n widgets: WidgetConfig[];\n}\n\nexport function DashboardGrid({ widgets, ...widgetProps }: DashboardGridProps) {\n const { t } = useI18n();\n\n const enabledWidgets = widgets.filter((w) => w.enabled).sort((a, b) => a.order - b.order);\n\n if (enabledWidgets.length === 0) {\n return (\n <div className=\"text-center py-12\">\n <p className=\"text-lg text-muted-foreground\">\n {tWithFallback(t, 'dashboardGrid.noWidgetsEnabled', 'No widgets enabled')}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {tWithFallback(\n t,\n 'dashboardGrid.noWidgetsHint',\n 'Click \"Customize\" to add widgets to your dashboard'\n )}\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n {enabledWidgets.map((widgetConfig) => {\n const Component = WIDGET_COMPONENTS[widgetConfig.widgetId];\n if (!Component) return null;\n\n return <Component key={widgetConfig.widgetId} {...widgetProps} />;\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,IAAM,IAA2D;CAC/D,SAAS;CACT,cAAc;CACd,YAAY;CACZ,UAAU;CACV,UAAU;CACV,UAAU;CACV,WAAW;CACX,MAAM;CACN,SAAS;CACT,QAAQ;CACR,SAAS;CACT,cAAc;CACd,MAAM;CACP;AAMD,SAAgB,EAAc,EAAE,YAAS,GAAG,KAAmC;CAC7E,IAAM,EAAE,SAAM,GAAS,EAEjB,IAAiB,EAAQ,QAAQ,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAmBzF,QAjBI,EAAe,WAAW,IAE1B,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,KAAD;GAAG,WAAU;aACV,EAAc,GAAG,kCAAkC,qBAAqB;GACvE,CAAA,EACJ,kBAAC,KAAD;GAAG,WAAU;aACV,EACC,GACA,+BACA,uDACD;GACC,CAAA,CACA;MAKR,kBAAC,OAAD;EAAK,WAAU;YACZ,EAAe,KAAK,MAAiB;GACpC,IAAM,IAAY,EAAkB,EAAa;AAGjD,UAFK,IAEE,kBAAC,GAAD,EAAuC,GAAI,GAAe,EAA1C,EAAa,SAA6B,GAF1C;IAGvB;EACE,CAAA"}
1
+ {"version":3,"file":"DashboardGrid.js","names":[],"sources":["../../../src/pages/dashboard/DashboardGrid.tsx"],"sourcesContent":["/**\n * DashboardGrid — Renders the configured widgets in a responsive grid.\n */\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig, WidgetProps } from './types';\nimport { isWidgetAvailable, WIDGET_DEFINITIONS } from './config';\n\n// Widget components\nimport { WelcomeWidget } from './widgets/WelcomeWidget';\nimport { QuickActionsWidget } from './widgets/QuickActionsWidget';\nimport { WorkspacesWidget } from './widgets/WorkspacesWidget';\nimport { ProjectsWidget } from './widgets/ProjectsWidget';\nimport { RecentActivityWidget } from './widgets/RecentActivityWidget';\nimport { UpcomingEventsWidget } from './widgets/UpcomingEventsWidget';\nimport { WorkflowStatsWidget } from './widgets/WorkflowStatsWidget';\nimport { TagCloudWidget } from './widgets/TagCloudWidget';\nimport { StorageWidget } from './widgets/StorageWidget';\nimport { GroupsWidget } from './widgets/GroupsWidget';\nimport { MembersWidget } from './widgets/MembersWidget';\nimport { TipsWidget } from './widgets/TipsWidget';\nimport { VibesWidget } from './widgets/VibesWidget';\nimport { SessionsWidget } from './widgets/SessionsWidget';\nimport { AgentsWidget } from './widgets/AgentsWidget';\n\n// Widget component registry\nconst WIDGET_COMPONENTS: Record<string, React.FC<WidgetProps>> = {\n welcome: WelcomeWidget,\n quickActions: QuickActionsWidget,\n workspaces: WorkspacesWidget,\n projects: ProjectsWidget,\n activity: RecentActivityWidget,\n calendar: UpcomingEventsWidget,\n workflows: WorkflowStatsWidget,\n tags: TagCloudWidget,\n storage: StorageWidget,\n groups: GroupsWidget,\n members: MembersWidget,\n tips: TipsWidget,\n vibes: VibesWidget,\n sessions: SessionsWidget,\n agents: AgentsWidget,\n};\n\ninterface DashboardGridProps extends WidgetProps {\n widgets: WidgetConfig[];\n}\n\nexport function DashboardGrid({ widgets, productId, ...widgetProps }: DashboardGridProps) {\n const { t } = useI18n();\n\n const enabledWidgets = widgets\n .filter((w) => w.enabled)\n .filter((w) => {\n const def = WIDGET_DEFINITIONS[w.widgetId];\n if (!def) return false;\n return isWidgetAvailable(def, productId);\n })\n .sort((a, b) => a.order - b.order);\n\n if (enabledWidgets.length === 0) {\n return (\n <div className=\"text-center py-12\">\n <p className=\"text-lg text-muted-foreground\">\n {tWithFallback(t, 'dashboardGrid.noWidgetsEnabled', 'No widgets enabled')}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {tWithFallback(\n t,\n 'dashboardGrid.noWidgetsHint',\n 'Click \"Customize\" to add widgets to your dashboard'\n )}\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n {enabledWidgets.map((widgetConfig) => {\n const Component = WIDGET_COMPONENTS[widgetConfig.widgetId];\n if (!Component) return null;\n\n return <Component key={widgetConfig.widgetId} productId={productId} {...widgetProps} />;\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,IAAM,IAA2D;CAC/D,SAAS;CACT,cAAc;CACd,YAAY;CACZ,UAAU;CACV,UAAU;CACV,UAAU;CACV,WAAW;CACX,MAAM;CACN,SAAS;CACT,QAAQ;CACR,SAAS;CACT,MAAM;CACN,OAAO;CACP,UAAU;CACV,QAAQ;CACT;AAMD,SAAgB,EAAc,EAAE,YAAS,cAAW,GAAG,KAAmC;CACxF,IAAM,EAAE,SAAM,GAAS,EAEjB,IAAiB,EACpB,QAAQ,MAAM,EAAE,QAAQ,CACxB,QAAQ,MAAM;EACb,IAAM,IAAM,EAAmB,EAAE;AAEjC,SADK,IACE,EAAkB,GAAK,EAAU,GADvB;GAEjB,CACD,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAmBpC,QAjBI,EAAe,WAAW,IAE1B,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,KAAD;GAAG,WAAU;aACV,EAAc,GAAG,kCAAkC,qBAAqB;GACvE,CAAA,EACJ,kBAAC,KAAD;GAAG,WAAU;aACV,EACC,GACA,+BACA,uDACD;GACC,CAAA,CACA;MAKR,kBAAC,OAAD;EAAK,WAAU;YACZ,EAAe,KAAK,MAAiB;GACpC,IAAM,IAAY,EAAkB,EAAa;AAGjD,UAFK,IAEE,kBAAC,GAAD;IAAkD;IAAW,GAAI;IAAe,EAAhE,EAAa,SAAmD,GAFhE;IAGvB;EACE,CAAA"}