@burdenoff/microfe-workspaces 2026.520.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/hooks/useOrgsWithPermission.js +1 -1
  21. package/dist/hooks/useOrgsWithPermission.js.map +1 -1
  22. package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
  23. package/dist/hooks/useWorkspacesPageView.js +6 -4
  24. package/dist/hooks/useWorkspacesPageView.js.map +1 -1
  25. package/dist/pages/CreateWorkspacePage.js +239 -224
  26. package/dist/pages/CreateWorkspacePage.js.map +1 -1
  27. package/dist/pages/InviteAcceptancePage.js +28 -28
  28. package/dist/pages/InviteAcceptancePage.js.map +1 -1
  29. package/dist/pages/MembersListPage.js +380 -352
  30. package/dist/pages/MembersListPage.js.map +1 -1
  31. package/dist/pages/ProjectDetailPage.js +96 -97
  32. package/dist/pages/ProjectDetailPage.js.map +1 -1
  33. package/dist/pages/ProjectsListPage.js +307 -304
  34. package/dist/pages/ProjectsListPage.js.map +1 -1
  35. package/dist/pages/WorkspaceSettingsPage.js +94 -91
  36. package/dist/pages/WorkspaceSettingsPage.js.map +1 -1
  37. package/dist/pages/WorkspacesListPage.js +1 -1
  38. package/dist/pages/WorkspacesListPage.js.map +1 -1
  39. package/dist/pages/dashboard/DashboardCustomizer.js +68 -68
  40. package/dist/pages/dashboard/DashboardCustomizer.js.map +1 -1
  41. package/dist/pages/dashboard/DashboardGrid.js +52 -41
  42. package/dist/pages/dashboard/DashboardGrid.js.map +1 -1
  43. package/dist/pages/dashboard/DashboardPage.js +74 -65
  44. package/dist/pages/dashboard/DashboardPage.js.map +1 -1
  45. package/dist/pages/dashboard/WidgetWrapper.js +3 -3
  46. package/dist/pages/dashboard/WidgetWrapper.js.map +1 -1
  47. package/dist/pages/dashboard/config.js +126 -30
  48. package/dist/pages/dashboard/config.js.map +1 -1
  49. package/dist/pages/dashboard/hooks/useDashboardData.js +39 -2
  50. package/dist/pages/dashboard/hooks/useDashboardData.js.map +1 -1
  51. package/dist/pages/dashboard/widgets/AgentsWidget.js +109 -0
  52. package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -0
  53. package/dist/pages/dashboard/widgets/GroupsWidget.js +6 -5
  54. package/dist/pages/dashboard/widgets/GroupsWidget.js.map +1 -1
  55. package/dist/pages/dashboard/widgets/MembersWidget.js +6 -6
  56. package/dist/pages/dashboard/widgets/MembersWidget.js.map +1 -1
  57. package/dist/pages/dashboard/widgets/ProjectsWidget.js +8 -7
  58. package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
  59. package/dist/pages/dashboard/widgets/QuickActionsWidget.js +72 -18
  60. package/dist/pages/dashboard/widgets/QuickActionsWidget.js.map +1 -1
  61. package/dist/pages/dashboard/widgets/RecentActivityWidget.js +3 -3
  62. package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
  63. package/dist/pages/dashboard/widgets/SessionsWidget.js +78 -0
  64. package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -0
  65. package/dist/pages/dashboard/widgets/StorageWidget.js +35 -20
  66. package/dist/pages/dashboard/widgets/StorageWidget.js.map +1 -1
  67. package/dist/pages/dashboard/widgets/TagCloudWidget.js +2 -2
  68. package/dist/pages/dashboard/widgets/TagCloudWidget.js.map +1 -1
  69. package/dist/pages/dashboard/widgets/TipsWidget.js +81 -22
  70. package/dist/pages/dashboard/widgets/TipsWidget.js.map +1 -1
  71. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +6 -5
  72. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
  73. package/dist/pages/dashboard/widgets/VibesWidget.js +64 -0
  74. package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -0
  75. package/dist/pages/dashboard/widgets/WelcomeWidget.js +5 -5
  76. package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
  77. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js +3 -3
  78. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
  79. package/dist/pages/dashboard/widgets/WorkspacesWidget.js +6 -5
  80. package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
  81. package/dist/providers/WorkspacesProvider.js +1 -1
  82. package/dist/providers/WorkspacesProvider.js.map +1 -1
  83. package/dist/store/workspacesStore.js.map +1 -1
  84. package/dist/utils/formatters.js +21 -16
  85. package/dist/utils/formatters.js.map +1 -1
  86. package/dist/utils/telemetryError.js +1 -1
  87. package/dist/utils/telemetryError.js.map +1 -1
  88. package/package.json +7 -7
  89. package/dist/WorkspacesRoot.d.ts +0 -35
  90. package/dist/WorkspacesRoot.d.ts.map +0 -1
  91. package/dist/WorkspacesRoutes.d.ts +0 -10
  92. package/dist/WorkspacesRoutes.d.ts.map +0 -1
  93. package/dist/components/CreateProjectDialog.d.ts +0 -6
  94. package/dist/components/CreateProjectDialog.d.ts.map +0 -1
  95. package/dist/components/CreateWorkspaceDialog.d.ts +0 -2
  96. package/dist/components/CreateWorkspaceDialog.d.ts.map +0 -1
  97. package/dist/components/InviteMemberDialog.d.ts +0 -7
  98. package/dist/components/InviteMemberDialog.d.ts.map +0 -1
  99. package/dist/components/MemberListItem.d.ts +0 -11
  100. package/dist/components/MemberListItem.d.ts.map +0 -1
  101. package/dist/components/ProjectCard.d.ts +0 -13
  102. package/dist/components/ProjectCard.d.ts.map +0 -1
  103. package/dist/components/WorkspaceCard.d.ts +0 -8
  104. package/dist/components/WorkspaceCard.d.ts.map +0 -1
  105. package/dist/components/WorkspacesErrorBoundary.d.ts +0 -27
  106. package/dist/components/WorkspacesErrorBoundary.d.ts.map +0 -1
  107. package/dist/components/index.d.ts +0 -8
  108. package/dist/components/index.d.ts.map +0 -1
  109. package/dist/constants/permissions.d.ts +0 -33
  110. package/dist/constants/permissions.d.ts.map +0 -1
  111. package/dist/generated/global-operations.d.ts +0 -319
  112. package/dist/generated/global-operations.d.ts.map +0 -1
  113. package/dist/generated/global-types.d.ts +0 -23527
  114. package/dist/generated/global-types.d.ts.map +0 -1
  115. package/dist/generated/wspace-operations.d.ts +0 -2300
  116. package/dist/generated/wspace-operations.d.ts.map +0 -1
  117. package/dist/generated/wspace-types.d.ts +0 -57851
  118. package/dist/generated/wspace-types.d.ts.map +0 -1
  119. package/dist/hooks/index.d.ts +0 -8
  120. package/dist/hooks/index.d.ts.map +0 -1
  121. package/dist/hooks/useMemberMutations.d.ts +0 -61
  122. package/dist/hooks/useMemberMutations.d.ts.map +0 -1
  123. package/dist/hooks/useOrgsWithPermission.d.ts +0 -7
  124. package/dist/hooks/useOrgsWithPermission.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":"MembersListPage.js","names":[],"sources":["../../src/pages/MembersListPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { Users, UserPlus, Search, AlertCircle, RefreshCw } from 'lucide-react';\nimport { Button, Input, Skeleton, Badge } from '@burdenoff/fe-libs/ui';\nimport { useDebounce } from '@burdenoff/fe-libs/shared/hooks';\nimport { nativeConfirm, nativeImpact } from '../utils/nativeBridge';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport { PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\nimport { useWorkspacePermissions } from '../hooks/useWorkspacePermissions';\nimport { useWorkspacesStore } from '../store/workspacesStore';\nimport { useWorkspaceMembers, useWorkspaceInvitations } from '../hooks/useWorkspaceMembers';\nimport { useRemoveUserFromWorkspace, useResendInvitation } from '../hooks/useMemberMutations';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\nimport { MemberListItem } from '../components/MemberListItem';\nimport { InviteMemberDialog } from '../components/InviteMemberDialog';\nimport type { Workspace } from '../types';\n\nexport function MembersListPage() {\n const { t } = useI18n();\n\n const {\n memberFilters,\n setMemberFilters,\n selectedMemberIds,\n toggleMemberSelection,\n clearMemberSelection,\n openInviteMemberDialog,\n } = useWorkspacesStore();\n const { workspaceId: contextWorkspaceId } = useWorkspacesContext();\n const { workspaceId: urlWorkspaceId } = useParams<{ workspaceId: string }>();\n\n // Prefer URL workspaceId over context (user navigated to specific workspace)\n const workspaceId = urlWorkspaceId || contextWorkspaceId;\n\n useWorkspacesPageView('workspaces.members', { workspaceId, requireParams: true });\n\n const [searchValue, setSearchValue] = useState(memberFilters.search || '');\n const debouncedSearch = useDebounce(searchValue, 500);\n\n // Update filters when debounced search changes\n useEffect(() => {\n setMemberFilters({ search: debouncedSearch });\n }, [debouncedSearch, setMemberFilters]);\n\n // Fetch members and invitations\n const {\n data: membersData,\n isLoading: isLoadingMembers,\n error: membersError,\n } = useWorkspaceMembers(workspaceId || '');\n\n const { data: invitationsData, isLoading: isLoadingInvitations } = useWorkspaceInvitations(\n workspaceId || '',\n 'PENDING'\n );\n\n const { mutate: resendInvitation, isPending: isResending } = useResendInvitation();\n const { mutate: removeUserFromWorkspace, isPending: isRemovingMembers } =\n useRemoveUserFromWorkspace();\n const [resendingId, setResendingId] = useState<string | null>(null);\n const [selectedInvitationIds, setSelectedInvitationIds] = useState<Set<string>>(new Set());\n\n const handleResendInvitation = (invitationId: string) => {\n setResendingId(invitationId);\n resendInvitation(invitationId, {\n onSuccess: () => {\n setResendingId(null);\n },\n onError: (error) => {\n console.error('Failed to resend invitation:', error);\n setResendingId(null);\n },\n });\n };\n\n const members = useMemo(() => membersData?.items || [], [membersData?.items]);\n const pendingInvitations = useMemo(() => invitationsData?.items || [], [invitationsData?.items]);\n const isLoading = isLoadingMembers || isLoadingInvitations;\n const hasMembers = members.length > 0;\n const hasPendingInvitations = pendingInvitations.length > 0;\n\n // Filter members based on search\n const filteredMembers = members.filter((member) => {\n if (!debouncedSearch) return true;\n return member.userId.toLowerCase().includes(debouncedSearch.toLowerCase());\n });\n\n const selectedMembers = useMemo(\n () => filteredMembers.filter((member) => selectedMemberIds.has(member.id)),\n [filteredMembers, selectedMemberIds]\n );\n\n const selectedInvitations = useMemo(\n () => pendingInvitations.filter((invitation) => selectedInvitationIds.has(invitation.id)),\n [pendingInvitations, selectedInvitationIds]\n );\n\n const allVisibleMembersSelected =\n filteredMembers.length > 0 &&\n filteredMembers.every((member) => selectedMemberIds.has(member.id));\n const partiallySelectedMembers =\n filteredMembers.some((member) => selectedMemberIds.has(member.id)) &&\n !allVisibleMembersSelected;\n\n const allVisibleInvitationsSelected =\n pendingInvitations.length > 0 &&\n pendingInvitations.every((invitation) => selectedInvitationIds.has(invitation.id));\n const partiallySelectedInvitations =\n pendingInvitations.some((invitation) => selectedInvitationIds.has(invitation.id)) &&\n !allVisibleInvitationsSelected;\n\n // Clear selection on unmount\n useEffect(() => {\n return () => clearMemberSelection();\n }, [clearMemberSelection]);\n\n const {\n canListMembers,\n canInviteMember,\n canRemoveMember,\n isLoading: permissionsLoading,\n } = useWorkspacePermissions();\n\n if (permissionsLoading) {\n return (\n <div className=\"space-y-4 p-6\">\n <Skeleton className=\"h-10 w-1/3\" />\n <Skeleton className=\"h-64\" />\n </div>\n );\n }\n\n if (!canListMembers && !canInviteMember) {\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'membersList.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'membersList.noPermissionToViewMembers',\n \"You don't have permission to view workspace members.\"\n )}\n </p>\n </div>\n </div>\n );\n }\n\n const handleInviteMember = () => {\n if (workspaceId) {\n openInviteMemberDialog({ id: workspaceId } as Workspace);\n }\n };\n\n const toggleAllMembers = (checked: boolean) => {\n filteredMembers.forEach((member) => {\n const isSelected = selectedMemberIds.has(member.id);\n if (checked !== isSelected) {\n toggleMemberSelection(member.id);\n }\n });\n };\n\n const toggleInvitationSelection = (invitationId: string, checked: boolean) => {\n setSelectedInvitationIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(invitationId);\n } else {\n next.delete(invitationId);\n }\n return next;\n });\n };\n\n const toggleAllInvitations = (checked: boolean) => {\n setSelectedInvitationIds((prev) => {\n const next = new Set(prev);\n pendingInvitations.forEach((invitation) => {\n if (checked) {\n next.add(invitation.id);\n } else {\n next.delete(invitation.id);\n }\n });\n return next;\n });\n };\n\n const handleBulkRemoveMembers = async () => {\n if (selectedMembers.length === 0) return;\n void nativeImpact('medium');\n const message = `${tWithFallback(t, 'membersList.bulkRemoveConfirmPrefix', 'Remove')} ${selectedMembers.length} ${\n selectedMembers.length === 1\n ? tWithFallback(t, 'membersList.bulkRemoveConfirmSingular', 'selected member')\n : tWithFallback(t, 'membersList.bulkRemoveConfirmPlural', 'selected members')\n } ${tWithFallback(t, 'membersList.bulkRemoveConfirmSuffix', 'from this workspace?')}`;\n const native = await nativeConfirm({\n title: 'Remove members',\n message,\n okButtonTitle: 'Remove',\n cancelButtonTitle: 'Cancel',\n });\n const confirmed = native === null ? window.confirm(message) : native;\n if (!confirmed) return;\n\n selectedMembers.forEach((member) => {\n removeUserFromWorkspace(member.userId);\n });\n clearMemberSelection();\n };\n\n const handleBulkResendInvitations = () => {\n if (selectedInvitations.length === 0) return;\n selectedInvitations.forEach((invitation) => {\n resendInvitation(invitation.id, {\n onSuccess: () => {\n setSelectedInvitationIds((prev) => {\n const next = new Set(prev);\n next.delete(invitation.id);\n return next;\n });\n },\n });\n });\n };\n\n return (\n <>\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tWithFallback(t, 'membersList.pageTitle', 'Members')}\n </h1>\n <p className=\"text-muted-foreground text-sm sm:text-base\">\n {tWithFallback(\n t,\n 'membersList.pageSubtitle',\n 'Manage workspace members and invitations'\n )}\n </p>\n </div>\n\n <div className=\"flex gap-2\">\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.MEMBER_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'membersList.noPermissionToInvite',\n \"You don't have permission to invite members\"\n )}\n >\n <Button onClick={handleInviteMember} disabled={!workspaceId}>\n <UserPlus className=\"h-4 w-4 sm:mr-2\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(t, 'membersList.inviteMember', 'Invite Member')}\n </span>\n </Button>\n </PermissionButton>\n </div>\n </div>\n\n {/* Search & Stats */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n placeholder={tWithFallback(t, 'membersList.searchPlaceholder', 'Search members...')}\n value={searchValue}\n onChange={(e) => setSearchValue(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n\n {hasPendingInvitations && (\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\" className=\"text-sm\">\n {pendingInvitations.length}{' '}\n {pendingInvitations.length !== 1\n ? tWithFallback(t, 'membersList.pendingInvitations', 'Pending Invitations')\n : tWithFallback(t, 'membersList.pendingInvitation', 'Pending Invitation')}\n </Badge>\n </div>\n )}\n </div>\n\n {filteredMembers.length > 0 && (\n <div className=\"flex flex-col gap-3 rounded-lg border bg-card p-4 sm:flex-row sm:items-center sm:justify-between\">\n <label className=\"flex items-center gap-2 text-sm text-foreground\">\n <input\n type=\"checkbox\"\n checked={allVisibleMembersSelected}\n ref={(input) => {\n if (input) {\n input.indeterminate = partiallySelectedMembers && !allVisibleMembersSelected;\n }\n }}\n onChange={(event) => toggleAllMembers(event.target.checked)}\n aria-label={tWithFallback(\n t,\n 'membersList.selectAllMembersAriaLabel',\n 'Select all workspace members'\n )}\n className=\"h-4 w-4 rounded border-border text-primary\"\n />\n <span>\n {tWithFallback(\n t,\n 'membersList.selectAllVisibleMembers',\n 'Select all visible members'\n )}\n </span>\n </label>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">\n {selectedMemberIds.size} {tWithFallback(t, 'membersList.selected', 'selected')}\n </span>\n {selectedMemberIds.size > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={clearMemberSelection}>\n {tWithFallback(t, 'membersList.clearSelection', 'Clear selection')}\n </Button>\n )}\n {canRemoveMember && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleBulkRemoveMembers}\n disabled={selectedMembers.length === 0 || isRemovingMembers}\n className=\"text-destructive\"\n >\n {tWithFallback(t, 'membersList.removeSelected', 'Remove Selected')}\n {selectedMembers.length > 0 ? ` (${selectedMembers.length})` : ''}\n </Button>\n )}\n </div>\n </div>\n )}\n\n {/* Loading State */}\n {isLoading && (\n <div className=\"space-y-3\">\n {[...Array(5)].map((_, i) => (\n <Skeleton key={i} className=\"h-20 w-full\" />\n ))}\n </div>\n )}\n\n {/* Error State */}\n {!isLoading && membersError && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"rounded-full bg-destructive/10 p-6 mb-4\">\n <AlertCircle size={48} className=\"text-destructive\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.failedToLoad', 'Failed to Load Members')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {membersError instanceof Error\n ? membersError.message\n : tWithFallback(\n t,\n 'membersList.errorLoadingMembers',\n 'An error occurred while loading members'\n )}\n </p>\n </div>\n )}\n\n {/* Empty State - No Workspace */}\n {!isLoading && !membersError && !workspaceId && (\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 <Users size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.noWorkspaceSelected', 'No Workspace Selected')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {tWithFallback(\n t,\n 'membersList.selectWorkspacePrompt',\n 'Select a workspace to view and manage its members'\n )}\n </p>\n </div>\n )}\n\n {/* Empty State - No Members */}\n {!isLoading && !membersError && workspaceId && !hasMembers && (\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 <Users size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.noMembersYet', 'No Members Yet')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm mb-4\">\n {tWithFallback(\n t,\n 'membersList.noMembersPrompt',\n 'Start building your team by inviting members to this workspace'\n )}\n </p>\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.MEMBER_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'membersList.noPermissionToInvite',\n \"You don't have permission to invite members\"\n )}\n >\n <Button onClick={handleInviteMember}>\n <UserPlus className=\"mr-2 h-4 w-4\" />\n {tWithFallback(t, 'membersList.inviteFirstMember', 'Invite Your First Member')}\n </Button>\n </PermissionButton>\n </div>\n )}\n\n {/* Empty State - No Search Results */}\n {!isLoading &&\n !membersError &&\n workspaceId &&\n hasMembers &&\n filteredMembers.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 <Search size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.noMembersFound', 'No Members Found')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {tWithFallback(\n t,\n 'membersList.noMembersFoundPrompt',\n 'No members match your search criteria. Try adjusting your search.'\n )}\n </p>\n </div>\n )}\n\n {/* Members List */}\n {!isLoading && filteredMembers.length > 0 && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'membersList.activeMembers', 'Active Members')} (\n {filteredMembers.length})\n </h2>\n </div>\n <div className=\"space-y-2\">\n {filteredMembers.map((member) => (\n <MemberListItem\n key={member.id}\n member={member}\n selected={selectedMemberIds.has(member.id)}\n onToggleSelect={(checked) => {\n const isSelected = selectedMemberIds.has(member.id);\n if (checked !== isSelected) {\n toggleMemberSelection(member.id);\n }\n }}\n canRemove={canRemoveMember}\n />\n ))}\n </div>\n </div>\n )}\n\n {/* Pending Invitations Section - Now at bottom */}\n {!isLoading && hasPendingInvitations && (\n <div className=\"space-y-3\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'membersList.pendingInvitationsHeader', 'Pending Invitations')}\n </h2>\n <div className=\"flex flex-col gap-3 rounded-lg border bg-card p-4 sm:flex-row sm:items-center sm:justify-between\">\n <label className=\"flex items-center gap-2 text-sm text-foreground\">\n <input\n type=\"checkbox\"\n checked={allVisibleInvitationsSelected}\n ref={(input) => {\n if (input) {\n input.indeterminate =\n partiallySelectedInvitations && !allVisibleInvitationsSelected;\n }\n }}\n onChange={(event) => toggleAllInvitations(event.target.checked)}\n aria-label={tWithFallback(\n t,\n 'membersList.selectAllInvitationsAriaLabel',\n 'Select all pending invitations'\n )}\n className=\"h-4 w-4 rounded border-border text-primary\"\n />\n <span>\n {tWithFallback(t, 'membersList.selectAllInvitations', 'Select all invitations')}\n </span>\n </label>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">\n {selectedInvitationIds.size}{' '}\n {tWithFallback(t, 'membersList.selected', 'selected')}\n </span>\n {selectedInvitationIds.size > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setSelectedInvitationIds(new Set())}\n >\n {tWithFallback(t, 'membersList.clearSelection', 'Clear selection')}\n </Button>\n )}\n {canInviteMember && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleBulkResendInvitations}\n disabled={selectedInvitations.length === 0 || isResending}\n >\n {tWithFallback(t, 'membersList.resendSelected', 'Resend Selected')}\n {selectedInvitations.length > 0 ? ` (${selectedInvitations.length})` : ''}\n </Button>\n )}\n </div>\n </div>\n <div className=\"space-y-2\">\n {pendingInvitations.map((invitation) => (\n <div\n key={invitation.id}\n className=\"flex items-center justify-between p-4 border rounded-lg bg-card\"\n >\n <div className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={selectedInvitationIds.has(invitation.id)}\n onChange={(event) =>\n toggleInvitationSelection(invitation.id, event.target.checked)\n }\n aria-label={`${tWithFallback(t, 'membersList.selectInvitationAriaLabel', 'Select invitation')} ${invitation.email}`}\n className=\"h-4 w-4 rounded border-border text-primary\"\n />\n <div className=\"w-10 h-10 rounded-full bg-status-warning/10 flex items-center justify-center transition-colors\">\n <Users className=\"h-5 w-5 text-status-warning\" />\n </div>\n <div>\n <p className=\"font-medium text-sm\">{invitation.email}</p>\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(t, 'membersList.invited', 'Invited')}{' '}\n {new Date(invitation.createdAt).toLocaleDateString()}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.MEMBER_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'membersList.noPermissionToResend',\n \"You don't have permission to resend invitations\"\n )}\n >\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleResendInvitation(invitation.id)}\n disabled={isResending && resendingId === invitation.id}\n >\n <RefreshCw\n className={`h-4 w-4 mr-1 ${isResending && resendingId === invitation.id ? 'animate-spin' : ''}`}\n />\n {isResending && resendingId === invitation.id\n ? tWithFallback(t, 'membersList.sending', 'Sending...')\n : tWithFallback(t, 'membersList.resend', 'Resend')}\n </Button>\n </PermissionButton>\n <Badge\n variant=\"outline\"\n className=\"bg-status-warning/10 text-status-warning border-status-warning/30 transition-colors\"\n >\n {tWithFallback(t, 'membersList.pending', 'Pending')}\n </Badge>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Dialogs */}\n <InviteMemberDialog workspaceId={workspaceId} />\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MembersListPage.js","names":[],"sources":["../../src/pages/MembersListPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { Users, UserPlus, Search, AlertCircle, RefreshCw } from 'lucide-react';\nimport { Button, Input, Skeleton, Badge, PageContainer } from '@burdenoff/fe-libs/ui';\nimport { useDebounce } from '@burdenoff/fe-libs/shared/hooks';\nimport { useActorProfiles, type ActorInput, type ActorProfileMap } from '@burdenoff/fe-libs/shared';\nimport { nativeConfirm, nativeImpact } from '../utils/nativeBridge';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport { PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\nimport { useWorkspacePermissions } from '../hooks/useWorkspacePermissions';\nimport { useWorkspacesStore } from '../store/workspacesStore';\nimport { useWorkspaceMembers, useWorkspaceInvitations } from '../hooks/useWorkspaceMembers';\nimport { useRemoveUserFromWorkspace, useResendInvitation } from '../hooks/useMemberMutations';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\nimport { MemberListItem } from '../components/MemberListItem';\nimport { InviteMemberDialog } from '../components/InviteMemberDialog';\nimport type { Workspace } from '../types';\n\nexport function MembersListPage() {\n const { t } = useI18n();\n\n const {\n memberFilters,\n setMemberFilters,\n selectedMemberIds,\n toggleMemberSelection,\n clearMemberSelection,\n openInviteMemberDialog,\n } = useWorkspacesStore();\n const { workspaceId: contextWorkspaceId } = useWorkspacesContext();\n const { workspaceId: urlWorkspaceId } = useParams<{ workspaceId: string }>();\n\n // Prefer URL workspaceId over context (user navigated to specific workspace)\n const workspaceId = urlWorkspaceId || contextWorkspaceId;\n\n useWorkspacesPageView('workspaces.members', { workspaceId, requireParams: true });\n\n const [searchValue, setSearchValue] = useState(memberFilters.search || '');\n const debouncedSearch = useDebounce(searchValue, 500);\n\n // Update filters when debounced search changes\n useEffect(() => {\n setMemberFilters({ search: debouncedSearch });\n }, [debouncedSearch, setMemberFilters]);\n\n // Fetch members and invitations\n const {\n data: membersData,\n isLoading: isLoadingMembers,\n error: membersError,\n } = useWorkspaceMembers(workspaceId || '');\n\n const { data: invitationsData, isLoading: isLoadingInvitations } = useWorkspaceInvitations(\n workspaceId || '',\n 'PENDING'\n );\n\n const { mutate: resendInvitation, isPending: isResending } = useResendInvitation();\n const { mutate: removeUserFromWorkspace, isPending: isRemovingMembers } =\n useRemoveUserFromWorkspace();\n const [resendingId, setResendingId] = useState<string | null>(null);\n const [selectedInvitationIds, setSelectedInvitationIds] = useState<Set<string>>(new Set());\n\n const handleResendInvitation = (invitationId: string) => {\n setResendingId(invitationId);\n resendInvitation(invitationId, {\n onSuccess: () => {\n setResendingId(null);\n },\n onError: (error) => {\n console.error('Failed to resend invitation:', error);\n setResendingId(null);\n },\n });\n };\n\n const members = useMemo(() => membersData?.items || [], [membersData?.items]);\n const pendingInvitations = useMemo(() => invitationsData?.items || [], [invitationsData?.items]);\n const isLoading = isLoadingMembers || isLoadingInvitations;\n const hasMembers = members.length > 0;\n const hasPendingInvitations = pendingInvitations.length > 0;\n\n // Resolve every member's userId to displayName + email via the shared\n // ActorProfile cache so search can match human-friendly fields instead of\n // raw UUIDs.\n const { apiGatewayUrl, authToken, organizationId } = useWorkspacesContext();\n const memberActors = useMemo<ActorInput[]>(\n () => members.map((m) => ({ actorId: m.userId, actorType: 'user' })),\n [members]\n );\n const profileMap: ActorProfileMap = useActorProfiles(memberActors, {\n apiGatewayUrl,\n authToken,\n orgId: organizationId,\n });\n\n // Filter members by resolved identity (displayName, email) — fall back to\n // raw userId only if the profile hasn't resolved yet so search still works\n // during the brief loading window.\n const filteredMembers = members.filter((member) => {\n if (!debouncedSearch) return true;\n const needle = debouncedSearch.toLowerCase();\n const profile = profileMap[member.userId];\n if (profile) {\n if (profile.displayName.toLowerCase().includes(needle)) return true;\n if (profile.email?.toLowerCase().includes(needle)) return true;\n }\n return member.userId.toLowerCase().includes(needle);\n });\n\n const selectedMembers = useMemo(\n () => filteredMembers.filter((member) => selectedMemberIds.has(member.id)),\n [filteredMembers, selectedMemberIds]\n );\n\n const selectedInvitations = useMemo(\n () => pendingInvitations.filter((invitation) => selectedInvitationIds.has(invitation.id)),\n [pendingInvitations, selectedInvitationIds]\n );\n\n const allVisibleMembersSelected =\n filteredMembers.length > 0 &&\n filteredMembers.every((member) => selectedMemberIds.has(member.id));\n const partiallySelectedMembers =\n filteredMembers.some((member) => selectedMemberIds.has(member.id)) &&\n !allVisibleMembersSelected;\n\n const allVisibleInvitationsSelected =\n pendingInvitations.length > 0 &&\n pendingInvitations.every((invitation) => selectedInvitationIds.has(invitation.id));\n const partiallySelectedInvitations =\n pendingInvitations.some((invitation) => selectedInvitationIds.has(invitation.id)) &&\n !allVisibleInvitationsSelected;\n\n // Clear selection on unmount\n useEffect(() => {\n return () => clearMemberSelection();\n }, [clearMemberSelection]);\n\n // Auto-open the invite dialog when arriving via /workspaces/members?invite=true\n // (used by dashboard widgets and deep links). Strip the param after opening so\n // the back button returns to the previous page rather than re-opening.\n const [searchParams, setSearchParams] = useSearchParams();\n useEffect(() => {\n if (searchParams.get('invite') === 'true' && workspaceId) {\n openInviteMemberDialog({ id: workspaceId } as Workspace);\n const next = new URLSearchParams(searchParams);\n next.delete('invite');\n setSearchParams(next, { replace: true });\n }\n }, [searchParams, setSearchParams, workspaceId, openInviteMemberDialog]);\n\n const {\n canListMembers,\n canInviteMember,\n canRemoveMember,\n isLoading: permissionsLoading,\n } = useWorkspacePermissions();\n\n if (permissionsLoading) {\n return (\n <div className=\"space-y-4 p-6\">\n <Skeleton className=\"h-10 w-1/3\" />\n <Skeleton className=\"h-64\" />\n </div>\n );\n }\n\n if (!canListMembers && !canInviteMember) {\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'membersList.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'membersList.noPermissionToViewMembers',\n \"You don't have permission to view workspace members.\"\n )}\n </p>\n </div>\n </div>\n );\n }\n\n const handleInviteMember = () => {\n if (workspaceId) {\n openInviteMemberDialog({ id: workspaceId } as Workspace);\n }\n };\n\n const toggleAllMembers = (checked: boolean) => {\n filteredMembers.forEach((member) => {\n const isSelected = selectedMemberIds.has(member.id);\n if (checked !== isSelected) {\n toggleMemberSelection(member.id);\n }\n });\n };\n\n const toggleInvitationSelection = (invitationId: string, checked: boolean) => {\n setSelectedInvitationIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(invitationId);\n } else {\n next.delete(invitationId);\n }\n return next;\n });\n };\n\n const toggleAllInvitations = (checked: boolean) => {\n setSelectedInvitationIds((prev) => {\n const next = new Set(prev);\n pendingInvitations.forEach((invitation) => {\n if (checked) {\n next.add(invitation.id);\n } else {\n next.delete(invitation.id);\n }\n });\n return next;\n });\n };\n\n const handleBulkRemoveMembers = async () => {\n if (selectedMembers.length === 0) return;\n void nativeImpact('medium');\n const message = `${tWithFallback(t, 'membersList.bulkRemoveConfirmPrefix', 'Remove')} ${selectedMembers.length} ${\n selectedMembers.length === 1\n ? tWithFallback(t, 'membersList.bulkRemoveConfirmSingular', 'selected member')\n : tWithFallback(t, 'membersList.bulkRemoveConfirmPlural', 'selected members')\n } ${tWithFallback(t, 'membersList.bulkRemoveConfirmSuffix', 'from this workspace?')}`;\n const native = await nativeConfirm({\n title: 'Remove members',\n message,\n okButtonTitle: 'Remove',\n cancelButtonTitle: 'Cancel',\n });\n const confirmed = native === null ? window.confirm(message) : native;\n if (!confirmed) return;\n\n selectedMembers.forEach((member) => {\n removeUserFromWorkspace(member.userId);\n });\n clearMemberSelection();\n };\n\n const handleBulkResendInvitations = () => {\n if (selectedInvitations.length === 0) return;\n selectedInvitations.forEach((invitation) => {\n resendInvitation(invitation.id, {\n onSuccess: () => {\n setSelectedInvitationIds((prev) => {\n const next = new Set(prev);\n next.delete(invitation.id);\n return next;\n });\n },\n });\n });\n };\n\n return (\n <PageContainer padded={false}>\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tWithFallback(t, 'membersList.pageTitle', 'Members')}\n </h1>\n <p className=\"text-muted-foreground text-sm sm:text-base\">\n {tWithFallback(\n t,\n 'membersList.pageSubtitle',\n 'Manage workspace members and invitations'\n )}\n </p>\n </div>\n\n <div className=\"flex gap-2\">\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.MEMBER_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'membersList.noPermissionToInvite',\n \"You don't have permission to invite members\"\n )}\n >\n <Button onClick={handleInviteMember} disabled={!workspaceId}>\n <UserPlus className=\"size-4 sm:mr-2\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(t, 'membersList.inviteMember', 'Invite Member')}\n </span>\n </Button>\n </PermissionButton>\n </div>\n </div>\n\n {/* Search & Stats */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground\" />\n <Input\n placeholder={tWithFallback(t, 'membersList.searchPlaceholder', 'Search members...')}\n value={searchValue}\n onChange={(e) => setSearchValue(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n\n {hasPendingInvitations && (\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\" className=\"text-sm\">\n {pendingInvitations.length}{' '}\n {pendingInvitations.length !== 1\n ? tWithFallback(t, 'membersList.pendingInvitations', 'Pending Invitations')\n : tWithFallback(t, 'membersList.pendingInvitation', 'Pending Invitation')}\n </Badge>\n </div>\n )}\n </div>\n\n {filteredMembers.length > 0 && (\n <div className=\"flex flex-col gap-3 rounded-lg border bg-card p-4 sm:flex-row sm:items-center sm:justify-between\">\n <label className=\"flex items-center gap-2 text-sm text-foreground\">\n <input\n type=\"checkbox\"\n checked={allVisibleMembersSelected}\n ref={(input) => {\n if (input) {\n input.indeterminate = partiallySelectedMembers && !allVisibleMembersSelected;\n }\n }}\n onChange={(event) => toggleAllMembers(event.target.checked)}\n aria-label={tWithFallback(\n t,\n 'membersList.selectAllMembersAriaLabel',\n 'Select all workspace members'\n )}\n className=\"size-4 rounded border-border text-primary\"\n />\n <span>\n {tWithFallback(\n t,\n 'membersList.selectAllVisibleMembers',\n 'Select all visible members'\n )}\n </span>\n </label>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">\n {selectedMemberIds.size} {tWithFallback(t, 'membersList.selected', 'selected')}\n </span>\n {selectedMemberIds.size > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={clearMemberSelection}>\n {tWithFallback(t, 'membersList.clearSelection', 'Clear selection')}\n </Button>\n )}\n {canRemoveMember && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleBulkRemoveMembers}\n disabled={selectedMembers.length === 0 || isRemovingMembers}\n className=\"text-destructive\"\n >\n {tWithFallback(t, 'membersList.removeSelected', 'Remove Selected')}\n {selectedMembers.length > 0 ? ` (${selectedMembers.length})` : ''}\n </Button>\n )}\n </div>\n </div>\n )}\n\n {/* Loading State */}\n {isLoading && (\n <div className=\"space-y-3\">\n {[...Array(5)].map((_, i) => (\n <Skeleton key={i} className=\"h-20 w-full\" />\n ))}\n </div>\n )}\n\n {/* Error State */}\n {!isLoading && membersError && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"rounded-full bg-destructive/10 p-6 mb-4\">\n <AlertCircle size={48} className=\"text-destructive\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.failedToLoad', 'Failed to Load Members')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {membersError instanceof Error\n ? membersError.message\n : tWithFallback(\n t,\n 'membersList.errorLoadingMembers',\n 'An error occurred while loading members'\n )}\n </p>\n </div>\n )}\n\n {/* Empty State - No Workspace */}\n {!isLoading && !membersError && !workspaceId && (\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 <Users size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.noWorkspaceSelected', 'No Workspace Selected')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {tWithFallback(\n t,\n 'membersList.selectWorkspacePrompt',\n 'Select a workspace to view and manage its members'\n )}\n </p>\n </div>\n )}\n\n {/* Empty State - No Members */}\n {!isLoading && !membersError && workspaceId && !hasMembers && (\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 <Users size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.noMembersYet', 'No Members Yet')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm mb-4\">\n {tWithFallback(\n t,\n 'membersList.noMembersPrompt',\n 'Start building your team by inviting members to this workspace'\n )}\n </p>\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.MEMBER_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'membersList.noPermissionToInvite',\n \"You don't have permission to invite members\"\n )}\n >\n <Button onClick={handleInviteMember}>\n <UserPlus className=\"mr-2 size-4\" />\n {tWithFallback(t, 'membersList.inviteFirstMember', 'Invite Your First Member')}\n </Button>\n </PermissionButton>\n </div>\n )}\n\n {/* Empty State - No Search Results */}\n {!isLoading &&\n !membersError &&\n workspaceId &&\n hasMembers &&\n filteredMembers.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 <Search size={48} className=\"text-muted-foreground\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'membersList.noMembersFound', 'No Members Found')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {tWithFallback(\n t,\n 'membersList.noMembersFoundPrompt',\n 'No members match your search criteria. Try adjusting your search.'\n )}\n </p>\n </div>\n )}\n\n {/* Members List */}\n {!isLoading && filteredMembers.length > 0 && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'membersList.activeMembers', 'Active Members')} (\n {filteredMembers.length})\n </h2>\n </div>\n <div className=\"space-y-2\">\n {filteredMembers.map((member) => (\n <MemberListItem\n key={member.id}\n member={member}\n selected={selectedMemberIds.has(member.id)}\n onToggleSelect={(checked) => {\n const isSelected = selectedMemberIds.has(member.id);\n if (checked !== isSelected) {\n toggleMemberSelection(member.id);\n }\n }}\n canRemove={canRemoveMember}\n />\n ))}\n </div>\n </div>\n )}\n\n {/* Pending Invitations Section - Now at bottom */}\n {!isLoading && hasPendingInvitations && (\n <div className=\"space-y-3\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'membersList.pendingInvitationsHeader', 'Pending Invitations')}\n </h2>\n <div className=\"flex flex-col gap-3 rounded-lg border bg-card p-4 sm:flex-row sm:items-center sm:justify-between\">\n <label className=\"flex items-center gap-2 text-sm text-foreground\">\n <input\n type=\"checkbox\"\n checked={allVisibleInvitationsSelected}\n ref={(input) => {\n if (input) {\n input.indeterminate =\n partiallySelectedInvitations && !allVisibleInvitationsSelected;\n }\n }}\n onChange={(event) => toggleAllInvitations(event.target.checked)}\n aria-label={tWithFallback(\n t,\n 'membersList.selectAllInvitationsAriaLabel',\n 'Select all pending invitations'\n )}\n className=\"size-4 rounded border-border text-primary\"\n />\n <span>\n {tWithFallback(t, 'membersList.selectAllInvitations', 'Select all invitations')}\n </span>\n </label>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">\n {selectedInvitationIds.size}{' '}\n {tWithFallback(t, 'membersList.selected', 'selected')}\n </span>\n {selectedInvitationIds.size > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setSelectedInvitationIds(new Set())}\n >\n {tWithFallback(t, 'membersList.clearSelection', 'Clear selection')}\n </Button>\n )}\n {canInviteMember && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleBulkResendInvitations}\n disabled={selectedInvitations.length === 0 || isResending}\n >\n {tWithFallback(t, 'membersList.resendSelected', 'Resend Selected')}\n {selectedInvitations.length > 0 ? ` (${selectedInvitations.length})` : ''}\n </Button>\n )}\n </div>\n </div>\n <div className=\"space-y-2\">\n {pendingInvitations.map((invitation) => (\n <div\n key={invitation.id}\n className=\"flex items-center justify-between p-4 border rounded-lg bg-card\"\n >\n <div className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={selectedInvitationIds.has(invitation.id)}\n onChange={(event) =>\n toggleInvitationSelection(invitation.id, event.target.checked)\n }\n aria-label={`${tWithFallback(t, 'membersList.selectInvitationAriaLabel', 'Select invitation')} ${invitation.email}`}\n className=\"size-4 rounded border-border text-primary\"\n />\n <div className=\"size-10 rounded-full bg-status-warning/10 flex items-center justify-center transition-colors\">\n <Users className=\"size-5 text-status-warning\" />\n </div>\n <div>\n <p className=\"font-medium text-sm\">{invitation.email}</p>\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(t, 'membersList.invited', 'Invited')}{' '}\n {new Date(invitation.createdAt).toLocaleDateString()}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.MEMBER_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tWithFallback(\n t,\n 'membersList.noPermissionToResend',\n \"You don't have permission to resend invitations\"\n )}\n >\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleResendInvitation(invitation.id)}\n disabled={isResending && resendingId === invitation.id}\n >\n <RefreshCw\n className={`size-4 mr-1 ${isResending && resendingId === invitation.id ? 'animate-spin' : ''}`}\n />\n {isResending && resendingId === invitation.id\n ? tWithFallback(t, 'membersList.sending', 'Sending...')\n : tWithFallback(t, 'membersList.resend', 'Resend')}\n </Button>\n </PermissionButton>\n <Badge\n variant=\"outline\"\n className=\"bg-status-warning/10 text-status-warning border-status-warning/30 transition-colors\"\n >\n {tWithFallback(t, 'membersList.pending', 'Pending')}\n </Badge>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Dialogs */}\n <InviteMemberDialog workspaceId={workspaceId} />\n </PageContainer>\n );\n}\n"],"mappings":"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"}
@@ -4,32 +4,32 @@ import { useScopedNavigation as ee } from "../hooks/useScopedNavigation.js";
4
4
  import { tWithFallback as n } from "../utils/i18n.js";
5
5
  import { useWorkspacesPageView as te } from "../hooks/useWorkspacesPageView.js";
6
6
  import { nativeImpact as ne, nativeNotify as r } from "../utils/nativeBridge.js";
7
- import { useProject as re, useProjectMembersCount as i } from "../hooks/useProjects.js";
8
- import { useArchiveProject as a, useDeleteProject as o, useUnarchiveProject as s, useUpdateProject as c } from "../hooks/useProjectMutations.js";
9
- import { formatDate as l } from "../utils/formatters.js";
10
- import { normalizeProjectTags as u, toProjectTag as d } from "../utils/projectTags.js";
11
- import { useWorkspaceActivity as ie } from "../hooks/useWorkspaceActivity.js";
12
- import { useWorkspacePermissions as ae } from "../hooks/useWorkspacePermissions.js";
13
- import { useEffect as oe, useMemo as se, useState as f } from "react";
14
- import { Activity as p, Archive as m, ArrowLeft as h, Clock as g, FolderKanban as _, MoreVertical as ce, Users as v } from "lucide-react";
7
+ import { useProject as i, useProjectMembersCount as a } from "../hooks/useProjects.js";
8
+ import { useArchiveProject as o, useDeleteProject as s, useUnarchiveProject as re, useUpdateProject as ie } from "../hooks/useProjectMutations.js";
9
+ import { formatDate as c } from "../utils/formatters.js";
10
+ import { normalizeProjectTags as l, toProjectTag as u } from "../utils/projectTags.js";
11
+ import { useWorkspaceActivity as ae } from "../hooks/useWorkspaceActivity.js";
12
+ import { useWorkspacePermissions as oe } from "../hooks/useWorkspacePermissions.js";
13
+ import { ProjectTagsWidget as se } from "../components/tags/ProjectTagsWidget.js";
14
+ import { useEffect as ce, useMemo as d, useState as f } from "react";
15
+ import { Activity as p, Archive as m, ArrowLeft as h, Clock as g, FolderKanban as _, MoreVertical as le, Users as v } from "lucide-react";
15
16
  import { jsx as y, jsxs as b } from "react/jsx-runtime";
16
- import { AlertDialog as le, AlertDialogAction as ue, AlertDialogCancel as de, AlertDialogContent as fe, AlertDialogDescription as pe, AlertDialogFooter as me, AlertDialogHeader as he, AlertDialogTitle as ge, Badge as x, Button as S, Card as C, CardContent as w, CardHeader as T, CardTitle as E, DropdownMenu as D, DropdownMenuContent as O, DropdownMenuItem as k, DropdownMenuSeparator as A, DropdownMenuTrigger as j, Skeleton as M } from "@burdenoff/fe-libs/ui";
17
+ import { AlertDialog as ue, AlertDialogAction as de, AlertDialogCancel as fe, AlertDialogContent as pe, AlertDialogDescription as me, AlertDialogFooter as he, AlertDialogHeader as ge, AlertDialogTitle as _e, Badge as x, Button as S, Card as C, CardContent as w, CardHeader as T, CardTitle as E, DropdownMenu as D, DropdownMenuContent as O, DropdownMenuItem as k, DropdownMenuSeparator as A, DropdownMenuTrigger as j, Skeleton as M } from "@burdenoff/fe-libs/ui";
17
18
  import { useNavigate as N, useParams as P } from "react-router-dom";
18
19
  import { useI18n as F } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
19
- import { TagsWidget as I } from "@burdenoff/fe-libs/tag";
20
20
  //#region src/pages/ProjectDetailPage.tsx
21
- function L() {
22
- let { t: L } = F(), { workspaceId: R, projectId: z } = P();
21
+ function I() {
22
+ let { t: I } = F(), { workspaceId: L, projectId: R } = P();
23
23
  te("workspaces.project-detail", {
24
- workspaceId: R,
25
- projectId: z,
24
+ workspaceId: L,
25
+ projectId: R,
26
26
  requireParams: !0
27
27
  });
28
- let B = N(), { basePath: V = "/workspaces" } = e(), { withCurrentSearch: H } = ee(), { data: U, isLoading: _e, error: ve } = re(z || "", R), [ye, W] = f(!1), [G, K] = f(() => u(U?.tags)), { mutate: be, isPending: q } = a(R), { mutate: xe, isPending: J } = s(R), { mutate: Se, isPending: Y } = o(R), { mutateAsync: Ce, isPending: we } = c(R), { data: Te } = i(z || "", R), { data: Ee } = ie(R), De = (Ee ?? []).filter((e) => e.resourceId === z || e.resourceType?.toLowerCase() === "project").length, { canViewProject: Oe, canDeleteProject: X, canArchiveProject: Z, isLoading: ke } = ae();
29
- oe(() => {
30
- K(u(U?.tags));
31
- }, [U?.tags]);
32
- let Ae = se(() => G, [G]);
28
+ let z = N(), { basePath: B = "/workspaces" } = e(), { withCurrentSearch: V } = ee(), { data: H, isLoading: ve, error: ye } = i(R || "", L), [be, U] = f(!1), [W, G] = f(() => l(H?.tags)), { mutate: xe, isPending: K } = o(L), { mutate: Se, isPending: q } = re(L), { mutate: Ce, isPending: J } = s(L), { mutateAsync: we, isPending: Te } = ie(L), { data: Ee } = a(R || "", L), { data: De } = ae(L), Y = (De ?? []).filter((e) => e.resourceId === R || e.resourceType?.toLowerCase() === "project").length, { canViewProject: Oe, canDeleteProject: X, canArchiveProject: Z, isLoading: ke } = oe();
29
+ ce(() => {
30
+ G(l(H?.tags));
31
+ }, [H?.tags]);
32
+ let Ae = d(() => W, [W]);
33
33
  if (ke) return /* @__PURE__ */ b("div", {
34
34
  className: "space-y-4 p-6",
35
35
  children: [/* @__PURE__ */ y(M, { className: "h-10 w-1/3" }), /* @__PURE__ */ y(M, { className: "h-64" })]
@@ -40,44 +40,44 @@ function L() {
40
40
  className: "text-center space-y-2",
41
41
  children: [/* @__PURE__ */ y("h2", {
42
42
  className: "text-lg font-semibold",
43
- children: n(L, "projectDetail.accessDenied", "Access Denied")
43
+ children: n(I, "projectDetail.accessDenied", "Access Denied")
44
44
  }), /* @__PURE__ */ y("p", {
45
45
  className: "text-sm text-muted-foreground",
46
- children: n(L, "projectDetail.noPermissionToViewProject", "You don't have permission to view this project.")
46
+ children: n(I, "projectDetail.noPermissionToViewProject", "You don't have permission to view this project.")
47
47
  })]
48
48
  })
49
49
  });
50
50
  let Q = () => {
51
- B(H(`${V}/${R}/projects`));
51
+ z(V(`${B}/${L}/projects`));
52
52
  }, je = () => {
53
- U && (U.archived ? xe(U.id, { onError: (e) => {
53
+ H && (H.archived ? Se(H.id, { onError: (e) => {
54
54
  console.error("Failed to unarchive project:", e);
55
- } }) : be(U.id, { onError: (e) => {
55
+ } }) : xe(H.id, { onError: (e) => {
56
56
  console.error("Failed to archive project:", e);
57
57
  } }));
58
58
  }, Me = () => {
59
- U && (ne("medium"), Se(U.id, {
59
+ H && (ne("medium"), Ce(H.id, {
60
60
  onSuccess: () => {
61
- r("success"), W(!1), B(H(`${V}/${R}/projects`));
61
+ r("success"), U(!1), z(V(`${B}/${L}/projects`));
62
62
  },
63
63
  onError: (e) => {
64
64
  r("error"), console.error("Failed to delete project:", e);
65
65
  }
66
66
  }));
67
67
  }, $ = async (e) => {
68
- if (!U) return;
69
- let t = e.map((e) => d(e));
70
- K(t);
68
+ if (!H) return;
69
+ let t = e.map((e) => u(e));
70
+ G(t);
71
71
  try {
72
- await Ce({
73
- id: U.id,
72
+ await we({
73
+ id: H.id,
74
74
  input: { tags: t }
75
75
  });
76
76
  } catch (e) {
77
- throw K(u(U.tags)), e;
77
+ throw G(l(H.tags)), e;
78
78
  }
79
79
  };
80
- return _e ? /* @__PURE__ */ b("div", {
80
+ return ve ? /* @__PURE__ */ b("div", {
81
81
  className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
82
82
  children: [
83
83
  /* @__PURE__ */ y(M, { className: "h-10 w-32" }),
@@ -92,13 +92,13 @@ function L() {
92
92
  }),
93
93
  /* @__PURE__ */ y(M, { className: "h-48" })
94
94
  ]
95
- }) : ve || !U ? /* @__PURE__ */ b("div", {
95
+ }) : ye || !H ? /* @__PURE__ */ b("div", {
96
96
  className: "space-y-4 p-6",
97
97
  children: [/* @__PURE__ */ b(S, {
98
98
  variant: "ghost",
99
99
  onClick: Q,
100
100
  className: "gap-2",
101
- children: [/* @__PURE__ */ y(h, { size: 20 }), n(L, "projectDetail.backToProjects", "Back to Projects")]
101
+ children: [/* @__PURE__ */ y(h, { size: 20 }), n(I, "projectDetail.backToProjects", "Back to Projects")]
102
102
  }), /* @__PURE__ */ b("div", {
103
103
  className: "text-center py-12",
104
104
  children: [
@@ -111,18 +111,18 @@ function L() {
111
111
  }),
112
112
  /* @__PURE__ */ y("h3", {
113
113
  className: "text-lg font-semibold mb-2",
114
- children: n(L, "projectDetail.projectNotFound", "Project not found")
114
+ children: n(I, "projectDetail.projectNotFound", "Project not found")
115
115
  }),
116
116
  /* @__PURE__ */ y("p", {
117
117
  className: "text-muted-foreground max-w-sm mx-auto mb-4",
118
- children: n(L, "projectDetail.projectNotFoundDescription", "The project you're looking for doesn't exist or you don't have permission to view it.")
118
+ children: n(I, "projectDetail.projectNotFoundDescription", "The project you're looking for doesn't exist or you don't have permission to view it.")
119
119
  }),
120
120
  /* @__PURE__ */ b(S, {
121
121
  onClick: Q,
122
122
  children: [/* @__PURE__ */ y(h, {
123
123
  size: 16,
124
124
  className: "mr-2"
125
- }), n(L, "projectDetail.backToProjects", "Back to Projects")]
125
+ }), n(I, "projectDetail.backToProjects", "Back to Projects")]
126
126
  })
127
127
  ]
128
128
  })]
@@ -136,7 +136,7 @@ function L() {
136
136
  variant: "ghost",
137
137
  onClick: Q,
138
138
  className: "gap-2 mb-2 -ml-2",
139
- children: [/* @__PURE__ */ y(h, { size: 20 }), n(L, "projectDetail.backToProjects", "Back to Projects")]
139
+ children: [/* @__PURE__ */ y(h, { size: 20 }), n(I, "projectDetail.backToProjects", "Back to Projects")]
140
140
  }),
141
141
  /* @__PURE__ */ b("div", {
142
142
  className: "flex items-center gap-3",
@@ -148,24 +148,24 @@ function L() {
148
148
  })
149
149
  }), /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("h1", {
150
150
  className: "text-2xl sm:text-3xl font-bold",
151
- children: U.name
151
+ children: H.name
152
152
  }), /* @__PURE__ */ y("p", {
153
153
  className: "text-sm text-muted-foreground font-mono",
154
- children: U.key
154
+ children: H.key
155
155
  })] })]
156
156
  }),
157
157
  /* @__PURE__ */ b("div", {
158
158
  className: "flex items-center gap-2 mt-3",
159
159
  children: [/* @__PURE__ */ y(x, {
160
- className: `border ${t(U.status)}`,
161
- children: U.status
162
- }), U.archived && /* @__PURE__ */ b(x, {
160
+ className: `border ${t(H.status)}`,
161
+ children: H.status
162
+ }), H.archived && /* @__PURE__ */ b(x, {
163
163
  variant: "outline",
164
164
  className: "border-workspace-archived-border text-workspace-archived-text",
165
165
  children: [/* @__PURE__ */ y(m, {
166
166
  size: 12,
167
167
  className: "mr-1"
168
- }), n(L, "projectDetail.archived", "Archived")]
168
+ }), n(I, "projectDetail.archived", "Archived")]
169
169
  })]
170
170
  })
171
171
  ] }), /* @__PURE__ */ y("div", {
@@ -175,25 +175,25 @@ function L() {
175
175
  children: /* @__PURE__ */ y(S, {
176
176
  variant: "outline",
177
177
  size: "icon",
178
- "aria-label": n(L, "projectDetail.openProjectActionsAriaLabel", "Open project actions"),
179
- children: /* @__PURE__ */ y(ce, { size: 20 })
178
+ "aria-label": n(I, "projectDetail.openProjectActionsAriaLabel", "Open project actions"),
179
+ children: /* @__PURE__ */ y(le, { size: 20 })
180
180
  })
181
181
  }), /* @__PURE__ */ b(O, {
182
182
  align: "end",
183
183
  children: [
184
184
  Z && /* @__PURE__ */ b(k, {
185
185
  onClick: je,
186
- disabled: q || J,
186
+ disabled: K || q,
187
187
  children: [/* @__PURE__ */ y(m, {
188
188
  size: 16,
189
189
  className: "mr-2"
190
- }), q || J ? n(L, "projectDetail.processing", "Processing...") : U.archived ? n(L, "projectDetail.unarchive", "Unarchive") : n(L, "projectDetail.archive", "Archive")]
190
+ }), K || q ? n(I, "projectDetail.processing", "Processing...") : H.archived ? n(I, "projectDetail.unarchive", "Unarchive") : n(I, "projectDetail.archive", "Archive")]
191
191
  }),
192
192
  Z && X && /* @__PURE__ */ y(A, {}),
193
193
  X && /* @__PURE__ */ y(k, {
194
- onClick: () => W(!0),
194
+ onClick: () => U(!0),
195
195
  className: "text-destructive",
196
- children: n(L, "projectDetail.deleteProject", "Delete Project")
196
+ children: n(I, "projectDetail.deleteProject", "Delete Project")
197
197
  })
198
198
  ]
199
199
  })] })
@@ -208,14 +208,14 @@ function L() {
208
208
  children: [/* @__PURE__ */ y(v, {
209
209
  size: 20,
210
210
  className: "text-muted-foreground"
211
- }), n(L, "projectDetail.membersCardTitle", "Members")]
211
+ }), n(I, "projectDetail.membersCardTitle", "Members")]
212
212
  })
213
213
  }), /* @__PURE__ */ b(w, { children: [/* @__PURE__ */ y("p", {
214
214
  className: "text-3xl font-bold",
215
- children: Te ?? 0
215
+ children: Ee ?? 0
216
216
  }), /* @__PURE__ */ y("p", {
217
217
  className: "text-sm text-muted-foreground",
218
- children: n(L, "projectDetail.projectMembers", "Project members")
218
+ children: n(I, "projectDetail.projectMembers", "Project members")
219
219
  })] })] }), /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, {
220
220
  className: "flex flex-row items-center justify-between pb-2",
221
221
  children: /* @__PURE__ */ b(E, {
@@ -223,37 +223,36 @@ function L() {
223
223
  children: [/* @__PURE__ */ y(p, {
224
224
  size: 20,
225
225
  className: "text-muted-foreground"
226
- }), n(L, "projectDetail.activityCardTitle", "Activity")]
226
+ }), n(I, "projectDetail.activityCardTitle", "Activity")]
227
227
  })
228
228
  }), /* @__PURE__ */ b(w, { children: [/* @__PURE__ */ y("p", {
229
229
  className: "text-3xl font-bold",
230
- children: De
230
+ children: Y
231
231
  }), /* @__PURE__ */ y("p", {
232
232
  className: "text-sm text-muted-foreground",
233
- children: n(L, "projectDetail.recentActivityItems", "Recent activity items")
233
+ children: n(I, "projectDetail.recentActivityItems", "Recent activity items")
234
234
  })] })] })]
235
235
  }),
236
- /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ y(E, { children: n(L, "projectDetail.tagsTitle", "Tags") }) }), /* @__PURE__ */ b(w, {
236
+ /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ y(E, { children: n(I, "projectDetail.tagsTitle", "Tags") }) }), /* @__PURE__ */ b(w, {
237
237
  className: "space-y-3",
238
238
  children: [/* @__PURE__ */ y("p", {
239
239
  className: "text-sm text-muted-foreground",
240
- children: n(L, "projectDetail.tagsDescription", "Use universal tags to classify and filter this project across the workspace.")
241
- }), /* @__PURE__ */ y(I, {
240
+ children: n(I, "projectDetail.tagsDescription", "Use universal tags to classify and filter this project across the workspace.")
241
+ }), /* @__PURE__ */ y(se, {
242
242
  entityType: "Project",
243
- entityId: U.id,
244
- workspaceId: R,
243
+ entityId: H.id,
244
+ workspaceId: L,
245
245
  tags: Ae,
246
246
  onAdd: async (e) => {
247
- await $([...G, d(e)]);
247
+ await $([...W, u(e)]);
248
248
  },
249
249
  onRemove: async (e) => {
250
- await $(G.filter((t) => t.tagId !== e && t.id !== e));
250
+ await $(W.filter((t) => t.tagId !== e && t.id !== e));
251
251
  },
252
- syncGraphNotifications: !1,
253
- className: we ? "pointer-events-none opacity-75" : void 0
252
+ className: Te ? "pointer-events-none opacity-75" : void 0
254
253
  })]
255
254
  })] }),
256
- /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ y(E, { children: n(L, "projectDetail.projectInformation", "Project Information") }) }), /* @__PURE__ */ b(w, {
255
+ /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ y(E, { children: n(I, "projectDetail.projectInformation", "Project Information") }) }), /* @__PURE__ */ b(w, {
257
256
  className: "space-y-4",
258
257
  children: [/* @__PURE__ */ b("div", {
259
258
  className: "grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm",
@@ -262,105 +261,105 @@ function L() {
262
261
  className: "space-y-1",
263
262
  children: [/* @__PURE__ */ b("span", {
264
263
  className: "text-muted-foreground flex items-center gap-2",
265
- children: [/* @__PURE__ */ y(_, { size: 14 }), n(L, "projectDetail.projectId", "Project ID")]
264
+ children: [/* @__PURE__ */ y(_, { size: 14 }), n(I, "projectDetail.projectId", "Project ID")]
266
265
  }), /* @__PURE__ */ y("span", {
267
266
  className: "font-mono text-xs block",
268
- children: U.id
267
+ children: H.id
269
268
  })]
270
269
  }),
271
270
  /* @__PURE__ */ b("div", {
272
271
  className: "space-y-1",
273
272
  children: [/* @__PURE__ */ b("span", {
274
273
  className: "text-muted-foreground flex items-center gap-2",
275
- children: [/* @__PURE__ */ y(_, { size: 14 }), n(L, "projectDetail.projectKey", "Project Key")]
274
+ children: [/* @__PURE__ */ y(_, { size: 14 }), n(I, "projectDetail.projectKey", "Project Key")]
276
275
  }), /* @__PURE__ */ y("span", {
277
276
  className: "font-medium",
278
- children: U.key
277
+ children: H.key
279
278
  })]
280
279
  }),
281
280
  /* @__PURE__ */ b("div", {
282
281
  className: "space-y-1",
283
282
  children: [/* @__PURE__ */ b("span", {
284
283
  className: "text-muted-foreground flex items-center gap-2",
285
- children: [/* @__PURE__ */ y(g, { size: 14 }), n(L, "projectDetail.created", "Created")]
286
- }), /* @__PURE__ */ y("span", { children: l(U.createdAt) })]
284
+ children: [/* @__PURE__ */ y(g, { size: 14 }), n(I, "projectDetail.created", "Created")]
285
+ }), /* @__PURE__ */ y("span", { children: c(H.createdAt) })]
287
286
  }),
288
287
  /* @__PURE__ */ b("div", {
289
288
  className: "space-y-1",
290
289
  children: [/* @__PURE__ */ b("span", {
291
290
  className: "text-muted-foreground flex items-center gap-2",
292
- children: [/* @__PURE__ */ y(g, { size: 14 }), n(L, "projectDetail.lastUpdated", "Last Updated")]
293
- }), /* @__PURE__ */ y("span", { children: l(U.updatedAt) })]
291
+ children: [/* @__PURE__ */ y(g, { size: 14 }), n(I, "projectDetail.lastUpdated", "Last Updated")]
292
+ }), /* @__PURE__ */ y("span", { children: c(H.updatedAt) })]
294
293
  }),
295
294
  /* @__PURE__ */ b("div", {
296
295
  className: "space-y-1",
297
296
  children: [/* @__PURE__ */ b("span", {
298
297
  className: "text-muted-foreground flex items-center gap-2",
299
- children: [/* @__PURE__ */ y(v, { size: 14 }), n(L, "projectDetail.workspaceId", "Workspace ID")]
298
+ children: [/* @__PURE__ */ y(v, { size: 14 }), n(I, "projectDetail.workspaceId", "Workspace ID")]
300
299
  }), /* @__PURE__ */ y("span", {
301
300
  className: "font-mono text-xs block",
302
- children: U.workspaceId
301
+ children: H.workspaceId
303
302
  })]
304
303
  }),
305
304
  /* @__PURE__ */ b("div", {
306
305
  className: "space-y-1",
307
306
  children: [/* @__PURE__ */ b("span", {
308
307
  className: "text-muted-foreground flex items-center gap-2",
309
- children: [/* @__PURE__ */ y(v, { size: 14 }), n(L, "projectDetail.creatorId", "Creator ID")]
308
+ children: [/* @__PURE__ */ y(v, { size: 14 }), n(I, "projectDetail.creatorId", "Creator ID")]
310
309
  }), /* @__PURE__ */ y("span", {
311
310
  className: "font-mono text-xs block",
312
- children: U.creatorId
311
+ children: H.creatorId
313
312
  })]
314
313
  })
315
314
  ]
316
- }), U.config && Object.keys(U.config).length > 0 && /* @__PURE__ */ b("div", {
315
+ }), H.config && Object.keys(H.config).length > 0 && /* @__PURE__ */ b("div", {
317
316
  className: "pt-4 border-t",
318
317
  children: [/* @__PURE__ */ y("h4", {
319
318
  className: "text-sm font-medium mb-2",
320
- children: n(L, "projectDetail.configuration", "Configuration")
319
+ children: n(I, "projectDetail.configuration", "Configuration")
321
320
  }), /* @__PURE__ */ y("pre", {
322
321
  className: "text-xs bg-muted p-3 rounded-lg overflow-auto",
323
- children: JSON.stringify(U.config, null, 2)
322
+ children: JSON.stringify(H.config, null, 2)
324
323
  })]
325
324
  })]
326
325
  })] }),
327
- /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ y(E, { children: n(L, "projectDetail.quickActions", "Quick Actions") }) }), /* @__PURE__ */ y(w, { children: /* @__PURE__ */ b("div", {
326
+ /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ y(E, { children: n(I, "projectDetail.quickActions", "Quick Actions") }) }), /* @__PURE__ */ y(w, { children: /* @__PURE__ */ b("div", {
328
327
  className: "flex flex-wrap gap-2",
329
328
  children: [/* @__PURE__ */ b(S, {
330
329
  variant: "outline",
331
330
  size: "sm",
332
- onClick: () => B(H(`${V}/${R}/members`)),
331
+ onClick: () => z(V(`${B}/${L}/members`)),
333
332
  children: [/* @__PURE__ */ y(v, {
334
333
  size: 16,
335
334
  className: "mr-2"
336
- }), n(L, "projectDetail.workspaceMembers", "Workspace Members")]
335
+ }), n(I, "projectDetail.workspaceMembers", "Workspace Members")]
337
336
  }), /* @__PURE__ */ b(S, {
338
337
  variant: "outline",
339
338
  size: "sm",
340
- onClick: () => B(H(`${V}/${R}/activity`)),
339
+ onClick: () => z(V(`${B}/${L}/activity`)),
341
340
  children: [/* @__PURE__ */ y(p, {
342
341
  size: 16,
343
342
  className: "mr-2"
344
- }), n(L, "projectDetail.workspaceActivity", "Workspace Activity")]
343
+ }), n(I, "projectDetail.workspaceActivity", "Workspace Activity")]
345
344
  })]
346
345
  }) })] }),
347
- /* @__PURE__ */ y(le, {
348
- open: ye,
349
- onOpenChange: W,
350
- children: /* @__PURE__ */ b(fe, { children: [/* @__PURE__ */ b(he, { children: [/* @__PURE__ */ y(ge, { children: n(L, "projectDetail.deleteDialogTitle", "Delete Project") }), /* @__PURE__ */ y(pe, { children: n(L, "projectDetail.deleteConfirmPrefix", "Are you sure you want to delete \"") + U.name + n(L, "projectDetail.deleteConfirmSuffix", "\"? This action cannot be undone and all project data will be permanently removed.") })] }), /* @__PURE__ */ b(me, { children: [/* @__PURE__ */ y(de, {
351
- disabled: Y,
352
- children: n(L, "projectDetail.cancel", "Cancel")
353
- }), /* @__PURE__ */ y(ue, {
346
+ /* @__PURE__ */ y(ue, {
347
+ open: be,
348
+ onOpenChange: U,
349
+ children: /* @__PURE__ */ b(pe, { children: [/* @__PURE__ */ b(ge, { children: [/* @__PURE__ */ y(_e, { children: n(I, "projectDetail.deleteDialogTitle", "Delete Project") }), /* @__PURE__ */ y(me, { children: n(I, "projectDetail.deleteConfirmPrefix", "Are you sure you want to delete \"") + H.name + n(I, "projectDetail.deleteConfirmSuffix", "\"? This action cannot be undone and all project data will be permanently removed.") })] }), /* @__PURE__ */ b(he, { children: [/* @__PURE__ */ y(fe, {
350
+ disabled: J,
351
+ children: n(I, "projectDetail.cancel", "Cancel")
352
+ }), /* @__PURE__ */ y(de, {
354
353
  onClick: Me,
355
- disabled: Y,
354
+ disabled: J,
356
355
  className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
357
- children: Y ? n(L, "projectDetail.deleting", "Deleting...") : n(L, "projectDetail.deleteProject", "Delete Project")
356
+ children: J ? n(I, "projectDetail.deleting", "Deleting...") : n(I, "projectDetail.deleteProject", "Delete Project")
358
357
  })] })] })
359
358
  })
360
359
  ]
361
360
  });
362
361
  }
363
362
  //#endregion
364
- export { L as ProjectDetailPage };
363
+ export { I as ProjectDetailPage };
365
364
 
366
365
  //# sourceMappingURL=ProjectDetailPage.js.map