@burdenoff/microfe-workspaces 2026.510.50 → 2026.511.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 (69) hide show
  1. package/dist/generated/wspace-operations.d.ts +91 -0
  2. package/dist/generated/wspace-operations.d.ts.map +1 -1
  3. package/dist/generated/wspace-operations.js +79 -51
  4. package/dist/generated/wspace-operations.js.map +1 -1
  5. package/dist/hooks/useMemberMutations.d.ts.map +1 -1
  6. package/dist/hooks/useMemberMutations.js +141 -60
  7. package/dist/hooks/useMemberMutations.js.map +1 -1
  8. package/dist/hooks/useProjectMutations.d.ts.map +1 -1
  9. package/dist/hooks/useProjectMutations.js +84 -44
  10. package/dist/hooks/useProjectMutations.js.map +1 -1
  11. package/dist/hooks/useWorkspaceMutations.d.ts.map +1 -1
  12. package/dist/hooks/useWorkspaceMutations.js +64 -29
  13. package/dist/hooks/useWorkspaceMutations.js.map +1 -1
  14. package/dist/hooks/useWorkspacesEventEmitter.d.ts +5 -1
  15. package/dist/hooks/useWorkspacesEventEmitter.d.ts.map +1 -1
  16. package/dist/hooks/useWorkspacesEventEmitter.js +8 -7
  17. package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
  18. package/dist/hooks/useWorkspacesPageView.d.ts +27 -0
  19. package/dist/hooks/useWorkspacesPageView.d.ts.map +1 -0
  20. package/dist/hooks/useWorkspacesPageView.js +29 -0
  21. package/dist/hooks/useWorkspacesPageView.js.map +1 -0
  22. package/dist/pages/ActivityListPage.d.ts.map +1 -1
  23. package/dist/pages/ActivityListPage.js +59 -56
  24. package/dist/pages/ActivityListPage.js.map +1 -1
  25. package/dist/pages/CreateWorkspacePage.d.ts.map +1 -1
  26. package/dist/pages/CreateWorkspacePage.js +104 -104
  27. package/dist/pages/CreateWorkspacePage.js.map +1 -1
  28. package/dist/pages/InviteAcceptancePage.d.ts.map +1 -1
  29. package/dist/pages/InviteAcceptancePage.js +197 -216
  30. package/dist/pages/InviteAcceptancePage.js.map +1 -1
  31. package/dist/pages/MembersListPage.d.ts.map +1 -1
  32. package/dist/pages/MembersListPage.js +142 -138
  33. package/dist/pages/MembersListPage.js.map +1 -1
  34. package/dist/pages/ProjectDetailPage.d.ts.map +1 -1
  35. package/dist/pages/ProjectDetailPage.js +181 -176
  36. package/dist/pages/ProjectDetailPage.js.map +1 -1
  37. package/dist/pages/ProjectsListPage.d.ts.map +1 -1
  38. package/dist/pages/ProjectsListPage.js +175 -171
  39. package/dist/pages/ProjectsListPage.js.map +1 -1
  40. package/dist/pages/WorkspaceDetailPage.d.ts.map +1 -1
  41. package/dist/pages/WorkspaceDetailPage.js +104 -101
  42. package/dist/pages/WorkspaceDetailPage.js.map +1 -1
  43. package/dist/pages/WorkspaceSettingsPage.d.ts.map +1 -1
  44. package/dist/pages/WorkspaceSettingsPage.js +182 -137
  45. package/dist/pages/WorkspaceSettingsPage.js.map +1 -1
  46. package/dist/pages/WorkspacesListPage.d.ts.map +1 -1
  47. package/dist/pages/WorkspacesListPage.js +77 -77
  48. package/dist/pages/WorkspacesListPage.js.map +1 -1
  49. package/dist/pages/dashboard/DashboardCustomizer.d.ts.map +1 -1
  50. package/dist/pages/dashboard/DashboardCustomizer.js +53 -55
  51. package/dist/pages/dashboard/DashboardCustomizer.js.map +1 -1
  52. package/dist/pages/dashboard/DashboardGrid.d.ts.map +1 -1
  53. package/dist/pages/dashboard/DashboardGrid.js +33 -36
  54. package/dist/pages/dashboard/DashboardGrid.js.map +1 -1
  55. package/dist/pages/dashboard/DashboardPage.d.ts.map +1 -1
  56. package/dist/pages/dashboard/DashboardPage.js +67 -65
  57. package/dist/pages/dashboard/DashboardPage.js.map +1 -1
  58. package/dist/pages/dashboard/WidgetWrapper.d.ts.map +1 -1
  59. package/dist/pages/dashboard/WidgetWrapper.js +3 -6
  60. package/dist/pages/dashboard/WidgetWrapper.js.map +1 -1
  61. package/dist/utils/i18n.d.ts +13 -0
  62. package/dist/utils/i18n.d.ts.map +1 -0
  63. package/dist/utils/i18n.js +12 -0
  64. package/dist/utils/i18n.js.map +1 -0
  65. package/dist/utils/telemetryError.d.ts +2 -0
  66. package/dist/utils/telemetryError.d.ts.map +1 -0
  67. package/dist/utils/telemetryError.js +28 -0
  68. package/dist/utils/telemetryError.js.map +1 -0
  69. package/package.json +9 -4
@@ -1 +1 @@
1
- {"version":3,"file":"MembersListPage.js","names":[],"sources":["../../src/pages/MembersListPage.tsx"],"sourcesContent":["import { useCallback, 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 { 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 { MemberListItem } from '../components/MemberListItem';\nimport { InviteMemberDialog } from '../components/InviteMemberDialog';\nimport type { Workspace } from '../types';\n\nexport function MembersListPage() {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\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 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 {tr('membersList.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\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 = `${tr('membersList.bulkRemoveConfirmPrefix', 'Remove')} ${selectedMembers.length} ${\n selectedMembers.length === 1\n ? tr('membersList.bulkRemoveConfirmSingular', 'selected member')\n : tr('membersList.bulkRemoveConfirmPlural', 'selected members')\n } ${tr('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 {tr('membersList.pageTitle', 'Members')}\n </h1>\n <p className=\"text-muted-foreground text-sm sm:text-base\">\n {tr('membersList.pageSubtitle', 'Manage workspace members and invitations')}\n </p>\n </div>\n\n <div className=\"flex gap-2\">\n <PermissionButton\n permission={WORKSPACE_PERMISSIONS.MEMBER_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip={tr(\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 {tr('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={tr('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 ? tr('membersList.pendingInvitations', 'Pending Invitations')\n : tr('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={tr(\n 'membersList.selectAllMembersAriaLabel',\n 'Select all workspace members'\n )}\n className=\"h-4 w-4 rounded border-border text-primary\"\n />\n <span>{tr('membersList.selectAllVisibleMembers', 'Select all visible members')}</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} {tr('membersList.selected', 'selected')}\n </span>\n {selectedMemberIds.size > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={clearMemberSelection}>\n {tr('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 {tr('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 {tr('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 : tr('membersList.errorLoadingMembers', 'An error occurred while loading members')}\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 {tr('membersList.noWorkspaceSelected', 'No Workspace Selected')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {tr(\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 {tr('membersList.noMembersYet', 'No Members Yet')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm mb-4\">\n {tr(\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={tr(\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 {tr('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 {tr('membersList.noMembersFound', 'No Members Found')}\n </h3>\n <p className=\"text-muted-foreground max-w-sm\">\n {tr(\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 {tr('membersList.activeMembers', 'Active Members')} ({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 {tr('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={tr(\n 'membersList.selectAllInvitationsAriaLabel',\n 'Select all pending invitations'\n )}\n className=\"h-4 w-4 rounded border-border text-primary\"\n />\n <span>{tr('membersList.selectAllInvitations', 'Select all invitations')}</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} {tr('membersList.selected', 'selected')}\n </span>\n {selectedInvitationIds.size > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setSelectedInvitationIds(new Set())}\n >\n {tr('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 {tr('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={`${tr('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 {tr('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={tr(\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 ? tr('membersList.sending', 'Sending...')\n : tr('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 {tr('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 } 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 +1 @@
1
- {"version":3,"file":"ProjectDetailPage.d.ts","sourceRoot":"","sources":["../../src/pages/ProjectDetailPage.tsx"],"names":[],"mappings":"AAmDA,wBAAgB,iBAAiB,4CAqbhC"}
1
+ {"version":3,"file":"ProjectDetailPage.d.ts","sourceRoot":"","sources":["../../src/pages/ProjectDetailPage.tsx"],"names":[],"mappings":"AAqDA,wBAAgB,iBAAiB,4CAichC"}