@burdenoff/microfe-organization 2026.1026.1 → 2026.1101.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 (172) hide show
  1. package/dist/generated/global-operations.js +57 -58
  2. package/dist/generated/global-operations.js.map +1 -1
  3. package/dist/generated/global-types.js +1 -2
  4. package/dist/generated/global-types.js.map +1 -1
  5. package/dist/node_modules/sonner/dist/index.js +2 -3
  6. package/dist/node_modules/sonner/dist/index.js.map +1 -1
  7. package/dist/node_modules/zod/v4/classic/errors.js +44 -0
  8. package/dist/node_modules/zod/v4/classic/errors.js.map +1 -0
  9. package/dist/node_modules/zod/v4/classic/parse.js +7 -0
  10. package/dist/node_modules/zod/v4/classic/parse.js.map +1 -0
  11. package/dist/node_modules/zod/v4/classic/schemas.js +652 -0
  12. package/dist/node_modules/zod/v4/classic/schemas.js.map +1 -0
  13. package/dist/node_modules/zod/v4/core/api.js +429 -0
  14. package/dist/node_modules/zod/v4/core/api.js.map +1 -0
  15. package/dist/node_modules/zod/v4/core/checks.js +143 -0
  16. package/dist/node_modules/zod/v4/core/checks.js.map +1 -0
  17. package/dist/node_modules/zod/v4/core/core.js +84 -0
  18. package/dist/node_modules/zod/v4/core/core.js.map +1 -0
  19. package/dist/node_modules/zod/v4/core/doc.js +29 -0
  20. package/dist/node_modules/zod/v4/core/doc.js.map +1 -0
  21. package/dist/node_modules/zod/v4/core/errors.js +90 -0
  22. package/dist/node_modules/zod/v4/core/errors.js.map +1 -0
  23. package/dist/node_modules/zod/v4/core/json-schema-processors.js +285 -0
  24. package/dist/node_modules/zod/v4/core/json-schema-processors.js.map +1 -0
  25. package/dist/node_modules/zod/v4/core/memoizer.js +188 -0
  26. package/dist/node_modules/zod/v4/core/memoizer.js.map +1 -0
  27. package/dist/node_modules/zod/v4/core/parse.js +159 -0
  28. package/dist/node_modules/zod/v4/core/parse.js.map +1 -0
  29. package/dist/node_modules/zod/v4/core/regexes.js +34 -0
  30. package/dist/node_modules/zod/v4/core/regexes.js.map +1 -0
  31. package/dist/node_modules/zod/v4/core/registries.js +41 -0
  32. package/dist/node_modules/zod/v4/core/registries.js.map +1 -0
  33. package/dist/node_modules/zod/v4/core/schemas.js +979 -0
  34. package/dist/node_modules/zod/v4/core/schemas.js.map +1 -0
  35. package/dist/node_modules/zod/v4/core/to-json-schema.js +330 -0
  36. package/dist/node_modules/zod/v4/core/to-json-schema.js.map +1 -0
  37. package/dist/node_modules/zod/v4/core/util.js +417 -0
  38. package/dist/node_modules/zod/v4/core/util.js.map +1 -0
  39. package/dist/node_modules/zod/v4/core/versions.js +9 -0
  40. package/dist/node_modules/zod/v4/core/versions.js.map +1 -0
  41. package/dist/node_modules/zod/v4/locales/en.js +96 -0
  42. package/dist/node_modules/zod/v4/locales/en.js.map +1 -0
  43. package/dist/organization-management/AdminOrganizationRoot.js +13 -10
  44. package/dist/organization-management/AdminOrganizationRoot.js.map +1 -1
  45. package/dist/organization-management/AdminOrganizationRoutes.js +8 -9
  46. package/dist/organization-management/AdminOrganizationRoutes.js.map +1 -1
  47. package/dist/organization-management/UserOrganizationRoot.js +13 -10
  48. package/dist/organization-management/UserOrganizationRoot.js.map +1 -1
  49. package/dist/organization-management/UserOrganizationRoutes.js +1 -2
  50. package/dist/organization-management/UserOrganizationRoutes.js.map +1 -1
  51. package/dist/organization-management/constants/permissions.js +1 -2
  52. package/dist/organization-management/constants/permissions.js.map +1 -1
  53. package/dist/organization-management/hooks/useOrganizationEventEmitter.js +1 -2
  54. package/dist/organization-management/hooks/useOrganizationEventEmitter.js.map +1 -1
  55. package/dist/organization-management/hooks/useOrganizationPageView.js +1 -2
  56. package/dist/organization-management/hooks/useOrganizationPageView.js.map +1 -1
  57. package/dist/organization-management/modules/members/components/BulkInviteForm.js +3 -3
  58. package/dist/organization-management/modules/members/components/BulkInviteForm.js.map +1 -1
  59. package/dist/organization-management/modules/members/components/InviteMemberForm.js +1 -2
  60. package/dist/organization-management/modules/members/components/InviteMemberForm.js.map +1 -1
  61. package/dist/organization-management/modules/members/components/InviteStatusBadge.js +1 -2
  62. package/dist/organization-management/modules/members/components/InviteStatusBadge.js.map +1 -1
  63. package/dist/organization-management/modules/members/components/MemberRoleBadge.js +1 -2
  64. package/dist/organization-management/modules/members/components/MemberRoleBadge.js.map +1 -1
  65. package/dist/organization-management/modules/members/components/MyInviteCard.js +5 -6
  66. package/dist/organization-management/modules/members/components/MyInviteCard.js.map +1 -1
  67. package/dist/organization-management/modules/members/components/PendingInvitesList.js +8 -9
  68. package/dist/organization-management/modules/members/components/PendingInvitesList.js.map +1 -1
  69. package/dist/organization-management/modules/members/hooks/useInvites.js +2 -3
  70. package/dist/organization-management/modules/members/hooks/useInvites.js.map +1 -1
  71. package/dist/organization-management/modules/members/hooks/useMembers.js +1 -2
  72. package/dist/organization-management/modules/members/hooks/useMembers.js.map +1 -1
  73. package/dist/organization-management/modules/members/hooks/useWorkspaceInvites.js +1 -2
  74. package/dist/organization-management/modules/members/hooks/useWorkspaceInvites.js.map +1 -1
  75. package/dist/organization-management/modules/members/pages/InviteMemberPage.js +16 -17
  76. package/dist/organization-management/modules/members/pages/InviteMemberPage.js.map +1 -1
  77. package/dist/organization-management/modules/members/pages/InvitePeoplePage.js +14 -15
  78. package/dist/organization-management/modules/members/pages/InvitePeoplePage.js.map +1 -1
  79. package/dist/organization-management/modules/members/pages/MemberDetailPage.js +18 -19
  80. package/dist/organization-management/modules/members/pages/MemberDetailPage.js.map +1 -1
  81. package/dist/organization-management/modules/members/pages/MembersListPage.js +142 -143
  82. package/dist/organization-management/modules/members/pages/MembersListPage.js.map +1 -1
  83. package/dist/organization-management/modules/members/pages/MyInvitesPage.js +168 -169
  84. package/dist/organization-management/modules/members/pages/MyInvitesPage.js.map +1 -1
  85. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js +13 -14
  86. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js.map +1 -1
  87. package/dist/organization-management/modules/members/utils/bulkInviteCsv.js +4 -10
  88. package/dist/organization-management/modules/members/utils/bulkInviteCsv.js.map +1 -1
  89. package/dist/organization-management/modules/members/utils/workspaceInvitationDisplay.js +1 -2
  90. package/dist/organization-management/modules/members/utils/workspaceInvitationDisplay.js.map +1 -1
  91. package/dist/organization-management/modules/organizations/components/OrganizationForm.js +14 -15
  92. package/dist/organization-management/modules/organizations/components/OrganizationForm.js.map +1 -1
  93. package/dist/organization-management/modules/organizations/components/OrganizationStatusBadge.js +1 -2
  94. package/dist/organization-management/modules/organizations/components/OrganizationStatusBadge.js.map +1 -1
  95. package/dist/organization-management/modules/organizations/hooks/useOrganizations.js +2 -3
  96. package/dist/organization-management/modules/organizations/hooks/useOrganizations.js.map +1 -1
  97. package/dist/organization-management/modules/organizations/hooks/useOrgsWithPermission.js +22 -21
  98. package/dist/organization-management/modules/organizations/hooks/useOrgsWithPermission.js.map +1 -1
  99. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js +18 -19
  100. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js.map +1 -1
  101. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js +29 -30
  102. package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map +1 -1
  103. package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js +14 -15
  104. package/dist/organization-management/modules/organizations/pages/OrganizationEditPage.js.map +1 -1
  105. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js +33 -34
  106. package/dist/organization-management/modules/organizations/pages/OrganizationsListPage.js.map +1 -1
  107. package/dist/organization-management/modules/organizations/schemas/index.js +11 -12
  108. package/dist/organization-management/modules/organizations/schemas/index.js.map +1 -1
  109. package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js +16 -24
  110. package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js.map +1 -1
  111. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js +5 -6
  112. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js.map +1 -1
  113. package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js +31 -32
  114. package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js.map +1 -1
  115. package/dist/organization-management/modules/workspaces/components/WorkspaceStatusBadge.js +1 -2
  116. package/dist/organization-management/modules/workspaces/components/WorkspaceStatusBadge.js.map +1 -1
  117. package/dist/organization-management/modules/workspaces/hooks/useWorkspaceMembers.js +1 -2
  118. package/dist/organization-management/modules/workspaces/hooks/useWorkspaceMembers.js.map +1 -1
  119. package/dist/organization-management/modules/workspaces/hooks/useWorkspaces.js +11 -12
  120. package/dist/organization-management/modules/workspaces/hooks/useWorkspaces.js.map +1 -1
  121. package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js +18 -19
  122. package/dist/organization-management/modules/workspaces/pages/WorkspaceCreatePage.js.map +1 -1
  123. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js +43 -44
  124. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js.map +1 -1
  125. package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js +19 -20
  126. package/dist/organization-management/modules/workspaces/pages/WorkspaceEditPage.js.map +1 -1
  127. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js +240 -241
  128. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js.map +1 -1
  129. package/dist/organization-management/modules/workspaces/schemas/index.js +6 -7
  130. package/dist/organization-management/modules/workspaces/schemas/index.js.map +1 -1
  131. package/dist/organization-management/providers/OrgConsoleProvider.js +1 -2
  132. package/dist/organization-management/providers/OrgConsoleProvider.js.map +1 -1
  133. package/dist/organization-management/providers/OrgScopedPermissions.js +1 -2
  134. package/dist/organization-management/providers/OrgScopedPermissions.js.map +1 -1
  135. package/dist/organization-management/shared/components/dialog/ConfirmDialog.js +1 -2
  136. package/dist/organization-management/shared/components/dialog/ConfirmDialog.js.map +1 -1
  137. package/dist/organization-management/shared/components/dialog/ConfirmDialogView.js +1 -2
  138. package/dist/organization-management/shared/components/dialog/ConfirmDialogView.js.map +1 -1
  139. package/dist/organization-management/shared/components/feedback/ErrorState.js +1 -2
  140. package/dist/organization-management/shared/components/feedback/ErrorState.js.map +1 -1
  141. package/dist/organization-management/shared/components/feedback/LoadingState.js +1 -2
  142. package/dist/organization-management/shared/components/feedback/LoadingState.js.map +1 -1
  143. package/dist/organization-management/shared/components/input/SearchInput.js +1 -2
  144. package/dist/organization-management/shared/components/input/SearchInput.js.map +1 -1
  145. package/dist/organization-management/shared/components/input/SelectionCheckbox.js +1 -2
  146. package/dist/organization-management/shared/components/input/SelectionCheckbox.js.map +1 -1
  147. package/dist/organization-management/shared/hooks/useDebouncedValue.js +1 -2
  148. package/dist/organization-management/shared/hooks/useDebouncedValue.js.map +1 -1
  149. package/dist/organization-management/shared/hooks/useTr.js +1 -2
  150. package/dist/organization-management/shared/hooks/useTr.js.map +1 -1
  151. package/dist/organization-management/shared/logger.js +1 -2
  152. package/dist/organization-management/shared/logger.js.map +1 -1
  153. package/dist/organization-management/shared/recaptcha.js +1 -2
  154. package/dist/organization-management/shared/recaptcha.js.map +1 -1
  155. package/dist/organization-management/shared/types/graphql.js +1 -2
  156. package/dist/organization-management/shared/types/graphql.js.map +1 -1
  157. package/dist/utils/nativeBridge.js +1 -2
  158. package/package.json +7 -6
  159. package/dist/node_modules/zod/v3/ZodError.js +0 -82
  160. package/dist/node_modules/zod/v3/ZodError.js.map +0 -1
  161. package/dist/node_modules/zod/v3/errors.js +0 -10
  162. package/dist/node_modules/zod/v3/errors.js.map +0 -1
  163. package/dist/node_modules/zod/v3/helpers/errorUtil.js +0 -9
  164. package/dist/node_modules/zod/v3/helpers/errorUtil.js.map +0 -1
  165. package/dist/node_modules/zod/v3/helpers/parseUtil.js +0 -93
  166. package/dist/node_modules/zod/v3/helpers/parseUtil.js.map +0 -1
  167. package/dist/node_modules/zod/v3/helpers/util.js +0 -76
  168. package/dist/node_modules/zod/v3/helpers/util.js.map +0 -1
  169. package/dist/node_modules/zod/v3/locales/en.js +0 -62
  170. package/dist/node_modules/zod/v3/locales/en.js.map +0 -1
  171. package/dist/node_modules/zod/v3/types.js +0 -2441
  172. package/dist/node_modules/zod/v3/types.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MyInvitesPage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/MyInvitesPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { NavLink } from 'react-router';\nimport { Mail, Loader2, AlertCircle, BriefcaseBusiness } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n ActorIdentity,\n useActorProfiles,\n type ActorInput,\n type ActorProfileMap,\n} from '@burdenoff/fe-libs/shared';\nimport { Badge, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMyInvites, useAcceptInvite, useRejectInvite } from '../hooks/useInvites';\nimport {\n useAcceptWorkspaceInvite,\n useMyWorkspaceInvites,\n useRejectWorkspaceInvite,\n} from '../hooks/useWorkspaceInvites';\nimport { MyInviteCard } from '../components/MyInviteCard';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { InviteStatus as OrganizationInviteStatus } from '../../../../generated/global-types';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport {\n getProjectDisplayNames,\n getRoleDisplayNames,\n getWorkspaceDisplayName,\n} from '../utils/workspaceInvitationDisplay';\n\n/**\n * My Invites Page\n * Shows pending invites for the current user with accept/reject actions\n */\ntype MyInvitesTab = 'workspace' | 'organization';\n\ninterface MyInvitesPageProps {\n activeTab?: MyInvitesTab;\n}\n\ninterface TabActionError {\n tab: MyInvitesTab;\n message: string;\n}\n\ninterface InvitesTabNavProps {\n activeTab: MyInvitesTab;\n basePath: string;\n tr: ReturnType<typeof useTr>;\n}\n\nfunction formatDate(value?: string | null) {\n if (!value) return null;\n\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n\n return date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction joinPath(base: string, path: string): string {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n}\n\nfunction InvitesTabNav({ activeTab, basePath, tr }: InvitesTabNavProps) {\n const getTabClassName = (isActive: boolean) =>\n [\n 'border-b-2 px-4 py-2 text-sm font-medium transition-colors',\n isActive\n ? 'border-[var(--color-border-focus)] text-[var(--color-text-primary)]'\n : 'border-transparent text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]',\n ].join(' ');\n\n return (\n <div className=\"mb-6 flex gap-2 border-b border-[var(--color-border-default)]\">\n <NavLink\n to={joinPath(basePath, '/invites')}\n end\n className={getTabClassName(activeTab === 'workspace')}\n >\n {tr('members.myInvites.workspaceTab', 'Workspace Invites')}\n </NavLink>\n <NavLink\n to={joinPath(basePath, '/invites/organizations')}\n className={getTabClassName(activeTab === 'organization')}\n >\n {tr('members.myInvites.organizationTab', 'Organization Invites')}\n </NavLink>\n </div>\n );\n}\n\nexport function MyInvitesPage({ activeTab = 'workspace' }: MyInvitesPageProps) {\n useOrganizationPageView(\n activeTab === 'workspace'\n ? 'organizations.my-workspace-invites'\n : 'organizations.my-organization-invites'\n );\n const tr = useTr();\n const { isLoading: permissionsLoading } = usePermissions();\n const { basePath = '/organizations', currentUser, authToken, apiGatewayUrl } = useOrgConsole();\n const orgInvitesEnabled = activeTab === 'organization';\n const workspaceInvitesEnabled = activeTab === 'workspace';\n const { invites, loading, error, total } = useMyInvites(\n OrganizationInviteStatus.Pending,\n 20,\n 0,\n orgInvitesEnabled\n );\n const {\n invites: workspaceInvites,\n loading: workspaceLoading,\n error: workspaceError,\n total: workspaceTotal,\n refetch: refetchWorkspaceInvites,\n } = useMyWorkspaceInvites(currentUser?.email, workspaceInvitesEnabled);\n const { acceptInvite, loading: accepting } = useAcceptInvite();\n const { rejectInvite, loading: rejecting } = useRejectInvite();\n const { acceptInvite: acceptWorkspaceInvite, loading: acceptingWorkspace } =\n useAcceptWorkspaceInvite();\n const { rejectInvite: rejectWorkspaceInvite, loading: rejectingWorkspace } =\n useRejectWorkspaceInvite();\n const [actionError, setActionError] = useState<TabActionError | null>(null);\n\n const visibleActionError = actionError?.tab === activeTab ? actionError.message : null;\n const [processingWorkspaceAction, setProcessingWorkspaceAction] = useState<{\n inviteId: string;\n action: 'accept' | 'reject';\n } | null>(null);\n\n const workspaceInviteActors = useMemo<ActorInput[]>(\n () =>\n workspaceInvites.flatMap((invite) =>\n invite.invitedById ? [{ actorId: invite.invitedById, actorType: 'user' as const }] : []\n ),\n [workspaceInvites]\n );\n\n const inviterProfiles: ActorProfileMap = useActorProfiles(workspaceInviteActors, {\n apiGatewayUrl,\n authToken,\n });\n\n const sortedWorkspaceInvites = useMemo(\n () =>\n [...workspaceInvites].sort(\n (left: (typeof workspaceInvites)[number], right: (typeof workspaceInvites)[number]) =>\n new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime()\n ),\n [workspaceInvites]\n );\n\n const totalCount = activeTab === 'workspace' ? workspaceTotal : total;\n\n const handleAccept = async (inviteId: string) => {\n try {\n setActionError(null);\n await acceptInvite(inviteId);\n } catch (err) {\n setActionError({\n tab: 'organization',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.acceptFailed', 'Failed to accept invite'),\n });\n }\n };\n\n const handleReject = async (inviteId: string) => {\n try {\n setActionError(null);\n await rejectInvite(inviteId);\n } catch (err) {\n setActionError({\n tab: 'organization',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.rejectFailed', 'Failed to reject invite'),\n });\n }\n };\n\n const handleAcceptWorkspace = async (inviteId: string) => {\n try {\n setProcessingWorkspaceAction({ inviteId, action: 'accept' });\n setActionError(null);\n await acceptWorkspaceInvite(inviteId);\n await refetchWorkspaceInvites().catch(() => undefined);\n } catch (err) {\n setActionError({\n tab: 'workspace',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.workspaceAcceptFailed', 'Failed to accept workspace invite'),\n });\n } finally {\n setProcessingWorkspaceAction((current) =>\n current?.inviteId === inviteId && current.action === 'accept' ? null : current\n );\n }\n };\n\n const handleRejectWorkspace = async (inviteId: string) => {\n try {\n setProcessingWorkspaceAction({ inviteId, action: 'reject' });\n setActionError(null);\n await rejectWorkspaceInvite(inviteId);\n await refetchWorkspaceInvites().catch(() => undefined);\n } catch (err) {\n setActionError({\n tab: 'workspace',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.workspaceRejectFailed', 'Failed to reject workspace invite'),\n });\n } finally {\n setProcessingWorkspaceAction((current) =>\n current?.inviteId === inviteId && current.action === 'reject' ? null : current\n );\n }\n };\n\n // Own invites are always accessible — no permission denial needed.\n // We still wait for permissions to load to ensure consistent UX.\n if (permissionsLoading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <LoadingState message={tr('common.loadingPermissions', 'Loading permissions...')} />\n </div>\n );\n }\n\n if (workspaceInvitesEnabled && !currentUser?.email) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-6 text-center\">\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr('members.myInvites.signInWorkspace', 'Sign in to view your workspace invites.')}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n if (orgInvitesEnabled && loading && invites.length === 0) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"flex items-center justify-center min-h-[300px] rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={24} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </div>\n </div>\n );\n }\n\n if (workspaceInvitesEnabled && workspaceLoading && workspaceInvites.length === 0) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"flex items-center justify-center min-h-[300px] rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={24} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </div>\n </div>\n );\n }\n\n if (orgInvitesEnabled && error) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"rounded-xl border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-6 text-center\">\n <p className=\"text-[var(--color-status-error-text)]\">\n {tr('members.myInvites.loadFailed', 'Failed to load invites')}: {error.message}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n if (workspaceInvitesEnabled && workspaceError) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"rounded-xl border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-6 text-center\">\n <p className=\"text-[var(--color-status-error-text)]\">\n {tr('members.myInvites.workspaceLoadFailed', 'Failed to load workspace invites')}:{' '}\n {workspaceError.message}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n {/* Header */}\n <div className=\"flex items-center gap-3 mb-6\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n {totalCount > 0 && (\n <span className=\"px-2.5 py-0.5 rounded-full text-xs font-medium bg-[var(--color-action-primary-bg)] text-[var(--color-action-primary-text)]\">\n {totalCount}\n </span>\n )}\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <PagePurpose className=\"mb-4 max-w-3xl\">\n {tr(\n 'members.myInvites.purpose',\n 'This is your personal inbox for invitations — when someone invites you to a workspace or organization, accept it here to gain access, or decline if it was not meant for you. Switch tabs to review each type of invite.'\n )}\n </PagePurpose>\n\n {visibleActionError && (\n <div className=\"mb-4 flex items-center gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3\">\n <AlertCircle size={16} className=\"shrink-0 text-[var(--color-status-error-text)]\" />\n <p className=\"text-sm text-[var(--color-status-error-text)]\">{visibleActionError}</p>\n </div>\n )}\n\n {workspaceInvitesEnabled ? (\n sortedWorkspaceInvites.length === 0 ? (\n <GlassCard treatment=\"glass\" glow className=\"rounded-xl\">\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title={tr('members.myInvites.workspaceEmptyTitle', 'No pending workspace invites')}\n description={tr(\n 'members.myInvites.workspaceEmptyDescription',\n 'When someone invites you to a workspace, it will appear here.'\n )}\n />\n </GlassCard>\n ) : (\n <div className=\"space-y-3\">\n {sortedWorkspaceInvites.map((invite) => {\n const workspaceName = getWorkspaceDisplayName(invite);\n const roleNames = getRoleDisplayNames(invite);\n const projectNames = getProjectDisplayNames(invite, tr);\n const inviterProfile = invite.invitedById\n ? inviterProfiles[invite.invitedById]\n : undefined;\n const inviterLabel =\n inviterProfile?.displayName ||\n inviterProfile?.email ||\n tr('members.myInvites.invitedByFallback', 'Someone');\n const isProcessingWorkspaceAccept =\n processingWorkspaceAction?.inviteId === invite.id &&\n processingWorkspaceAction?.action === 'accept' &&\n acceptingWorkspace;\n const isProcessingWorkspaceReject =\n processingWorkspaceAction?.inviteId === invite.id &&\n processingWorkspaceAction?.action === 'reject' &&\n rejectingWorkspace;\n\n return (\n <GlassCard key={invite.id} treatment=\"insight\" className=\"border-border-seam p-5\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"min-w-0 space-y-3\">\n <div className=\"flex items-start gap-3\">\n <div className=\"rounded-lg bg-[var(--color-bg-subtle)] p-2\">\n <BriefcaseBusiness\n size={20}\n className=\"text-[var(--color-text-secondary)]\"\n />\n </div>\n <div className=\"min-w-0\">\n <h3 className=\"font-semibold text-[var(--color-text-primary)] break-words\">\n {workspaceName}\n </h3>\n <p className=\"mt-1 text-sm text-[var(--color-text-secondary)] break-all\">\n {invite.email}\n </p>\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"secondary\">{invite.status}</Badge>\n {roleNames.map((roleName) => (\n <Badge key={`${invite.id}-${roleName}`} variant=\"outline\">\n {roleName}\n </Badge>\n ))}\n </div>\n\n <dl className=\"grid gap-3 text-sm text-[var(--color-text-secondary)] sm:grid-cols-2\">\n <div>\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.invitedByLabel', 'Invited by')}\n </dt>\n <dd className=\"break-all\">\n {inviterProfile ? (\n <ActorIdentity\n profile={inviterProfile}\n variant=\"inline\"\n hideIdDrilldown\n />\n ) : (\n inviterLabel\n )}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.receivedLabel', 'Received')}\n </dt>\n <dd>{formatDate(invite.createdAt) ?? '—'}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.expiresLabel', 'Expires')}\n </dt>\n <dd>{formatDate(invite.expiresAt) ?? '—'}</dd>\n </div>\n {projectNames.length > 0 ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.projectsLabel', 'Projects')}\n </dt>\n <dd className=\"mt-1 flex flex-wrap gap-2\">\n {projectNames.map((projectName) => (\n <Badge key={`${invite.id}-${projectName}`} variant=\"outline\">\n {projectName}\n </Badge>\n ))}\n </dd>\n </div>\n ) : null}\n </dl>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2 shrink-0\">\n <button\n type=\"button\"\n onClick={() => void handleAcceptWorkspace(invite.id)}\n disabled={isProcessingWorkspaceAccept || isProcessingWorkspaceReject}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-[var(--color-status-success-bg)] px-4 py-2 text-sm font-medium text-[var(--color-text-inverse)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {isProcessingWorkspaceAccept ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : null}\n {tr('members.myInvites.accept', 'Accept')}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleRejectWorkspace(invite.id)}\n disabled={isProcessingWorkspaceAccept || isProcessingWorkspaceReject}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-[var(--color-border-default)] bg-transparent px-4 py-2 text-sm font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:border-[var(--color-status-error-border)] hover:bg-[var(--color-status-error-bgSubtle)] hover:text-[var(--color-status-error-text)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {isProcessingWorkspaceReject ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : null}\n {tr('members.myInvites.decline', 'Decline')}\n </button>\n </div>\n </div>\n </GlassCard>\n );\n })}\n </div>\n )\n ) : invites.length === 0 ? (\n <GlassCard treatment=\"glass\" glow className=\"rounded-xl\">\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title={tr('members.myInvites.emptyTitle', 'No pending invites')}\n description={tr(\n 'members.myInvites.emptyDescription',\n 'When someone invites you to an organization, it will appear here.'\n )}\n />\n </GlassCard>\n ) : (\n <div className=\"space-y-3\">\n {invites.map((invite) => (\n <MyInviteCard\n key={invite.id}\n invite={invite}\n onAccept={handleAccept}\n onReject={handleReject}\n accepting={accepting}\n rejecting={rejecting}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MyInvitesPage.js","names":["OrganizationInviteStatus","formatDate","value","date","joinPath","base","path","InvitesTabNav","getTabClassName","isActive","NavLink","basePath","activeTab","tr","MyInvitesPage","useTr","permissionsLoading","usePermissions","useOrgConsole","orgInvitesEnabled","workspaceInvitesEnabled","useMyInvites","InviteStatus","workspaceInvites","workspaceLoading","workspaceError","workspaceTotal","refetchWorkspaceInvites","useMyWorkspaceInvites","currentUser","accepting","useAcceptInvite","rejecting","useRejectInvite","acceptWorkspaceInvite","acceptingWorkspace","useAcceptWorkspaceInvite","rejectWorkspaceInvite","rejectingWorkspace","useRejectWorkspaceInvite","actionError","setActionError","useState","visibleActionError","processingWorkspaceAction","setProcessingWorkspaceAction","workspaceInviteActors","useMemo","invite","inviterProfiles","useActorProfiles","sortedWorkspaceInvites","right","left","totalCount","total","handleAccept","acceptInvite","inviteId","err","handleReject","rejectInvite","handleAcceptWorkspace","current","handleRejectWorkspace","LoadingState","Mail","loading","invites","Loader2","error","PagePurpose","AlertCircle","GlassCard","IllustratedEmptyState","workspaceName","getWorkspaceDisplayName","roleNames","getRoleDisplayNames","projectNames","getProjectDisplayNames","inviterProfile","inviterLabel","isProcessingWorkspaceAccept","isProcessingWorkspaceReject","BriefcaseBusiness","Badge","roleName","ActorIdentity","projectName","MyInviteCard"],"sources":["../../../../../src/organization-management/modules/members/pages/MyInvitesPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { NavLink } from 'react-router';\nimport { Mail, Loader2, AlertCircle, BriefcaseBusiness } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n ActorIdentity,\n useActorProfiles,\n type ActorInput,\n type ActorProfileMap,\n} from '@burdenoff/fe-libs/shared';\nimport { Badge, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMyInvites, useAcceptInvite, useRejectInvite } from '../hooks/useInvites';\nimport {\n useAcceptWorkspaceInvite,\n useMyWorkspaceInvites,\n useRejectWorkspaceInvite,\n} from '../hooks/useWorkspaceInvites';\nimport { MyInviteCard } from '../components/MyInviteCard';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { InviteStatus as OrganizationInviteStatus } from '../../../../generated/global-types';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport {\n getProjectDisplayNames,\n getRoleDisplayNames,\n getWorkspaceDisplayName,\n} from '../utils/workspaceInvitationDisplay';\n\n/**\n * My Invites Page\n * Shows pending invites for the current user with accept/reject actions\n */\ntype MyInvitesTab = 'workspace' | 'organization';\n\ninterface MyInvitesPageProps {\n activeTab?: MyInvitesTab;\n}\n\ninterface TabActionError {\n tab: MyInvitesTab;\n message: string;\n}\n\ninterface InvitesTabNavProps {\n activeTab: MyInvitesTab;\n basePath: string;\n tr: ReturnType<typeof useTr>;\n}\n\nfunction formatDate(value?: string | null) {\n if (!value) return null;\n\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n\n return date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction joinPath(base: string, path: string): string {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n}\n\nfunction InvitesTabNav({ activeTab, basePath, tr }: InvitesTabNavProps) {\n const getTabClassName = (isActive: boolean) =>\n [\n 'border-b-2 px-4 py-2 text-sm font-medium transition-colors',\n isActive\n ? 'border-[var(--color-border-focus)] text-[var(--color-text-primary)]'\n : 'border-transparent text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]',\n ].join(' ');\n\n return (\n <div className=\"mb-6 flex gap-2 border-b border-[var(--color-border-default)]\">\n <NavLink\n to={joinPath(basePath, '/invites')}\n end\n className={getTabClassName(activeTab === 'workspace')}\n >\n {tr('members.myInvites.workspaceTab', 'Workspace Invites')}\n </NavLink>\n <NavLink\n to={joinPath(basePath, '/invites/organizations')}\n className={getTabClassName(activeTab === 'organization')}\n >\n {tr('members.myInvites.organizationTab', 'Organization Invites')}\n </NavLink>\n </div>\n );\n}\n\nexport function MyInvitesPage({ activeTab = 'workspace' }: MyInvitesPageProps) {\n useOrganizationPageView(\n activeTab === 'workspace'\n ? 'organizations.my-workspace-invites'\n : 'organizations.my-organization-invites'\n );\n const tr = useTr();\n const { isLoading: permissionsLoading } = usePermissions();\n const { basePath = '/organizations', currentUser, authToken, apiGatewayUrl } = useOrgConsole();\n const orgInvitesEnabled = activeTab === 'organization';\n const workspaceInvitesEnabled = activeTab === 'workspace';\n const { invites, loading, error, total } = useMyInvites(\n OrganizationInviteStatus.Pending,\n 20,\n 0,\n orgInvitesEnabled\n );\n const {\n invites: workspaceInvites,\n loading: workspaceLoading,\n error: workspaceError,\n total: workspaceTotal,\n refetch: refetchWorkspaceInvites,\n } = useMyWorkspaceInvites(currentUser?.email, workspaceInvitesEnabled);\n const { acceptInvite, loading: accepting } = useAcceptInvite();\n const { rejectInvite, loading: rejecting } = useRejectInvite();\n const { acceptInvite: acceptWorkspaceInvite, loading: acceptingWorkspace } =\n useAcceptWorkspaceInvite();\n const { rejectInvite: rejectWorkspaceInvite, loading: rejectingWorkspace } =\n useRejectWorkspaceInvite();\n const [actionError, setActionError] = useState<TabActionError | null>(null);\n\n const visibleActionError = actionError?.tab === activeTab ? actionError.message : null;\n const [processingWorkspaceAction, setProcessingWorkspaceAction] = useState<{\n inviteId: string;\n action: 'accept' | 'reject';\n } | null>(null);\n\n const workspaceInviteActors = useMemo<ActorInput[]>(\n () =>\n workspaceInvites.flatMap((invite) =>\n invite.invitedById ? [{ actorId: invite.invitedById, actorType: 'user' as const }] : []\n ),\n [workspaceInvites]\n );\n\n const inviterProfiles: ActorProfileMap = useActorProfiles(workspaceInviteActors, {\n apiGatewayUrl,\n authToken,\n });\n\n const sortedWorkspaceInvites = useMemo(\n () =>\n [...workspaceInvites].sort(\n (left: (typeof workspaceInvites)[number], right: (typeof workspaceInvites)[number]) =>\n new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime()\n ),\n [workspaceInvites]\n );\n\n const totalCount = activeTab === 'workspace' ? workspaceTotal : total;\n\n const handleAccept = async (inviteId: string) => {\n try {\n setActionError(null);\n await acceptInvite(inviteId);\n } catch (err) {\n setActionError({\n tab: 'organization',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.acceptFailed', 'Failed to accept invite'),\n });\n }\n };\n\n const handleReject = async (inviteId: string) => {\n try {\n setActionError(null);\n await rejectInvite(inviteId);\n } catch (err) {\n setActionError({\n tab: 'organization',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.rejectFailed', 'Failed to reject invite'),\n });\n }\n };\n\n const handleAcceptWorkspace = async (inviteId: string) => {\n try {\n setProcessingWorkspaceAction({ inviteId, action: 'accept' });\n setActionError(null);\n await acceptWorkspaceInvite(inviteId);\n await refetchWorkspaceInvites().catch(() => undefined);\n } catch (err) {\n setActionError({\n tab: 'workspace',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.workspaceAcceptFailed', 'Failed to accept workspace invite'),\n });\n } finally {\n setProcessingWorkspaceAction((current) =>\n current?.inviteId === inviteId && current.action === 'accept' ? null : current\n );\n }\n };\n\n const handleRejectWorkspace = async (inviteId: string) => {\n try {\n setProcessingWorkspaceAction({ inviteId, action: 'reject' });\n setActionError(null);\n await rejectWorkspaceInvite(inviteId);\n await refetchWorkspaceInvites().catch(() => undefined);\n } catch (err) {\n setActionError({\n tab: 'workspace',\n message:\n err instanceof Error\n ? err.message\n : tr('members.myInvites.workspaceRejectFailed', 'Failed to reject workspace invite'),\n });\n } finally {\n setProcessingWorkspaceAction((current) =>\n current?.inviteId === inviteId && current.action === 'reject' ? null : current\n );\n }\n };\n\n // Own invites are always accessible — no permission denial needed.\n // We still wait for permissions to load to ensure consistent UX.\n if (permissionsLoading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <LoadingState message={tr('common.loadingPermissions', 'Loading permissions...')} />\n </div>\n );\n }\n\n if (workspaceInvitesEnabled && !currentUser?.email) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-6 text-center\">\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr('members.myInvites.signInWorkspace', 'Sign in to view your workspace invites.')}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n if (orgInvitesEnabled && loading && invites.length === 0) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"flex items-center justify-center min-h-[300px] rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={24} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </div>\n </div>\n );\n }\n\n if (workspaceInvitesEnabled && workspaceLoading && workspaceInvites.length === 0) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"flex items-center justify-center min-h-[300px] rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={24} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </div>\n </div>\n );\n }\n\n if (orgInvitesEnabled && error) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"rounded-xl border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-6 text-center\">\n <p className=\"text-[var(--color-status-error-text)]\">\n {tr('members.myInvites.loadFailed', 'Failed to load invites')}: {error.message}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n if (workspaceInvitesEnabled && workspaceError) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"mb-6 flex items-center gap-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <div className=\"rounded-xl border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-6 text-center\">\n <p className=\"text-[var(--color-status-error-text)]\">\n {tr('members.myInvites.workspaceLoadFailed', 'Failed to load workspace invites')}:{' '}\n {workspaceError.message}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <div className=\"max-w-4xl mx-auto\">\n {/* Header */}\n <div className=\"flex items-center gap-3 mb-6\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.myInvites.title', 'My Invites')}\n </h1>\n {totalCount > 0 && (\n <span className=\"px-2.5 py-0.5 rounded-full text-xs font-medium bg-[var(--color-action-primary-bg)] text-[var(--color-action-primary-text)]\">\n {totalCount}\n </span>\n )}\n </div>\n\n <InvitesTabNav activeTab={activeTab} basePath={basePath} tr={tr} />\n\n <PagePurpose className=\"mb-4 max-w-3xl\">\n {tr(\n 'members.myInvites.purpose',\n 'This is your personal inbox for invitations — when someone invites you to a workspace or organization, accept it here to gain access, or decline if it was not meant for you. Switch tabs to review each type of invite.'\n )}\n </PagePurpose>\n\n {visibleActionError && (\n <div className=\"mb-4 flex items-center gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3\">\n <AlertCircle size={16} className=\"shrink-0 text-[var(--color-status-error-text)]\" />\n <p className=\"text-sm text-[var(--color-status-error-text)]\">{visibleActionError}</p>\n </div>\n )}\n\n {workspaceInvitesEnabled ? (\n sortedWorkspaceInvites.length === 0 ? (\n <GlassCard treatment=\"glass\" glow className=\"rounded-xl\">\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title={tr('members.myInvites.workspaceEmptyTitle', 'No pending workspace invites')}\n description={tr(\n 'members.myInvites.workspaceEmptyDescription',\n 'When someone invites you to a workspace, it will appear here.'\n )}\n />\n </GlassCard>\n ) : (\n <div className=\"space-y-3\">\n {sortedWorkspaceInvites.map((invite) => {\n const workspaceName = getWorkspaceDisplayName(invite);\n const roleNames = getRoleDisplayNames(invite);\n const projectNames = getProjectDisplayNames(invite, tr);\n const inviterProfile = invite.invitedById\n ? inviterProfiles[invite.invitedById]\n : undefined;\n const inviterLabel =\n inviterProfile?.displayName ||\n inviterProfile?.email ||\n tr('members.myInvites.invitedByFallback', 'Someone');\n const isProcessingWorkspaceAccept =\n processingWorkspaceAction?.inviteId === invite.id &&\n processingWorkspaceAction?.action === 'accept' &&\n acceptingWorkspace;\n const isProcessingWorkspaceReject =\n processingWorkspaceAction?.inviteId === invite.id &&\n processingWorkspaceAction?.action === 'reject' &&\n rejectingWorkspace;\n\n return (\n <GlassCard key={invite.id} treatment=\"insight\" className=\"border-border-seam p-5\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"min-w-0 space-y-3\">\n <div className=\"flex items-start gap-3\">\n <div className=\"rounded-lg bg-[var(--color-bg-subtle)] p-2\">\n <BriefcaseBusiness\n size={20}\n className=\"text-[var(--color-text-secondary)]\"\n />\n </div>\n <div className=\"min-w-0\">\n <h3 className=\"font-semibold text-[var(--color-text-primary)] break-words\">\n {workspaceName}\n </h3>\n <p className=\"mt-1 text-sm text-[var(--color-text-secondary)] break-all\">\n {invite.email}\n </p>\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"secondary\">{invite.status}</Badge>\n {roleNames.map((roleName) => (\n <Badge key={`${invite.id}-${roleName}`} variant=\"outline\">\n {roleName}\n </Badge>\n ))}\n </div>\n\n <dl className=\"grid gap-3 text-sm text-[var(--color-text-secondary)] sm:grid-cols-2\">\n <div>\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.invitedByLabel', 'Invited by')}\n </dt>\n <dd className=\"break-all\">\n {inviterProfile ? (\n <ActorIdentity\n profile={inviterProfile}\n variant=\"inline\"\n hideIdDrilldown\n />\n ) : (\n inviterLabel\n )}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.receivedLabel', 'Received')}\n </dt>\n <dd>{formatDate(invite.createdAt) ?? '—'}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.expiresLabel', 'Expires')}\n </dt>\n <dd>{formatDate(invite.expiresAt) ?? '—'}</dd>\n </div>\n {projectNames.length > 0 ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"font-medium text-[var(--color-text-primary)]\">\n {tr('members.myInvites.projectsLabel', 'Projects')}\n </dt>\n <dd className=\"mt-1 flex flex-wrap gap-2\">\n {projectNames.map((projectName) => (\n <Badge key={`${invite.id}-${projectName}`} variant=\"outline\">\n {projectName}\n </Badge>\n ))}\n </dd>\n </div>\n ) : null}\n </dl>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2 shrink-0\">\n <button\n type=\"button\"\n onClick={() => void handleAcceptWorkspace(invite.id)}\n disabled={isProcessingWorkspaceAccept || isProcessingWorkspaceReject}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-[var(--color-status-success-bg)] px-4 py-2 text-sm font-medium text-[var(--color-text-inverse)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {isProcessingWorkspaceAccept ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : null}\n {tr('members.myInvites.accept', 'Accept')}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleRejectWorkspace(invite.id)}\n disabled={isProcessingWorkspaceAccept || isProcessingWorkspaceReject}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-[var(--color-border-default)] bg-transparent px-4 py-2 text-sm font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:border-[var(--color-status-error-border)] hover:bg-[var(--color-status-error-bgSubtle)] hover:text-[var(--color-status-error-text)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {isProcessingWorkspaceReject ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : null}\n {tr('members.myInvites.decline', 'Decline')}\n </button>\n </div>\n </div>\n </GlassCard>\n );\n })}\n </div>\n )\n ) : invites.length === 0 ? (\n <GlassCard treatment=\"glass\" glow className=\"rounded-xl\">\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title={tr('members.myInvites.emptyTitle', 'No pending invites')}\n description={tr(\n 'members.myInvites.emptyDescription',\n 'When someone invites you to an organization, it will appear here.'\n )}\n />\n </GlassCard>\n ) : (\n <div className=\"space-y-3\">\n {invites.map((invite) => (\n <MyInviteCard\n key={invite.id}\n invite={invite}\n onAccept={handleAccept}\n onReject={handleReject}\n accepting={accepting}\n rejecting={rejecting}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,14 +1,14 @@
1
- import { useOrgConsole as e } from "../../../providers/OrgConsoleProvider.js";
2
- import { useAcceptInvite as t, useOrganizationInvite as n, useRejectInvite as r } from "../hooks/useInvites.js";
3
- import { InviteStatus as i } from "../../../../generated/global-types.js";
4
- import { useTr as a } from "../../../shared/hooks/useTr.js";
5
- import { useOrganizationPageView as o } from "../../../hooks/useOrganizationPageView.js";
1
+ import { useAcceptInvite as e, useOrganizationInvite as t, useRejectInvite as n } from "../hooks/useInvites.js";
2
+ import { InviteStatus as r } from "../../../../generated/global-types.js";
3
+ import { useTr as i } from "../../../shared/hooks/useTr.js";
4
+ import { useOrganizationPageView as a } from "../../../hooks/useOrganizationPageView.js";
5
+ import { useOrgConsole as o } from "../../../providers/OrgConsoleProvider.js";
6
6
  import { useState as s } from "react";
7
7
  import { AlertTriangle as c, Ban as l, Building2 as u, CheckCircle as d, Clock as f, Home as p, Loader2 as m, Mail as h, XCircle as g } from "lucide-react";
8
8
  import { Badge as _, EmphasisPanel as v, GlassCard as y, PagePurpose as b } from "@burdenoff/fe-libs/ui";
9
9
  import { jsx as x, jsxs as S } from "react/jsx-runtime";
10
10
  import { useParams as C } from "react-router";
11
- //#region src/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.tsx
11
+ // src/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.tsx
12
12
  function w(e) {
13
13
  if (!e) return null;
14
14
  let t = new Date(e);
@@ -60,8 +60,8 @@ function E({ icon: e, iconClass: t, title: n, description: r, email: i, primaryL
60
60
  }) });
61
61
  }
62
62
  function D() {
63
- o("organizations.invite-acceptance");
64
- let D = a(), { inviteId: O = "" } = C(), { basePath: k = "/organizations", navigate: A, currentUser: j, authToken: M } = e(), N = !!(M || j?.email), { invite: P, loading: F, error: I, refetch: L } = n(O, N), { acceptInvite: R } = t(), { rejectInvite: z } = r(), [B, V] = s(null), [H, U] = s(null), W = () => A(`${k}/invites/organizations`), G = async () => {
63
+ a("organizations.invite-acceptance");
64
+ let D = i(), { inviteId: O = "" } = C(), { basePath: k = "/organizations", navigate: A, currentUser: j, authToken: M } = o(), N = !!(M || j?.email), { invite: P, loading: F, error: I, refetch: L } = t(O, N), { acceptInvite: R } = e(), { rejectInvite: z } = n(), [B, V] = s(null), [H, U] = s(null), W = () => A(`${k}/invites/organizations`), G = async () => {
65
65
  if (O) try {
66
66
  V("accept"), U(null), await R(O), A(P?.organizationId ? `${k}/${P.organizationId}` : k);
67
67
  } catch (e) {
@@ -145,8 +145,8 @@ function D() {
145
145
  primaryLabel: D("members.inviteAcceptance.goToOrganizations", "Go to Organizations"),
146
146
  onPrimary: () => A(k)
147
147
  });
148
- let q = P.expiresAt && new Date(P.expiresAt) < /* @__PURE__ */ new Date(), J = P.status === i.Pending && q ? i.Expired : P.status;
149
- if (J === i.Accepted) return /* @__PURE__ */ x(E, {
148
+ let q = P.expiresAt && new Date(P.expiresAt) < /* @__PURE__ */ new Date(), J = P.status === r.Pending && q ? r.Expired : P.status;
149
+ if (J === r.Accepted) return /* @__PURE__ */ x(E, {
150
150
  icon: d,
151
151
  iconClass: "bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)]",
152
152
  title: D("members.inviteAcceptance.alreadyAcceptedTitle", "Invitation Already Accepted"),
@@ -155,7 +155,7 @@ function D() {
155
155
  primaryLabel: D("members.inviteAcceptance.goToOrganization", "Go to Organization"),
156
156
  onPrimary: () => A(`${k}/${P.organizationId}`)
157
157
  });
158
- if (J === i.Rejected) return /* @__PURE__ */ x(E, {
158
+ if (J === r.Rejected) return /* @__PURE__ */ x(E, {
159
159
  icon: g,
160
160
  iconClass: "bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]",
161
161
  title: D("members.inviteAcceptance.rejectedTitle", "Invitation Declined"),
@@ -164,7 +164,7 @@ function D() {
164
164
  primaryLabel: D("members.inviteAcceptance.goToOrganizations", "Go to Organizations"),
165
165
  onPrimary: () => A(k)
166
166
  });
167
- if (J === i.Expired) return /* @__PURE__ */ x(E, {
167
+ if (J === r.Expired) return /* @__PURE__ */ x(E, {
168
168
  icon: f,
169
169
  iconClass: "bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)]",
170
170
  title: D("members.inviteAcceptance.expiredTitle", "Invitation Expired"),
@@ -173,7 +173,7 @@ function D() {
173
173
  primaryLabel: D("members.inviteAcceptance.goToOrganizations", "Go to Organizations"),
174
174
  onPrimary: () => A(k)
175
175
  });
176
- if (J === i.Cancelled) return /* @__PURE__ */ x(E, {
176
+ if (J === r.Cancelled) return /* @__PURE__ */ x(E, {
177
177
  icon: l,
178
178
  iconClass: "bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]",
179
179
  title: D("members.inviteAcceptance.cancelledTitle", "Invitation Cancelled"),
@@ -287,7 +287,6 @@ function D() {
287
287
  ]
288
288
  }) });
289
289
  }
290
- //#endregion
291
290
  export { D as OrganizationInviteAcceptancePage };
292
291
 
293
292
  //# sourceMappingURL=OrganizationInviteAcceptancePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrganizationInviteAcceptancePage.js","names":[],"sources":["../../../../../src/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router';\nimport {\n Mail,\n Loader2,\n CheckCircle,\n XCircle,\n Clock,\n AlertTriangle,\n Ban,\n Home,\n Building2,\n} from 'lucide-react';\nimport { Badge, EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useOrganizationInvite, useAcceptInvite, useRejectInvite } from '../hooks/useInvites';\nimport { InviteStatus } from '../../../../generated/global-types';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\n\n/**\n * OrganizationInviteAcceptancePage\n *\n * Per-invite acceptance page reached from the organization invite email link\n * (`/organizations/invite/:inviteId`). Mirrors the workspace invite-acceptance\n * flow: loads the single invite by id, renders the appropriate state machine\n * (PENDING → accept/reject, ACCEPTED/REJECTED/EXPIRED/CANCELLED), and gates the\n * unauthenticated case behind a sign-in CTA that returns the user here.\n *\n * The previous behaviour dropped the recipient on `/organizations/invites`\n * (the workspace-invites list tab) with no invite context, which rendered as\n * an empty page. The email now deep-links here with the invite id.\n */\nfunction formatDate(value?: string | null): string | null {\n if (!value) return null;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n return date.toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction PageShell({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-10 sm:px-6\">\n <div className=\"mx-auto max-w-2xl\">{children}</div>\n </div>\n );\n}\n\ninterface StatusViewProps {\n icon: typeof CheckCircle;\n iconClass: string;\n title: string;\n description: string;\n email?: string;\n primaryLabel: string;\n onPrimary: () => void;\n}\n\nfunction StatusView({\n icon: Icon,\n iconClass,\n title,\n description,\n email,\n primaryLabel,\n onPrimary,\n}: StatusViewProps) {\n return (\n <PageShell>\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-8 text-center\">\n <div\n className={`mx-auto mb-4 flex size-14 items-center justify-center rounded-2xl ${iconClass}`}\n >\n <Icon size={28} />\n </div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">{title}</h1>\n <p className=\"mt-2 text-[var(--color-text-secondary)]\">{description}</p>\n {email ? (\n <p className=\"mt-1 break-all text-sm text-[var(--color-text-muted)]\">{email}</p>\n ) : null}\n <button\n type=\"button\"\n onClick={onPrimary}\n className=\"mt-6 inline-flex items-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n <Home size={16} />\n {primaryLabel}\n </button>\n </GlassCard>\n </PageShell>\n );\n}\n\nexport function OrganizationInviteAcceptancePage() {\n useOrganizationPageView('organizations.invite-acceptance');\n const tr = useTr();\n const { inviteId = '' } = useParams<{ inviteId: string }>();\n const { basePath = '/organizations', navigate, currentUser, authToken } = useOrgConsole();\n\n const isAuthenticated = Boolean(authToken || currentUser?.email);\n const { invite, loading, error, refetch } = useOrganizationInvite(inviteId, isAuthenticated);\n const { acceptInvite } = useAcceptInvite();\n const { rejectInvite } = useRejectInvite();\n\n const [processing, setProcessing] = useState<'accept' | 'reject' | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n\n const goToInvitesList = () => navigate(`${basePath}/invites/organizations`);\n\n const handleAccept = async () => {\n if (!inviteId) return;\n try {\n setProcessing('accept');\n setActionError(null);\n await acceptInvite(inviteId);\n navigate(invite?.organizationId ? `${basePath}/${invite.organizationId}` : basePath);\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.acceptFailed', 'Failed to accept invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n const handleReject = async () => {\n if (!inviteId) return;\n try {\n setProcessing('reject');\n setActionError(null);\n await rejectInvite(inviteId);\n goToInvitesList();\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.rejectFailed', 'Failed to reject invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n // Unauthenticated — invitees must sign in with the invited email first.\n if (!isAuthenticated) {\n const returnTo = encodeURIComponent(`${basePath}/invite/${inviteId}`);\n return (\n <PageShell>\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-8\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.signInRequired', 'Sign in to view your invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n 'members.inviteAcceptance.signInDescription',\n 'Organization invitations require an authenticated account before you can review or accept them.'\n )}\n </p>\n </div>\n </div>\n <p className=\"mb-6 text-sm text-[var(--color-text-muted)]\">\n {tr(\n 'members.inviteAcceptance.signInHint',\n 'Use the same email address that received the invitation, then come back here to accept or decline it.'\n )}\n </p>\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n <a\n href={`/auth/login?returnTo=${returnTo}`}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n {tr('members.inviteAcceptance.signInButton', 'Sign In')}\n </a>\n <button\n type=\"button\"\n onClick={() => navigate(basePath)}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Home size={16} />\n {tr('members.inviteAcceptance.backToOrganizations', 'Back to Organizations')}\n </button>\n </div>\n </GlassCard>\n </PageShell>\n );\n }\n\n if (loading) {\n return (\n <PageShell>\n <div className=\"flex min-h-[300px] items-center justify-center rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={28} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </PageShell>\n );\n }\n\n if (error) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.errorTitle', 'Error Loading Invitation')}\n description={error.message}\n primaryLabel={tr('members.inviteAcceptance.tryAgain', 'Try Again')}\n onPrimary={() => {\n void refetch();\n }}\n />\n );\n }\n\n if (!invite) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.notFoundTitle', 'Invitation Not Found')}\n description={tr(\n 'members.inviteAcceptance.notFoundDescription',\n 'This invitation link is invalid, has been removed, or was addressed to a different account.'\n )}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n const isExpiredByDate = invite.expiresAt && new Date(invite.expiresAt) < new Date();\n const effectiveStatus =\n invite.status === InviteStatus.Pending && isExpiredByDate\n ? InviteStatus.Expired\n : invite.status;\n\n if (effectiveStatus === InviteStatus.Accepted) {\n return (\n <StatusView\n icon={CheckCircle}\n iconClass=\"bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)]\"\n title={tr('members.inviteAcceptance.alreadyAcceptedTitle', 'Invitation Already Accepted')}\n description={tr(\n 'members.inviteAcceptance.alreadyAcceptedDescription',\n 'You have already accepted this invitation.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganization', 'Go to Organization')}\n onPrimary={() => navigate(`${basePath}/${invite.organizationId}`)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Rejected) {\n return (\n <StatusView\n icon={XCircle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.rejectedTitle', 'Invitation Declined')}\n description={tr(\n 'members.inviteAcceptance.rejectedDescription',\n 'This invitation was previously declined.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Expired) {\n return (\n <StatusView\n icon={Clock}\n iconClass=\"bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)]\"\n title={tr('members.inviteAcceptance.expiredTitle', 'Invitation Expired')}\n description={tr(\n 'members.inviteAcceptance.expiredDescription',\n 'This invitation has expired. Please contact an organization admin for a new one.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Cancelled) {\n return (\n <StatusView\n icon={Ban}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.cancelledTitle', 'Invitation Cancelled')}\n description={tr(\n 'members.inviteAcceptance.cancelledDescription',\n 'This invitation was cancelled by the sender and is no longer valid.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n // PENDING — show the acceptance UI.\n const organizationName = invite.organization?.name ?? invite.organizationId;\n const expiresLabel = formatDate(invite.expiresAt);\n const busy = processing !== null;\n\n return (\n <PageShell>\n <EmphasisPanel className=\"p-8\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Building2 size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.pageTitle', 'Organization Invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr('members.inviteAcceptance.pageSubtitle', \"You've been invited to join\")}{' '}\n <span className=\"font-medium text-[var(--color-text-primary)]\">\n {organizationName}\n </span>\n </p>\n </div>\n </div>\n\n <PagePurpose className=\"mb-6\">\n {tr(\n 'members.inviteAcceptance.purpose',\n 'Review the details of this invitation below. Accept it to join the organization and gain access to its workspaces, or decline if it was not meant for you.'\n )}\n </PagePurpose>\n\n <dl className=\"space-y-4 rounded-xl bg-[var(--color-bg-subtle)] p-5\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.emailLabel', 'Email Address')}\n </dt>\n <dd className=\"mt-1 break-all text-[var(--color-text-primary)]\">{invite.email}</dd>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.roleLabel', 'Role')}\n </dt>\n <dd>\n <Badge variant=\"secondary\">{invite.role}</Badge>\n </dd>\n </div>\n {expiresLabel ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.expiresLabel', 'Expires')}\n </dt>\n <dd className=\"mt-1 flex items-center gap-2 text-[var(--color-text-primary)]\">\n <Clock size={16} className=\"text-[var(--color-text-muted)]\" />\n {expiresLabel}\n </dd>\n </div>\n ) : null}\n {invite.message ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.messageLabel', 'Message')}\n </dt>\n <dd className=\"mt-1 text-[var(--color-text-secondary)]\">{invite.message}</dd>\n </div>\n ) : null}\n </dl>\n\n {actionError ? (\n <div className=\"mt-4 flex items-center gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3\">\n <AlertTriangle size={16} className=\"shrink-0 text-[var(--color-status-error-text)]\" />\n <p className=\"text-sm text-[var(--color-status-error-text)]\">{actionError}</p>\n </div>\n ) : null}\n\n <div className=\"mt-6 flex flex-col gap-3 border-t border-[var(--color-border-seam)] pt-6 sm:flex-row\">\n <button\n type=\"button\"\n onClick={() => void handleAccept()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg bg-[var(--color-status-success-bg)] px-6 py-3 font-medium text-[var(--color-text-inverse)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'accept' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <CheckCircle size={16} />\n )}\n {tr('members.inviteAcceptance.acceptButton', 'Accept Invitation')}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleReject()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-3 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:border-[var(--color-status-error-border)] hover:bg-[var(--color-status-error-bgSubtle)] hover:text-[var(--color-status-error-text)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'reject' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <XCircle size={16} />\n )}\n {tr('members.inviteAcceptance.declineButton', 'Decline')}\n </button>\n </div>\n </EmphasisPanel>\n </PageShell>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"OrganizationInviteAcceptancePage.js","names":["formatDate","value","date","PageShell","StatusView","Icon","GlassCard","iconClass","title","description","email","onPrimary","Home","primaryLabel","OrganizationInviteAcceptancePage","tr","useTr","useParams","useOrgConsole","isAuthenticated","authToken","currentUser","useOrganizationInvite","inviteId","useAcceptInvite","useRejectInvite","processing","setProcessing","useState","actionError","setActionError","goToInvitesList","navigate","basePath","handleAccept","acceptInvite","invite","err","handleReject","rejectInvite","returnTo","Mail","loading","Loader2","error","AlertTriangle","isExpiredByDate","effectiveStatus","InviteStatus","CheckCircle","XCircle","Clock","Ban","organizationName","expiresLabel","busy","EmphasisPanel","Building2","PagePurpose","Badge"],"sources":["../../../../../src/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router';\nimport {\n Mail,\n Loader2,\n CheckCircle,\n XCircle,\n Clock,\n AlertTriangle,\n Ban,\n Home,\n Building2,\n} from 'lucide-react';\nimport { Badge, EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useOrganizationInvite, useAcceptInvite, useRejectInvite } from '../hooks/useInvites';\nimport { InviteStatus } from '../../../../generated/global-types';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\n\n/**\n * OrganizationInviteAcceptancePage\n *\n * Per-invite acceptance page reached from the organization invite email link\n * (`/organizations/invite/:inviteId`). Mirrors the workspace invite-acceptance\n * flow: loads the single invite by id, renders the appropriate state machine\n * (PENDING → accept/reject, ACCEPTED/REJECTED/EXPIRED/CANCELLED), and gates the\n * unauthenticated case behind a sign-in CTA that returns the user here.\n *\n * The previous behaviour dropped the recipient on `/organizations/invites`\n * (the workspace-invites list tab) with no invite context, which rendered as\n * an empty page. The email now deep-links here with the invite id.\n */\nfunction formatDate(value?: string | null): string | null {\n if (!value) return null;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n return date.toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction PageShell({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-10 sm:px-6\">\n <div className=\"mx-auto max-w-2xl\">{children}</div>\n </div>\n );\n}\n\ninterface StatusViewProps {\n icon: typeof CheckCircle;\n iconClass: string;\n title: string;\n description: string;\n email?: string;\n primaryLabel: string;\n onPrimary: () => void;\n}\n\nfunction StatusView({\n icon: Icon,\n iconClass,\n title,\n description,\n email,\n primaryLabel,\n onPrimary,\n}: StatusViewProps) {\n return (\n <PageShell>\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-8 text-center\">\n <div\n className={`mx-auto mb-4 flex size-14 items-center justify-center rounded-2xl ${iconClass}`}\n >\n <Icon size={28} />\n </div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">{title}</h1>\n <p className=\"mt-2 text-[var(--color-text-secondary)]\">{description}</p>\n {email ? (\n <p className=\"mt-1 break-all text-sm text-[var(--color-text-muted)]\">{email}</p>\n ) : null}\n <button\n type=\"button\"\n onClick={onPrimary}\n className=\"mt-6 inline-flex items-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n <Home size={16} />\n {primaryLabel}\n </button>\n </GlassCard>\n </PageShell>\n );\n}\n\nexport function OrganizationInviteAcceptancePage() {\n useOrganizationPageView('organizations.invite-acceptance');\n const tr = useTr();\n const { inviteId = '' } = useParams<{ inviteId: string }>();\n const { basePath = '/organizations', navigate, currentUser, authToken } = useOrgConsole();\n\n const isAuthenticated = Boolean(authToken || currentUser?.email);\n const { invite, loading, error, refetch } = useOrganizationInvite(inviteId, isAuthenticated);\n const { acceptInvite } = useAcceptInvite();\n const { rejectInvite } = useRejectInvite();\n\n const [processing, setProcessing] = useState<'accept' | 'reject' | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n\n const goToInvitesList = () => navigate(`${basePath}/invites/organizations`);\n\n const handleAccept = async () => {\n if (!inviteId) return;\n try {\n setProcessing('accept');\n setActionError(null);\n await acceptInvite(inviteId);\n navigate(invite?.organizationId ? `${basePath}/${invite.organizationId}` : basePath);\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.acceptFailed', 'Failed to accept invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n const handleReject = async () => {\n if (!inviteId) return;\n try {\n setProcessing('reject');\n setActionError(null);\n await rejectInvite(inviteId);\n goToInvitesList();\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr('members.inviteAcceptance.rejectFailed', 'Failed to reject invitation')\n );\n } finally {\n setProcessing(null);\n }\n };\n\n // Unauthenticated — invitees must sign in with the invited email first.\n if (!isAuthenticated) {\n const returnTo = encodeURIComponent(`${basePath}/invite/${inviteId}`);\n return (\n <PageShell>\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-8\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Mail size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.signInRequired', 'Sign in to view your invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n 'members.inviteAcceptance.signInDescription',\n 'Organization invitations require an authenticated account before you can review or accept them.'\n )}\n </p>\n </div>\n </div>\n <p className=\"mb-6 text-sm text-[var(--color-text-muted)]\">\n {tr(\n 'members.inviteAcceptance.signInHint',\n 'Use the same email address that received the invitation, then come back here to accept or decline it.'\n )}\n </p>\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n <a\n href={`/auth/login?returnTo=${returnTo}`}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n {tr('members.inviteAcceptance.signInButton', 'Sign In')}\n </a>\n <button\n type=\"button\"\n onClick={() => navigate(basePath)}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Home size={16} />\n {tr('members.inviteAcceptance.backToOrganizations', 'Back to Organizations')}\n </button>\n </div>\n </GlassCard>\n </PageShell>\n );\n }\n\n if (loading) {\n return (\n <PageShell>\n <div className=\"flex min-h-[300px] items-center justify-center rounded-2xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)]\">\n <Loader2 size={28} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n </PageShell>\n );\n }\n\n if (error) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.errorTitle', 'Error Loading Invitation')}\n description={error.message}\n primaryLabel={tr('members.inviteAcceptance.tryAgain', 'Try Again')}\n onPrimary={() => {\n void refetch();\n }}\n />\n );\n }\n\n if (!invite) {\n return (\n <StatusView\n icon={AlertTriangle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.notFoundTitle', 'Invitation Not Found')}\n description={tr(\n 'members.inviteAcceptance.notFoundDescription',\n 'This invitation link is invalid, has been removed, or was addressed to a different account.'\n )}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n const isExpiredByDate = invite.expiresAt && new Date(invite.expiresAt) < new Date();\n const effectiveStatus =\n invite.status === InviteStatus.Pending && isExpiredByDate\n ? InviteStatus.Expired\n : invite.status;\n\n if (effectiveStatus === InviteStatus.Accepted) {\n return (\n <StatusView\n icon={CheckCircle}\n iconClass=\"bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)]\"\n title={tr('members.inviteAcceptance.alreadyAcceptedTitle', 'Invitation Already Accepted')}\n description={tr(\n 'members.inviteAcceptance.alreadyAcceptedDescription',\n 'You have already accepted this invitation.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganization', 'Go to Organization')}\n onPrimary={() => navigate(`${basePath}/${invite.organizationId}`)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Rejected) {\n return (\n <StatusView\n icon={XCircle}\n iconClass=\"bg-[var(--color-bg-subtle)] text-[var(--color-text-muted)]\"\n title={tr('members.inviteAcceptance.rejectedTitle', 'Invitation Declined')}\n description={tr(\n 'members.inviteAcceptance.rejectedDescription',\n 'This invitation was previously declined.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Expired) {\n return (\n <StatusView\n icon={Clock}\n iconClass=\"bg-[var(--color-status-warning-bgSubtle)] text-[var(--color-status-warning-text)]\"\n title={tr('members.inviteAcceptance.expiredTitle', 'Invitation Expired')}\n description={tr(\n 'members.inviteAcceptance.expiredDescription',\n 'This invitation has expired. Please contact an organization admin for a new one.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n if (effectiveStatus === InviteStatus.Cancelled) {\n return (\n <StatusView\n icon={Ban}\n iconClass=\"bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]\"\n title={tr('members.inviteAcceptance.cancelledTitle', 'Invitation Cancelled')}\n description={tr(\n 'members.inviteAcceptance.cancelledDescription',\n 'This invitation was cancelled by the sender and is no longer valid.'\n )}\n email={invite.email}\n primaryLabel={tr('members.inviteAcceptance.goToOrganizations', 'Go to Organizations')}\n onPrimary={() => navigate(basePath)}\n />\n );\n }\n\n // PENDING — show the acceptance UI.\n const organizationName = invite.organization?.name ?? invite.organizationId;\n const expiresLabel = formatDate(invite.expiresAt);\n const busy = processing !== null;\n\n return (\n <PageShell>\n <EmphasisPanel className=\"p-8\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"rounded-xl bg-[var(--color-bg-subtle)] p-3\">\n <Building2 size={24} className=\"text-[var(--color-text-primary)]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-bold text-[var(--color-text-primary)]\">\n {tr('members.inviteAcceptance.pageTitle', 'Organization Invitation')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr('members.inviteAcceptance.pageSubtitle', \"You've been invited to join\")}{' '}\n <span className=\"font-medium text-[var(--color-text-primary)]\">\n {organizationName}\n </span>\n </p>\n </div>\n </div>\n\n <PagePurpose className=\"mb-6\">\n {tr(\n 'members.inviteAcceptance.purpose',\n 'Review the details of this invitation below. Accept it to join the organization and gain access to its workspaces, or decline if it was not meant for you.'\n )}\n </PagePurpose>\n\n <dl className=\"space-y-4 rounded-xl bg-[var(--color-bg-subtle)] p-5\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.emailLabel', 'Email Address')}\n </dt>\n <dd className=\"mt-1 break-all text-[var(--color-text-primary)]\">{invite.email}</dd>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.roleLabel', 'Role')}\n </dt>\n <dd>\n <Badge variant=\"secondary\">{invite.role}</Badge>\n </dd>\n </div>\n {expiresLabel ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.expiresLabel', 'Expires')}\n </dt>\n <dd className=\"mt-1 flex items-center gap-2 text-[var(--color-text-primary)]\">\n <Clock size={16} className=\"text-[var(--color-text-muted)]\" />\n {expiresLabel}\n </dd>\n </div>\n ) : null}\n {invite.message ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-muted)]\">\n {tr('members.inviteAcceptance.messageLabel', 'Message')}\n </dt>\n <dd className=\"mt-1 text-[var(--color-text-secondary)]\">{invite.message}</dd>\n </div>\n ) : null}\n </dl>\n\n {actionError ? (\n <div className=\"mt-4 flex items-center gap-2 rounded-lg border border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] p-3\">\n <AlertTriangle size={16} className=\"shrink-0 text-[var(--color-status-error-text)]\" />\n <p className=\"text-sm text-[var(--color-status-error-text)]\">{actionError}</p>\n </div>\n ) : null}\n\n <div className=\"mt-6 flex flex-col gap-3 border-t border-[var(--color-border-seam)] pt-6 sm:flex-row\">\n <button\n type=\"button\"\n onClick={() => void handleAccept()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg bg-[var(--color-status-success-bg)] px-6 py-3 font-medium text-[var(--color-text-inverse)] transition-all duration-200 hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'accept' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <CheckCircle size={16} />\n )}\n {tr('members.inviteAcceptance.acceptButton', 'Accept Invitation')}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleReject()}\n disabled={busy}\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-3 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:border-[var(--color-status-error-border)] hover:bg-[var(--color-status-error-bgSubtle)] hover:text-[var(--color-status-error-text)] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {processing === 'reject' ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <XCircle size={16} />\n )}\n {tr('members.inviteAcceptance.declineButton', 'Decline')}\n </button>\n </div>\n </EmphasisPanel>\n </PageShell>\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { UserRole as e } from "../../../../generated/global-types.js";
2
- //#region src/organization-management/modules/members/utils/bulkInviteCsv.ts
3
- var t = new Set([e.Member, e.OrgAdmin]), n = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2
+ // src/organization-management/modules/members/utils/bulkInviteCsv.ts
3
+ var t = /* @__PURE__ */ new Set([e.Member, e.OrgAdmin]), n = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4
4
  function r(e) {
5
5
  let t = [], n = "", r = !1;
6
6
  for (let i = 0; i < e.length; i += 1) {
@@ -32,12 +32,7 @@ function i(e, i) {
32
32
  };
33
33
  });
34
34
  }
35
- var a = "invite-members-template.csv", o = [
36
- "email,role,message",
37
- "alice@example.com,MEMBER,Welcome to the team",
38
- "bob@example.com,ORG_ADMIN,",
39
- "carol@example.com,,"
40
- ].join("\n");
35
+ var a = "invite-members-template.csv", o = "email,role,message\nalice@example.com,MEMBER,Welcome to the team\nbob@example.com,ORG_ADMIN,\ncarol@example.com,,";
41
36
  function s(e, t) {
42
37
  let n = e instanceof Error ? e.message : String(e);
43
38
  return n.includes("CONFLICT") ? t("members.invite.error.conflict", "An invite already exists for this email address.") : n.includes("already a member") ? t("members.invite.error.alreadyMember", "This user is already a member of the organization.") : n;
@@ -46,7 +41,6 @@ function c() {
46
41
  let e = new Blob([o], { type: "text/csv;charset=utf-8" }), t = URL.createObjectURL(e), n = document.createElement("a");
47
42
  n.href = t, n.download = a, document.body.appendChild(n), n.click(), document.body.removeChild(n), URL.revokeObjectURL(t);
48
43
  }
49
- //#endregion
50
- export { c as downloadTemplate, s as formatInviteError, i as parseBulkInviteCsv };
44
+ export { o as TEMPLATE_CONTENT, a as TEMPLATE_FILENAME, c as downloadTemplate, s as formatInviteError, i as parseBulkInviteCsv };
51
45
 
52
46
  //# sourceMappingURL=bulkInviteCsv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bulkInviteCsv.js","names":[],"sources":["../../../../../src/organization-management/modules/members/utils/bulkInviteCsv.ts"],"sourcesContent":["/**\n * Minimal CSV parsing + template generation for bulk member invites.\n * Hand-rolled (no csv lib dep) — invite CSVs are small enough to keep\n * the parser inline. Supports double-quoted fields with embedded commas\n * and escaped quotes (RFC 4180 subset).\n *\n * Expected columns (header row required, case-insensitive, any order):\n * email — required\n * role — optional, one of MEMBER | ADMIN | OWNER (case-insensitive)\n * message — optional, free text\n */\n\nimport { UserRole } from '../../../../generated/global-types';\nimport type { TranslationFn } from '../../../shared/hooks/useTr';\n\nexport interface BulkInviteRow {\n rowNumber: number;\n email: string;\n role?: UserRole;\n message?: string;\n errors: string[];\n}\n\nconst VALID_ROLES = new Set<string>([UserRole.Member, UserRole.OrgAdmin]);\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/**\n * RFC 4180-subset CSV row parser. Handles double-quoted fields, embedded\n * commas and `\"\"` escapes. Trims surrounding whitespace per field but\n * preserves whitespace inside quotes.\n */\nfunction splitCsvLine(line: string): string[] {\n const fields: string[] = [];\n let current = '';\n let inQuotes = false;\n for (let i = 0; i < line.length; i += 1) {\n const ch = line[i];\n if (inQuotes) {\n if (ch === '\"') {\n if (line[i + 1] === '\"') {\n current += '\"';\n i += 1;\n } else {\n inQuotes = false;\n }\n } else {\n current += ch;\n }\n } else if (ch === '\"') {\n inQuotes = true;\n } else if (ch === ',') {\n fields.push(current);\n current = '';\n } else {\n current += ch;\n }\n }\n fields.push(current);\n return fields.map((f) => f.trim());\n}\n\nexport function parseBulkInviteCsv(text: string, tr: TranslationFn): BulkInviteRow[] {\n const lines = text\n .replace(/^\\uFEFF/, '')\n .split(/\\r?\\n/)\n .filter((l) => l.trim().length > 0);\n\n if (lines.length === 0) return [];\n\n const header = splitCsvLine(lines[0]).map((h) => h.toLowerCase());\n const emailIdx = header.indexOf('email');\n if (emailIdx === -1) {\n return [\n {\n rowNumber: 1,\n email: '',\n errors: [\n tr(\n 'members.bulkInvite.errors.emailColumnRequired',\n 'CSV header must include an \"email\" column.'\n ),\n ],\n },\n ];\n }\n const roleIdx = header.indexOf('role');\n const messageIdx = header.indexOf('message');\n\n const seen = new Set<string>();\n\n return lines.slice(1).map((line, idx) => {\n const fields = splitCsvLine(line);\n const rowNumber = idx + 2;\n const email = (fields[emailIdx] ?? '').toLowerCase();\n const rawRole = roleIdx >= 0 ? (fields[roleIdx] ?? '').toUpperCase() : '';\n const message = messageIdx >= 0 ? (fields[messageIdx] ?? '') : '';\n const errors: string[] = [];\n\n if (!email) {\n errors.push(tr('members.bulkInvite.errors.emailRequired', 'Email is required.'));\n } else if (!EMAIL_RE.test(email)) {\n errors.push(tr('members.bulkInvite.errors.emailInvalid', 'Invalid email format.'));\n } else if (seen.has(email)) {\n errors.push(tr('members.bulkInvite.errors.emailDuplicate', 'Duplicate email in this CSV.'));\n } else {\n seen.add(email);\n }\n\n let role: UserRole | undefined;\n if (rawRole) {\n if (VALID_ROLES.has(rawRole)) {\n role = rawRole as UserRole;\n } else {\n errors.push(\n tr(\n 'members.bulkInvite.errors.roleInvalid',\n `Invalid role \"${rawRole}\". Use MEMBER or ORG_ADMIN.`\n )\n );\n }\n }\n\n return {\n rowNumber,\n email,\n role,\n message: message || undefined,\n errors,\n };\n });\n}\n\n/**\n * Sample template content + filename. Includes a header row, a couple of\n * placeholder example rows, and a comment-style hint as a trailing row\n * users will likely delete.\n */\nexport const TEMPLATE_FILENAME = 'invite-members-template.csv';\n\nexport const TEMPLATE_CONTENT = [\n 'email,role,message',\n 'alice@example.com,MEMBER,Welcome to the team',\n 'bob@example.com,ORG_ADMIN,',\n 'carol@example.com,,',\n].join('\\n');\n\n/**\n * Map a thrown invite mutation error to a user-facing message, matching the\n * existing single-invite page's mapping (CONFLICT → already invited, etc).\n * Centralised here so single + bulk surfaces stay consistent.\n */\nexport function formatInviteError(error: unknown, tr: TranslationFn): string {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('CONFLICT')) {\n return tr('members.invite.error.conflict', 'An invite already exists for this email address.');\n }\n if (message.includes('already a member')) {\n return tr(\n 'members.invite.error.alreadyMember',\n 'This user is already a member of the organization.'\n );\n }\n return message;\n}\n\nexport function downloadTemplate(): void {\n const blob = new Blob([TEMPLATE_CONTENT], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = TEMPLATE_FILENAME;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n"],"mappings":";;AAuBA,IAAM,IAAc,IAAI,IAAY,CAAC,EAAS,QAAQ,EAAS,SAAS,CAAC,EAEnE,IAAW;AAOjB,SAAS,EAAa,GAAwB;CAC5C,IAAM,IAAmB,EAAE,EACvB,IAAU,IACV,IAAW;AACf,MAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,GAAG;EACvC,IAAM,IAAK,EAAK;AAChB,EAAI,IACE,MAAO,OACL,EAAK,IAAI,OAAO,QAClB,KAAW,MACX,KAAK,KAEL,IAAW,KAGb,KAAW,IAEJ,MAAO,OAChB,IAAW,KACF,MAAO,OAChB,EAAO,KAAK,EAAQ,EACpB,IAAU,MAEV,KAAW;;AAIf,QADA,EAAO,KAAK,EAAQ,EACb,EAAO,KAAK,MAAM,EAAE,MAAM,CAAC;;AAGpC,SAAgB,EAAmB,GAAc,GAAoC;CACnF,IAAM,IAAQ,EACX,QAAQ,WAAW,GAAG,CACtB,MAAM,QAAQ,CACd,QAAQ,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE;AAErC,KAAI,EAAM,WAAW,EAAG,QAAO,EAAE;CAEjC,IAAM,IAAS,EAAa,EAAM,GAAG,CAAC,KAAK,MAAM,EAAE,aAAa,CAAC,EAC3D,IAAW,EAAO,QAAQ,QAAQ;AACxC,KAAI,MAAa,GACf,QAAO,CACL;EACE,WAAW;EACX,OAAO;EACP,QAAQ,CACN,EACE,iDACA,+CACD,CACF;EACF,CACF;CAEH,IAAM,IAAU,EAAO,QAAQ,OAAO,EAChC,IAAa,EAAO,QAAQ,UAAU,EAEtC,oBAAO,IAAI,KAAa;AAE9B,QAAO,EAAM,MAAM,EAAE,CAAC,KAAK,GAAM,MAAQ;EACvC,IAAM,IAAS,EAAa,EAAK,EAC3B,IAAY,IAAM,GAClB,KAAS,EAAO,MAAa,IAAI,aAAa,EAC9C,IAAU,KAAW,KAAK,EAAO,MAAY,IAAI,aAAa,GAAG,IACjE,IAAU,KAAc,IAAK,EAAO,MAAe,KAAM,IACzD,IAAmB,EAAE;AAE3B,EAAK,IAEO,EAAS,KAAK,EAAM,GAErB,EAAK,IAAI,EAAM,GACxB,EAAO,KAAK,EAAG,4CAA4C,+BAA+B,CAAC,GAE3F,EAAK,IAAI,EAAM,GAJf,EAAO,KAAK,EAAG,0CAA0C,wBAAwB,CAAC,GAFlF,EAAO,KAAK,EAAG,2CAA2C,qBAAqB,CAAC;EASlF,IAAI;AAcJ,SAbI,MACE,EAAY,IAAI,EAAQ,GAC1B,IAAO,IAEP,EAAO,KACL,EACE,yCACA,iBAAiB,EAAQ,6BAC1B,CACF,GAIE;GACL;GACA;GACA;GACA,SAAS,KAAW,KAAA;GACpB;GACD;GACD;;AAQJ,IAAa,IAAoB,+BAEpB,IAAmB;CAC9B;CACA;CACA;CACA;CACD,CAAC,KAAK,KAAK;AAOZ,SAAgB,EAAkB,GAAgB,GAA2B;CAC3E,IAAM,IAAU,aAAiB,QAAQ,EAAM,UAAU,OAAO,EAAM;AAUtE,QATI,EAAQ,SAAS,WAAW,GACvB,EAAG,iCAAiC,mDAAmD,GAE5F,EAAQ,SAAS,mBAAmB,GAC/B,EACL,sCACA,qDACD,GAEI;;AAGT,SAAgB,IAAyB;CACvC,IAAM,IAAO,IAAI,KAAK,CAAC,EAAiB,EAAE,EAAE,MAAM,0BAA0B,CAAC,EACvE,IAAM,IAAI,gBAAgB,EAAK,EAC/B,IAAI,SAAS,cAAc,IAAI;AAMrC,CALA,EAAE,OAAO,GACT,EAAE,WAAW,GACb,SAAS,KAAK,YAAY,EAAE,EAC5B,EAAE,OAAO,EACT,SAAS,KAAK,YAAY,EAAE,EAC5B,IAAI,gBAAgB,EAAI"}
1
+ {"version":3,"file":"bulkInviteCsv.js","names":["VALID_ROLES","UserRole","EMAIL_RE","splitCsvLine","fields","current","inQuotes","line","ch","f","parseBulkInviteCsv","lines","text","l","header","h","emailIdx","tr","roleIdx","messageIdx","seen","rowNumber","idx","email","rawRole","message","errors","role","TEMPLATE_FILENAME","TEMPLATE_CONTENT","formatInviteError","error","downloadTemplate","blob","url","a"],"sources":["../../../../../src/organization-management/modules/members/utils/bulkInviteCsv.ts"],"sourcesContent":["/**\n * Minimal CSV parsing + template generation for bulk member invites.\n * Hand-rolled (no csv lib dep) — invite CSVs are small enough to keep\n * the parser inline. Supports double-quoted fields with embedded commas\n * and escaped quotes (RFC 4180 subset).\n *\n * Expected columns (header row required, case-insensitive, any order):\n * email — required\n * role — optional, one of MEMBER | ADMIN | OWNER (case-insensitive)\n * message — optional, free text\n */\n\nimport { UserRole } from '../../../../generated/global-types';\nimport type { TranslationFn } from '../../../shared/hooks/useTr';\n\nexport interface BulkInviteRow {\n rowNumber: number;\n email: string;\n role?: UserRole;\n message?: string;\n errors: string[];\n}\n\nconst VALID_ROLES = new Set<string>([UserRole.Member, UserRole.OrgAdmin]);\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/**\n * RFC 4180-subset CSV row parser. Handles double-quoted fields, embedded\n * commas and `\"\"` escapes. Trims surrounding whitespace per field but\n * preserves whitespace inside quotes.\n */\nfunction splitCsvLine(line: string): string[] {\n const fields: string[] = [];\n let current = '';\n let inQuotes = false;\n for (let i = 0; i < line.length; i += 1) {\n const ch = line[i];\n if (inQuotes) {\n if (ch === '\"') {\n if (line[i + 1] === '\"') {\n current += '\"';\n i += 1;\n } else {\n inQuotes = false;\n }\n } else {\n current += ch;\n }\n } else if (ch === '\"') {\n inQuotes = true;\n } else if (ch === ',') {\n fields.push(current);\n current = '';\n } else {\n current += ch;\n }\n }\n fields.push(current);\n return fields.map((f) => f.trim());\n}\n\nexport function parseBulkInviteCsv(text: string, tr: TranslationFn): BulkInviteRow[] {\n const lines = text\n .replace(/^\\uFEFF/, '')\n .split(/\\r?\\n/)\n .filter((l) => l.trim().length > 0);\n\n if (lines.length === 0) return [];\n\n const header = splitCsvLine(lines[0]).map((h) => h.toLowerCase());\n const emailIdx = header.indexOf('email');\n if (emailIdx === -1) {\n return [\n {\n rowNumber: 1,\n email: '',\n errors: [\n tr(\n 'members.bulkInvite.errors.emailColumnRequired',\n 'CSV header must include an \"email\" column.'\n ),\n ],\n },\n ];\n }\n const roleIdx = header.indexOf('role');\n const messageIdx = header.indexOf('message');\n\n const seen = new Set<string>();\n\n return lines.slice(1).map((line, idx) => {\n const fields = splitCsvLine(line);\n const rowNumber = idx + 2;\n const email = (fields[emailIdx] ?? '').toLowerCase();\n const rawRole = roleIdx >= 0 ? (fields[roleIdx] ?? '').toUpperCase() : '';\n const message = messageIdx >= 0 ? (fields[messageIdx] ?? '') : '';\n const errors: string[] = [];\n\n if (!email) {\n errors.push(tr('members.bulkInvite.errors.emailRequired', 'Email is required.'));\n } else if (!EMAIL_RE.test(email)) {\n errors.push(tr('members.bulkInvite.errors.emailInvalid', 'Invalid email format.'));\n } else if (seen.has(email)) {\n errors.push(tr('members.bulkInvite.errors.emailDuplicate', 'Duplicate email in this CSV.'));\n } else {\n seen.add(email);\n }\n\n let role: UserRole | undefined;\n if (rawRole) {\n if (VALID_ROLES.has(rawRole)) {\n role = rawRole as UserRole;\n } else {\n errors.push(\n tr(\n 'members.bulkInvite.errors.roleInvalid',\n `Invalid role \"${rawRole}\". Use MEMBER or ORG_ADMIN.`\n )\n );\n }\n }\n\n return {\n rowNumber,\n email,\n role,\n message: message || undefined,\n errors,\n };\n });\n}\n\n/**\n * Sample template content + filename. Includes a header row, a couple of\n * placeholder example rows, and a comment-style hint as a trailing row\n * users will likely delete.\n */\nexport const TEMPLATE_FILENAME = 'invite-members-template.csv';\n\nexport const TEMPLATE_CONTENT = [\n 'email,role,message',\n 'alice@example.com,MEMBER,Welcome to the team',\n 'bob@example.com,ORG_ADMIN,',\n 'carol@example.com,,',\n].join('\\n');\n\n/**\n * Map a thrown invite mutation error to a user-facing message, matching the\n * existing single-invite page's mapping (CONFLICT → already invited, etc).\n * Centralised here so single + bulk surfaces stay consistent.\n */\nexport function formatInviteError(error: unknown, tr: TranslationFn): string {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('CONFLICT')) {\n return tr('members.invite.error.conflict', 'An invite already exists for this email address.');\n }\n if (message.includes('already a member')) {\n return tr(\n 'members.invite.error.alreadyMember',\n 'This user is already a member of the organization.'\n );\n }\n return message;\n}\n\nexport function downloadTemplate(): void {\n const blob = new Blob([TEMPLATE_CONTENT], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = TEMPLATE_FILENAME;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- //#region src/organization-management/modules/members/utils/workspaceInvitationDisplay.ts
1
+ // src/organization-management/modules/members/utils/workspaceInvitationDisplay.ts
2
2
  function e(e) {
3
3
  let t = e.context?.metadata;
4
4
  return t && typeof t == "object" && !Array.isArray(t) ? t : null;
@@ -26,7 +26,6 @@ function r(t, n) {
26
26
  pluralSuffix: s === 1 ? "" : "s"
27
27
  })] : [`${s} project${s === 1 ? "" : "s"} selected`];
28
28
  }
29
- //#endregion
30
29
  export { r as getProjectDisplayNames, n as getRoleDisplayNames, t as getWorkspaceDisplayName };
31
30
 
32
31
  //# sourceMappingURL=workspaceInvitationDisplay.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workspaceInvitationDisplay.js","names":[],"sources":["../../../../../src/organization-management/modules/members/utils/workspaceInvitationDisplay.ts"],"sourcesContent":["import type { Invitation } from '../../../../generated/wspace-types';\n\nimport type { TranslationFn } from '../../../shared/hooks/useTr';\n\ntype InvitationLike = Pick<Invitation, 'workspaceId' | 'roleIds' | 'projectId' | 'context'> & {\n workspaceName?: string;\n projectIds?: string[];\n roleNames?: string[];\n};\n\nfunction readMetadata(invitation: InvitationLike): Record<string, unknown> | null {\n const metadata = invitation.context?.metadata;\n if (metadata && typeof metadata === 'object' && !Array.isArray(metadata)) {\n return metadata as Record<string, unknown>;\n }\n\n return null;\n}\n\nexport function getWorkspaceDisplayName(invitation: InvitationLike): string {\n if (invitation.workspaceName) {\n return invitation.workspaceName;\n }\n\n const metadata = readMetadata(invitation);\n const workspaceName = metadata?.workspaceName;\n if (typeof workspaceName === 'string' && workspaceName.trim().length > 0) {\n return workspaceName;\n }\n\n return invitation.workspaceId || '—';\n}\n\nexport function getRoleDisplayNames(invitation: InvitationLike): string[] {\n if (Array.isArray(invitation.roleNames) && invitation.roleNames.length > 0) {\n return invitation.roleNames;\n }\n\n const metadata = readMetadata(invitation);\n const roleNames = metadata?.roleNames;\n if (Array.isArray(roleNames) && roleNames.every((value) => typeof value === 'string')) {\n return roleNames;\n }\n\n return [];\n}\n\nexport function getProjectDisplayNames(invitation: InvitationLike, tr?: TranslationFn): string[] {\n const metadata = readMetadata(invitation);\n const projectNames = metadata?.projectNames;\n if (Array.isArray(projectNames) && projectNames.every((value) => typeof value === 'string')) {\n return projectNames;\n }\n\n const metadataProjectIds = metadata?.projectIds;\n const projectIds = [\n ...(Array.isArray(invitation.projectIds) ? invitation.projectIds : []),\n ...(invitation.projectId ? [invitation.projectId] : []),\n ...(Array.isArray(metadataProjectIds)\n ? metadataProjectIds.filter((value): value is string => typeof value === 'string')\n : []),\n ];\n const projectCount = new Set(projectIds).size;\n\n if (projectCount === 0) {\n return [];\n }\n\n if (!tr) {\n return [`${projectCount} project${projectCount === 1 ? '' : 's'} selected`];\n }\n\n return [\n tr('members.myInvites.projectCount', '{{count}} project{{pluralSuffix}} selected', {\n count: projectCount,\n pluralSuffix: projectCount === 1 ? '' : 's',\n }),\n ];\n}\n"],"mappings":";AAUA,SAAS,EAAa,GAA4D;CAChF,IAAM,IAAW,EAAW,SAAS;AAKrC,QAJI,KAAY,OAAO,KAAa,YAAY,CAAC,MAAM,QAAQ,EAAS,GAC/D,IAGF;;AAGT,SAAgB,EAAwB,GAAoC;AAC1E,KAAI,EAAW,cACb,QAAO,EAAW;CAIpB,IAAM,IADW,EAAa,EAAW,EACT;AAKhC,QAJI,OAAO,KAAkB,YAAY,EAAc,MAAM,CAAC,SAAS,IAC9D,IAGF,EAAW,eAAe;;AAGnC,SAAgB,EAAoB,GAAsC;AACxE,KAAI,MAAM,QAAQ,EAAW,UAAU,IAAI,EAAW,UAAU,SAAS,EACvE,QAAO,EAAW;CAIpB,IAAM,IADW,EAAa,EAAW,EACb;AAK5B,QAJI,MAAM,QAAQ,EAAU,IAAI,EAAU,OAAO,MAAU,OAAO,KAAU,SAAS,GAC5E,IAGF,EAAE;;AAGX,SAAgB,EAAuB,GAA4B,GAA8B;CAC/F,IAAM,IAAW,EAAa,EAAW,EACnC,IAAe,GAAU;AAC/B,KAAI,MAAM,QAAQ,EAAa,IAAI,EAAa,OAAO,MAAU,OAAO,KAAU,SAAS,CACzF,QAAO;CAGT,IAAM,IAAqB,GAAU,YAC/B,IAAa;EACjB,GAAI,MAAM,QAAQ,EAAW,WAAW,GAAG,EAAW,aAAa,EAAE;EACrE,GAAI,EAAW,YAAY,CAAC,EAAW,UAAU,GAAG,EAAE;EACtD,GAAI,MAAM,QAAQ,EAAmB,GACjC,EAAmB,QAAQ,MAA2B,OAAO,KAAU,SAAS,GAChF,EAAE;EACP,EACK,IAAe,IAAI,IAAI,EAAW,CAAC;AAUzC,QARI,MAAiB,IACZ,EAAE,GAGN,IAIE,CACL,EAAG,kCAAkC,8CAA8C;EACjF,OAAO;EACP,cAAc,MAAiB,IAAI,KAAK;EACzC,CAAC,CACH,GARQ,CAAC,GAAG,EAAa,UAAU,MAAiB,IAAI,KAAK,IAAI,WAAW"}
1
+ {"version":3,"file":"workspaceInvitationDisplay.js","names":["readMetadata","metadata","invitation","getWorkspaceDisplayName","workspaceName","getRoleDisplayNames","roleNames","value","getProjectDisplayNames","projectNames","metadataProjectIds","projectIds","projectCount","tr"],"sources":["../../../../../src/organization-management/modules/members/utils/workspaceInvitationDisplay.ts"],"sourcesContent":["import type { Invitation } from '../../../../generated/wspace-types';\n\nimport type { TranslationFn } from '../../../shared/hooks/useTr';\n\ntype InvitationLike = Pick<Invitation, 'workspaceId' | 'roleIds' | 'projectId' | 'context'> & {\n workspaceName?: string;\n projectIds?: string[];\n roleNames?: string[];\n};\n\nfunction readMetadata(invitation: InvitationLike): Record<string, unknown> | null {\n const metadata = invitation.context?.metadata;\n if (metadata && typeof metadata === 'object' && !Array.isArray(metadata)) {\n return metadata as Record<string, unknown>;\n }\n\n return null;\n}\n\nexport function getWorkspaceDisplayName(invitation: InvitationLike): string {\n if (invitation.workspaceName) {\n return invitation.workspaceName;\n }\n\n const metadata = readMetadata(invitation);\n const workspaceName = metadata?.workspaceName;\n if (typeof workspaceName === 'string' && workspaceName.trim().length > 0) {\n return workspaceName;\n }\n\n return invitation.workspaceId || '—';\n}\n\nexport function getRoleDisplayNames(invitation: InvitationLike): string[] {\n if (Array.isArray(invitation.roleNames) && invitation.roleNames.length > 0) {\n return invitation.roleNames;\n }\n\n const metadata = readMetadata(invitation);\n const roleNames = metadata?.roleNames;\n if (Array.isArray(roleNames) && roleNames.every((value) => typeof value === 'string')) {\n return roleNames;\n }\n\n return [];\n}\n\nexport function getProjectDisplayNames(invitation: InvitationLike, tr?: TranslationFn): string[] {\n const metadata = readMetadata(invitation);\n const projectNames = metadata?.projectNames;\n if (Array.isArray(projectNames) && projectNames.every((value) => typeof value === 'string')) {\n return projectNames;\n }\n\n const metadataProjectIds = metadata?.projectIds;\n const projectIds = [\n ...(Array.isArray(invitation.projectIds) ? invitation.projectIds : []),\n ...(invitation.projectId ? [invitation.projectId] : []),\n ...(Array.isArray(metadataProjectIds)\n ? metadataProjectIds.filter((value): value is string => typeof value === 'string')\n : []),\n ];\n const projectCount = new Set(projectIds).size;\n\n if (projectCount === 0) {\n return [];\n }\n\n if (!tr) {\n return [`${projectCount} project${projectCount === 1 ? '' : 's'} selected`];\n }\n\n return [\n tr('members.myInvites.projectCount', '{{count}} project{{pluralSuffix}} selected', {\n count: projectCount,\n pluralSuffix: projectCount === 1 ? '' : 's',\n }),\n ];\n}\n"],"mappings":";AAUA,SAASA,EAAa,GAA4D;CAChF,IAAMC,IAAWC,EAAW,SAAS;CAKrC,OAJID,KAAY,OAAOA,KAAa,YAAY,CAAC,MAAM,QAAQA,CAAQ,IAC9DA,IAGF;AACT;AAEA,SAAgBE,EAAwB,GAAoC;CAC1E,IAAID,EAAW,eACb,OAAOA,EAAW;CAIpB,IAAME,IADWJ,EAAaE,CACR,CAAA,EAAU;CAKhC,OAJI,OAAOE,KAAkB,YAAYA,EAAc,KAAK,CAAC,CAAC,SAAS,IAC9DA,IAGFF,EAAW,eAAe;AACnC;AAEA,SAAgBG,EAAoB,GAAsC;CACxE,IAAI,MAAM,QAAQH,EAAW,SAAS,KAAKA,EAAW,UAAU,SAAS,GACvE,OAAOA,EAAW;CAIpB,IAAMI,IADWN,EAAaE,CACZ,CAAA,EAAU;CAK5B,OAJI,MAAM,QAAQI,CAAS,KAAKA,EAAU,OAAO,MAAU,OAAOC,KAAU,QAAQ,IAC3ED,IAGF,CAAC;AACV;AAEA,SAAgBE,EAAuB,GAA4B,GAA8B;CAC/F,IAAMP,IAAWD,EAAaE,CAAU,GAClCO,IAAeR,GAAU;CAC/B,IAAI,MAAM,QAAQQ,CAAY,KAAKA,EAAa,OAAO,MAAU,OAAOF,KAAU,QAAQ,GACxF,OAAOE;CAGT,IAAMC,IAAqBT,GAAU,YAC/BU,IAAa;EACjB,GAAI,MAAM,QAAQT,EAAW,UAAU,IAAIA,EAAW,aAAa,CAAC;EACpE,GAAIA,EAAW,YAAY,CAACA,EAAW,SAAS,IAAI,CAAC;EACrD,GAAI,MAAM,QAAQQ,CAAkB,IAChCA,EAAmB,QAAQ,MAA2B,OAAOH,KAAU,QAAQ,IAC/E,CAAC;CACP,GACMK,IAAe,IAAI,IAAID,CAAU,CAAC,CAAC;CAUzC,OARIC,MAAiB,IACZ,CAAC,IAGLC,IAIE,CACLA,EAAG,kCAAkC,8CAA8C;EACjF,OAAOD;EACP,cAAcA,MAAiB,IAAI,KAAK;CAC1C,CAAC,CACH,IARS,CAAC,GAAGA,EAAa,UAAUA,MAAiB,IAAI,KAAK,IAAI,UAAU;AAS9E"}
@@ -1,12 +1,12 @@
1
- import { useGetOrganizationBySlugLazyQuery as e } from "../../../../generated/global-operations.js";
2
- import { useTr as t } from "../../../shared/hooks/useTr.js";
1
+ import { ZodError as e } from "../../../../node_modules/zod/v4/classic/errors.js";
2
+ import { useGetOrganizationBySlugLazyQuery as t } from "../../../../generated/global-operations.js";
3
3
  import { useDebouncedValue as n } from "../../../shared/hooks/useDebouncedValue.js";
4
- import { ZodError as r } from "../../../../node_modules/zod/v3/ZodError.js";
4
+ import { useTr as r } from "../../../shared/hooks/useTr.js";
5
5
  import { createOrganizationSchema as i, updateOrganizationSchema as a } from "../schemas/index.js";
6
6
  import { useEffect as o, useMemo as s, useRef as c, useState as l } from "react";
7
7
  import { Loader2 as u } from "lucide-react";
8
8
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
9
- //#region src/organization-management/modules/organizations/components/OrganizationForm.tsx
9
+ // src/organization-management/modules/organizations/components/OrganizationForm.tsx
10
10
  function p(e) {
11
11
  return e.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
12
12
  }
@@ -18,7 +18,7 @@ function m(e) {
18
18
  }
19
19
  }
20
20
  function h({ organization: h, tenantId: g, tenantName: _, hideTenantSelector: v = !1, onSubmit: y, onCancel: b, loading: x }) {
21
- let S = t(), C = !h, w = h?.id ?? null, [T, E] = l({
21
+ let S = r(), C = !h, w = h?.id ?? null, [T, E] = l({
22
22
  name: h?.name || "",
23
23
  slug: h?.slug || "",
24
24
  description: h?.description || "",
@@ -28,9 +28,9 @@ function h({ organization: h, tenantId: g, tenantName: _, hideTenantSelector: v
28
28
  }), [D, O] = l({}), [k, A] = l(!1), [j, M] = l({
29
29
  tone: "muted",
30
30
  message: S("organizations.form.slugAutoGenerated", "Slug is auto-generated from the organization name.")
31
- }), N = c(0), P = c(null), F = c(null), I = n(T.slug, 350), [L] = e({ fetchPolicy: "network-only" }), R = s(() => T.tenantId ? _ ? `${_} (${T.tenantId})` : T.tenantId : "", [T.tenantId, _]);
31
+ }), N = c(0), P = c(null), F = c(null), I = n(T.slug, 350), [L] = t({ fetchPolicy: "network-only" }), R = s(() => T.tenantId ? _ ? `${_} (${T.tenantId})` : T.tenantId : "", [T.tenantId, _]);
32
32
  o(() => {
33
- !C || g === void 0 || E((e) => e.tenantId === g ? e : {
33
+ C && g !== void 0 && E((e) => e.tenantId === g ? e : {
34
34
  ...e,
35
35
  tenantId: g
36
36
  });
@@ -108,13 +108,13 @@ function h({ organization: h, tenantId: g, tenantName: _, hideTenantSelector: v
108
108
  let z = () => {
109
109
  try {
110
110
  return (h ? a(S) : i(S)).parse(T), O({}), !0;
111
- } catch (e) {
112
- if (e instanceof r) {
113
- let t = {};
114
- e.issues.forEach((e) => {
115
- let n = e.path.join(".");
116
- t[n] = e.message;
117
- }), O(t);
111
+ } catch (t) {
112
+ if (t instanceof e) {
113
+ let e = {};
114
+ t.issues.forEach((t) => {
115
+ let n = t.path.join(".");
116
+ e[n] = t.message;
117
+ }), O(e);
118
118
  }
119
119
  return !1;
120
120
  }
@@ -325,7 +325,6 @@ function h({ organization: h, tenantId: g, tenantName: _, hideTenantSelector: v
325
325
  ]
326
326
  });
327
327
  }
328
- //#endregion
329
328
  export { h as OrganizationForm };
330
329
 
331
330
  //# sourceMappingURL=OrganizationForm.js.map