@burdenoff/microfe-organization 2026.1026.1 → 2026.1101.2

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 +8 -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":"useWorkspaces.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/hooks/useWorkspaces.ts"],"sourcesContent":["import {\n useGetWorkspacesQuery,\n useGetMyWorkspacesQuery,\n useGetWorkspaceQuery,\n useGetTenantsQuery,\n useCreateWorkspaceMutation,\n useUpdateWorkspaceMutation,\n useSuspendWorkspaceMutation,\n GetWorkspacesDocument,\n} from '../../../../generated/global-operations';\nimport type {\n Workspace,\n WorkspaceFilterInput,\n CreateWorkspaceInput,\n UpdateWorkspaceInput,\n} from '../types';\n\n/**\n * Scope of the workspace listing:\n * - `'my'` — membership-scoped via `myWorkspaces` (@rbac scopeType: \"self\").\n * The correct scope for user-facing app shells; a regular user only\n * ever sees the workspaces they belong to. `myWorkspaces` takes no\n * server-side filter arg, so callers filter client-side.\n * - `'all'` — platform-wide via `allWorkspaces` (@rbac scopeType: \"global\",\n * super-admin / platform-admin only). Reserved for the admin app.\n */\nexport type WorkspacesScope = 'my' | 'all';\n\n/**\n * Hook to fetch workspaces with filtering and pagination.\n * Uses offset-based pagination (limit/offset).\n *\n * `scope` selects the backing query so the user shells (`'my'`) never call the\n * global-scoped `allWorkspaces`; the admin app keeps `'all'`. Both queries are\n * declared (rules-of-hooks) and the inactive one is skipped.\n */\nexport function useWorkspaces(\n filter?: WorkspaceFilterInput,\n limit: number = 20,\n offset: number = 0,\n scope: WorkspacesScope = 'all'\n) {\n const allResult = useGetWorkspacesQuery({\n variables: { filter, limit, offset },\n skip: scope !== 'all',\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n const myResult = useGetMyWorkspacesQuery({\n variables: { limit, offset },\n skip: scope !== 'my',\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n const { loading, error, refetch, fetchMore } = scope === 'my' ? myResult : allResult;\n const list = scope === 'my' ? myResult.data?.myWorkspaces : allResult.data?.allWorkspaces;\n\n return {\n workspaces: (list?.items as Workspace[]) || [],\n total: list?.total || 0,\n limit: list?.limit || limit,\n offset: list?.offset || offset,\n hasMore: list?.hasMore || false,\n loading,\n error,\n refetch,\n fetchMore,\n };\n}\n\n/**\n * Hook to fetch a single workspace by ID\n */\nexport function useWorkspace(id: string) {\n const { data, loading, error, refetch } = useGetWorkspaceQuery({\n variables: { id },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n workspace: data?.workspace as Workspace | undefined,\n loading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook to fetch workspaces by organization ID\n */\nexport function useWorkspacesByOrganization(\n organizationId: string,\n limit: number = 20,\n offset: number = 0\n) {\n // User-facing organization pages must stay membership-scoped. `myWorkspaces`\n // has no organization filter arg, so fetch the caller-visible list and narrow\n // it client-side to the current organization.\n const effectiveLimit = Math.max(limit + offset, 200);\n const { data, loading, error, refetch, fetchMore } = useGetMyWorkspacesQuery({\n variables: { limit: effectiveLimit, offset: 0 },\n skip: !organizationId,\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n });\n\n const organizationWorkspaces = (\n (data?.myWorkspaces?.items as Workspace[] | undefined) ?? []\n ).filter((workspace) => workspace.organizationId === organizationId);\n const paginatedWorkspaces = organizationWorkspaces.slice(offset, offset + limit);\n\n return {\n workspaces: paginatedWorkspaces,\n total: organizationWorkspaces.length,\n hasMore: offset + paginatedWorkspaces.length < organizationWorkspaces.length,\n loading,\n error,\n refetch,\n fetchMore,\n };\n}\n\n/**\n * Hook to create a new workspace\n */\nexport function useCreateWorkspace() {\n const [createWorkspace, { data, loading, error }] = useCreateWorkspaceMutation({\n refetchQueries: [GetWorkspacesDocument],\n });\n\n return {\n createWorkspace: (input: CreateWorkspaceInput) => createWorkspace({ variables: { input } }),\n data,\n loading,\n error,\n };\n}\n\n/**\n * Hook to update a workspace\n */\nexport function useUpdateWorkspace() {\n const [updateWorkspace, { data, loading, error }] = useUpdateWorkspaceMutation();\n\n return {\n updateWorkspace: (id: string, input: UpdateWorkspaceInput) =>\n updateWorkspace({ variables: { id, input } }),\n data,\n loading,\n error,\n };\n}\n\n/**\n * Hook to delete (suspend) a workspace\n * Note: Backend doesn't have deleteWorkspace, using suspendWorkspace instead\n */\nexport function useDeleteWorkspace() {\n const [deleteWorkspace, { data, loading, error }] = useSuspendWorkspaceMutation({\n refetchQueries: [GetWorkspacesDocument],\n });\n\n return {\n deleteWorkspace: (id: string) => deleteWorkspace({ variables: { id } }),\n data,\n loading,\n error,\n };\n}\n\n/**\n * Tenant type for the tenants query\n */\ninterface Tenant {\n id: string;\n name: string;\n slug: string;\n status: string;\n /** SHARED | DEDICATED — lets the UI prefer the shared tenant when auto-selecting. */\n type?: string;\n}\n\n/**\n * Hook to fetch tenants available to the current actor for workspace creation\n */\nexport function useTenants(limit: number = 100, offset: number = 0, enabled: boolean = true) {\n const { data, loading, error, refetch } = useGetTenantsQuery({\n variables: { limit, offset },\n skip: !enabled,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n tenants: (data?.myTenants?.items as Tenant[]) || [],\n total: data?.myTenants?.total || 0,\n loading,\n error,\n refetch,\n };\n}\n"],"mappings":";;AAoCA,SAAgB,EACd,GACA,IAAgB,IAChB,IAAiB,GACjB,IAAyB,OACzB;CACA,IAAM,IAAY,EAAsB;EACtC,WAAW;GAAE;GAAQ;GAAO;GAAQ;EACpC,MAAM,MAAU;EAChB,aAAa;EACb,iBAAiB;EAClB,CAAC,EACI,IAAW,EAAwB;EACvC,WAAW;GAAE;GAAO;GAAQ;EAC5B,MAAM,MAAU;EAChB,aAAa;EACb,iBAAiB;EAClB,CAAC,EAEI,EAAE,YAAS,UAAO,YAAS,iBAAc,MAAU,OAAO,IAAW,GACrE,IAAO,MAAU,OAAO,EAAS,MAAM,eAAe,EAAU,MAAM;AAE5E,QAAO;EACL,YAAa,GAAM,SAAyB,EAAE;EAC9C,OAAO,GAAM,SAAS;EACtB,OAAO,GAAM,SAAS;EACtB,QAAQ,GAAM,UAAU;EACxB,SAAS,GAAM,WAAW;EAC1B;EACA;EACA;EACA;EACD;;AAMH,SAAgB,EAAa,GAAY;CACvC,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAAqB;EAC7D,WAAW,EAAE,OAAI;EACjB,MAAM,CAAC;EACP,aAAa;EACb,iBAAiB;EAClB,CAAC;AAEF,QAAO;EACL,WAAW,GAAM;EACjB;EACA;EACA;EACD;;AAMH,SAAgB,EACd,GACA,IAAgB,IAChB,IAAiB,GACjB;CAKA,IAAM,EAAE,SAAM,YAAS,UAAO,YAAS,iBAAc,EAAwB;EAC3E,WAAW;GAAE,OAFQ,KAAK,IAAI,IAAQ,GAAQ,IAAI;GAEd,QAAQ;GAAG;EAC/C,MAAM,CAAC;EACP,aAAa;EACb,iBAAiB;EAClB,CAAC,EAEI,KACH,GAAM,cAAc,SAAqC,EAAE,EAC5D,QAAQ,MAAc,EAAU,mBAAmB,EAAe,EAC9D,IAAsB,EAAuB,MAAM,GAAQ,IAAS,EAAM;AAEhF,QAAO;EACL,YAAY;EACZ,OAAO,EAAuB;EAC9B,SAAS,IAAS,EAAoB,SAAS,EAAuB;EACtE;EACA;EACA;EACA;EACD;;AAMH,SAAgB,IAAqB;CACnC,IAAM,CAAC,GAAiB,EAAE,SAAM,YAAS,cAAW,EAA2B,EAC7E,gBAAgB,CAAC,EAAsB,EACxC,CAAC;AAEF,QAAO;EACL,kBAAkB,MAAgC,EAAgB,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC;EAC3F;EACA;EACA;EACD;;AAMH,SAAgB,IAAqB;CACnC,IAAM,CAAC,GAAiB,EAAE,SAAM,YAAS,cAAW,GAA4B;AAEhF,QAAO;EACL,kBAAkB,GAAY,MAC5B,EAAgB,EAAE,WAAW;GAAE;GAAI;GAAO,EAAE,CAAC;EAC/C;EACA;EACA;EACD;;AAOH,SAAgB,IAAqB;CACnC,IAAM,CAAC,GAAiB,EAAE,SAAM,YAAS,cAAW,EAA4B,EAC9E,gBAAgB,CAAC,EAAsB,EACxC,CAAC;AAEF,QAAO;EACL,kBAAkB,MAAe,EAAgB,EAAE,WAAW,EAAE,OAAI,EAAE,CAAC;EACvE;EACA;EACA;EACD;;AAkBH,SAAgB,EAAW,IAAgB,KAAK,IAAiB,GAAG,IAAmB,IAAM;CAC3F,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAAmB;EAC3D,WAAW;GAAE;GAAO;GAAQ;EAC5B,MAAM,CAAC;EACP,aAAa;EACb,iBAAiB;EAClB,CAAC;AAEF,QAAO;EACL,SAAU,GAAM,WAAW,SAAsB,EAAE;EACnD,OAAO,GAAM,WAAW,SAAS;EACjC;EACA;EACA;EACD"}
1
+ {"version":3,"file":"useWorkspaces.js","names":["useWorkspaces","allResult","useGetWorkspacesQuery","scope","myResult","useGetMyWorkspacesQuery","list","limit","offset","useWorkspace","useGetWorkspaceQuery","id","data","useWorkspacesByOrganization","effectiveLimit","organizationId","organizationWorkspaces","workspace","paginatedWorkspaces","useCreateWorkspace","createWorkspace","useCreateWorkspaceMutation","GetWorkspacesDocument","useUpdateWorkspace","updateWorkspace","useUpdateWorkspaceMutation","useDeleteWorkspace","deleteWorkspace","useSuspendWorkspaceMutation","useTenants","useGetTenantsQuery","enabled"],"sources":["../../../../../src/organization-management/modules/workspaces/hooks/useWorkspaces.ts"],"sourcesContent":["import {\n useGetWorkspacesQuery,\n useGetMyWorkspacesQuery,\n useGetWorkspaceQuery,\n useGetTenantsQuery,\n useCreateWorkspaceMutation,\n useUpdateWorkspaceMutation,\n useSuspendWorkspaceMutation,\n GetWorkspacesDocument,\n} from '../../../../generated/global-operations';\nimport type {\n Workspace,\n WorkspaceFilterInput,\n CreateWorkspaceInput,\n UpdateWorkspaceInput,\n} from '../types';\n\n/**\n * Scope of the workspace listing:\n * - `'my'` — membership-scoped via `myWorkspaces` (@rbac scopeType: \"self\").\n * The correct scope for user-facing app shells; a regular user only\n * ever sees the workspaces they belong to. `myWorkspaces` takes no\n * server-side filter arg, so callers filter client-side.\n * - `'all'` — platform-wide via `allWorkspaces` (@rbac scopeType: \"global\",\n * super-admin / platform-admin only). Reserved for the admin app.\n */\nexport type WorkspacesScope = 'my' | 'all';\n\n/**\n * Hook to fetch workspaces with filtering and pagination.\n * Uses offset-based pagination (limit/offset).\n *\n * `scope` selects the backing query so the user shells (`'my'`) never call the\n * global-scoped `allWorkspaces`; the admin app keeps `'all'`. Both queries are\n * declared (rules-of-hooks) and the inactive one is skipped.\n */\nexport function useWorkspaces(\n filter?: WorkspaceFilterInput,\n limit: number = 20,\n offset: number = 0,\n scope: WorkspacesScope = 'all'\n) {\n const allResult = useGetWorkspacesQuery({\n variables: { filter, limit, offset },\n skip: scope !== 'all',\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n const myResult = useGetMyWorkspacesQuery({\n variables: { limit, offset },\n skip: scope !== 'my',\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n const { loading, error, refetch, fetchMore } = scope === 'my' ? myResult : allResult;\n const list = scope === 'my' ? myResult.data?.myWorkspaces : allResult.data?.allWorkspaces;\n\n return {\n workspaces: (list?.items as Workspace[]) || [],\n total: list?.total || 0,\n limit: list?.limit || limit,\n offset: list?.offset || offset,\n hasMore: list?.hasMore || false,\n loading,\n error,\n refetch,\n fetchMore,\n };\n}\n\n/**\n * Hook to fetch a single workspace by ID\n */\nexport function useWorkspace(id: string) {\n const { data, loading, error, refetch } = useGetWorkspaceQuery({\n variables: { id },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n workspace: data?.workspace as Workspace | undefined,\n loading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook to fetch workspaces by organization ID\n */\nexport function useWorkspacesByOrganization(\n organizationId: string,\n limit: number = 20,\n offset: number = 0\n) {\n // User-facing organization pages must stay membership-scoped. `myWorkspaces`\n // has no organization filter arg, so fetch the caller-visible list and narrow\n // it client-side to the current organization.\n const effectiveLimit = Math.max(limit + offset, 200);\n const { data, loading, error, refetch, fetchMore } = useGetMyWorkspacesQuery({\n variables: { limit: effectiveLimit, offset: 0 },\n skip: !organizationId,\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n });\n\n const organizationWorkspaces = (\n (data?.myWorkspaces?.items as Workspace[] | undefined) ?? []\n ).filter((workspace) => workspace.organizationId === organizationId);\n const paginatedWorkspaces = organizationWorkspaces.slice(offset, offset + limit);\n\n return {\n workspaces: paginatedWorkspaces,\n total: organizationWorkspaces.length,\n hasMore: offset + paginatedWorkspaces.length < organizationWorkspaces.length,\n loading,\n error,\n refetch,\n fetchMore,\n };\n}\n\n/**\n * Hook to create a new workspace\n */\nexport function useCreateWorkspace() {\n const [createWorkspace, { data, loading, error }] = useCreateWorkspaceMutation({\n refetchQueries: [GetWorkspacesDocument],\n });\n\n return {\n createWorkspace: (input: CreateWorkspaceInput) => createWorkspace({ variables: { input } }),\n data,\n loading,\n error,\n };\n}\n\n/**\n * Hook to update a workspace\n */\nexport function useUpdateWorkspace() {\n const [updateWorkspace, { data, loading, error }] = useUpdateWorkspaceMutation();\n\n return {\n updateWorkspace: (id: string, input: UpdateWorkspaceInput) =>\n updateWorkspace({ variables: { id, input } }),\n data,\n loading,\n error,\n };\n}\n\n/**\n * Hook to delete (suspend) a workspace\n * Note: Backend doesn't have deleteWorkspace, using suspendWorkspace instead\n */\nexport function useDeleteWorkspace() {\n const [deleteWorkspace, { data, loading, error }] = useSuspendWorkspaceMutation({\n refetchQueries: [GetWorkspacesDocument],\n });\n\n return {\n deleteWorkspace: (id: string) => deleteWorkspace({ variables: { id } }),\n data,\n loading,\n error,\n };\n}\n\n/**\n * Tenant type for the tenants query\n */\ninterface Tenant {\n id: string;\n name: string;\n slug: string;\n status: string;\n /** SHARED | DEDICATED — lets the UI prefer the shared tenant when auto-selecting. */\n type?: string;\n}\n\n/**\n * Hook to fetch tenants available to the current actor for workspace creation\n */\nexport function useTenants(limit: number = 100, offset: number = 0, enabled: boolean = true) {\n const { data, loading, error, refetch } = useGetTenantsQuery({\n variables: { limit, offset },\n skip: !enabled,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n return {\n tenants: (data?.myTenants?.items as Tenant[]) || [],\n total: data?.myTenants?.total || 0,\n loading,\n error,\n refetch,\n };\n}\n"],"mappings":";;AAoCA,SAAgBA,EACd,GACA,IAAgB,IAChB,IAAiB,GACjB,IAAyB,OACzB;CACA,IAAMC,IAAYC,EAAsB;EACtC,WAAW;GAAE;GAAQ;GAAO;EAAO;EACnC,MAAMC,MAAU;EAChB,aAAa;EACb,iBAAiB;CACnB,CAAC,GACKC,IAAWC,EAAwB;EACvC,WAAW;GAAE;GAAO;EAAO;EAC3B,MAAMF,MAAU;EAChB,aAAa;EACb,iBAAiB;CACnB,CAAC,GAEK,EAAE,YAAS,UAAO,YAAS,iBAAcA,MAAU,OAAOC,IAAWH,GACrEK,IAAOH,MAAU,OAAOC,EAAS,MAAM,eAAeH,EAAU,MAAM;CAE5E,OAAO;EACL,YAAaK,GAAM,SAAyB,CAAC;EAC7C,OAAOA,GAAM,SAAS;EACtB,OAAOA,GAAM,SAASC;EACtB,QAAQD,GAAM,UAAUE;EACxB,SAASF,GAAM,WAAW;EAC1B;EACA;EACA;EACA;CACF;AACF;AAKA,SAAgBG,EAAa,GAAY;CACvC,IAAM,EAAE,SAAM,YAAS,UAAO,eAAYC,EAAqB;EAC7D,WAAW,EAAE,MAAG;EAChB,MAAM,CAACC;EACP,aAAa;EACb,iBAAiB;CACnB,CAAC;CAED,OAAO;EACL,WAAWC,GAAM;EACjB;EACA;EACA;CACF;AACF;AAKA,SAAgBC,EACd,GACA,IAAgB,IAChB,IAAiB,GACjB;CAIA,IAAMC,IAAiB,KAAK,IAAIP,IAAQC,GAAQ,GAAG,GAC7C,EAAE,SAAM,YAAS,UAAO,YAAS,iBAAcH,EAAwB;EAC3E,WAAW;GAAE,OAAOS;GAAgB,QAAQ;EAAE;EAC9C,MAAM,CAACC;EACP,aAAa;EACb,iBAAiB;CACnB,CAAC,GAEKC,KACHJ,GAAM,cAAc,SAAqC,CAAC,EAAA,CAC3D,QAAQ,MAAcK,EAAU,mBAAmBF,CAAc,GAC7DG,IAAsBF,EAAuB,MAAMR,GAAQA,IAASD,CAAK;CAE/E,OAAO;EACL,YAAYW;EACZ,OAAOF,EAAuB;EAC9B,SAASR,IAASU,EAAoB,SAASF,EAAuB;EACtE;EACA;EACA;EACA;CACF;AACF;AAKA,SAAgBG,IAAqB;CACnC,IAAM,CAACC,GAAiB,EAAE,SAAM,YAAS,cAAWC,EAA2B,EAC7E,gBAAgB,CAACC,CAAqB,EACxC,CAAC;CAED,OAAO;EACL,kBAAkB,MAAgCF,EAAgB,EAAE,WAAW,EAAE,SAAM,EAAE,CAAC;EAC1F;EACA;EACA;CACF;AACF;AAKA,SAAgBG,IAAqB;CACnC,IAAM,CAACC,GAAiB,EAAE,SAAM,YAAS,cAAWC,EAA2B;CAE/E,OAAO;EACL,kBAAkB,GAAY,MAC5BD,EAAgB,EAAE,WAAW;GAAE;GAAI;EAAM,EAAE,CAAC;EAC9C;EACA;EACA;CACF;AACF;AAMA,SAAgBE,IAAqB;CACnC,IAAM,CAACC,GAAiB,EAAE,SAAM,YAAS,cAAWC,EAA4B,EAC9E,gBAAgB,CAACN,CAAqB,EACxC,CAAC;CAED,OAAO;EACL,kBAAkB,MAAeK,EAAgB,EAAE,WAAW,EAAE,MAAG,EAAE,CAAC;EACtE;EACA;EACA;CACF;AACF;AAiBA,SAAgBE,EAAW,IAAgB,KAAK,IAAiB,GAAG,IAAmB,IAAM;CAC3F,IAAM,EAAE,SAAM,YAAS,UAAO,eAAYC,EAAmB;EAC3D,WAAW;GAAE;GAAO;EAAO;EAC3B,MAAM,CAACC;EACP,aAAa;EACb,iBAAiB;CACnB,CAAC;CAED,OAAO;EACL,SAAUnB,GAAM,WAAW,SAAsB,CAAC;EAClD,OAAOA,GAAM,WAAW,SAAS;EACjC;EACA;EACA;CACF;AACF"}
@@ -1,35 +1,35 @@
1
- import { useOrgConsole as e } from "../../../providers/OrgConsoleProvider.js";
2
- import { toast as t } from "../../../../node_modules/sonner/dist/index.js";
3
- import { useOrganization as n } from "../../organizations/hooks/useOrganizations.js";
4
- import { useTr as r } from "../../../shared/hooks/useTr.js";
5
- import { LoadingState as i } from "../../../shared/components/feedback/LoadingState.js";
6
- import { useCreateWorkspace as a } from "../hooks/useWorkspaces.js";
7
- import { WorkspaceForm as o } from "../components/WorkspaceForm.js";
1
+ import { toast as e } from "../../../../node_modules/sonner/dist/index.js";
2
+ import { useOrgConsole as t } from "../../../providers/OrgConsoleProvider.js";
3
+ import { useCreateWorkspace as n } from "../hooks/useWorkspaces.js";
4
+ import { useOrganization as r } from "../../organizations/hooks/useOrganizations.js";
5
+ import { WorkspaceForm as i } from "../components/WorkspaceForm.js";
6
+ import { LoadingState as a } from "../../../shared/components/feedback/LoadingState.js";
7
+ import { useTr as o } from "../../../shared/hooks/useTr.js";
8
8
  import { ArrowLeft as s } from "lucide-react";
9
9
  import { GlassCard as c, PagePurpose as l } from "@burdenoff/fe-libs/ui";
10
10
  import { usePermissions as u } from "@burdenoff/fe-libs/shared/providers/shell";
11
11
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
12
12
  import { useSearchParams as p } from "react-router";
13
- //#region src/organization-management/modules/workspaces/pages/WorkspaceCreatePage.tsx
13
+ // src/organization-management/modules/workspaces/pages/WorkspaceCreatePage.tsx
14
14
  function m() {
15
- let m = r(), { navigate: h, basePath: g = "/organizations" } = e(), { isLoading: _ } = u(), { createWorkspace: v, loading: y } = a(), [b] = p(), x = b.get("organizationId") || void 0, { organization: S } = n(x || ""), C = async (e) => {
15
+ let m = o(), { navigate: h, basePath: g = "/organizations" } = t(), { isLoading: _ } = u(), { createWorkspace: v, loading: y } = n(), [b] = p(), x = b.get("organizationId") || void 0, { organization: S } = r(x || ""), C = async (t) => {
16
16
  try {
17
- let n = await v(e);
18
- if (n.data?.createWorkspace) t.success(m("workspaces.create.success", "Workspace created successfully")), h(x ? `${g}/${x}` : `${g}/workspaces/${n.data.createWorkspace.id}`);
17
+ let n = await v(t);
18
+ if (n.data?.createWorkspace) e.success(m("workspaces.create.success", "Workspace created successfully")), h(x ? `${g}/${x}` : `${g}/workspaces/${n.data.createWorkspace.id}`);
19
19
  else if (n.errors && n.errors.length > 0) {
20
- let e = n.errors[0]?.message || m("workspaces.create.failed", "Failed to create workspace");
21
- n.errors[0]?.extensions?.code === "UNAUTHENTICATED" ? t.error(m("common.authRequired", "Authentication required. Please log in again.")) : t.error(e);
20
+ let t = n.errors[0]?.message || m("workspaces.create.failed", "Failed to create workspace");
21
+ n.errors[0]?.extensions?.code === "UNAUTHENTICATED" ? e.error(m("common.authRequired", "Authentication required. Please log in again.")) : e.error(t);
22
22
  }
23
- } catch (e) {
24
- let n = e instanceof Error ? e.message : m("common.unexpectedError", "An unexpected error occurred");
25
- t.error(n);
23
+ } catch (t) {
24
+ let n = t instanceof Error ? t.message : m("common.unexpectedError", "An unexpected error occurred");
25
+ e.error(n);
26
26
  }
27
27
  }, w = () => {
28
28
  h(x ? `${g}/${x}` : `${g}/workspaces`);
29
29
  };
30
30
  return _ ? /* @__PURE__ */ d("div", {
31
31
  className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
32
- children: /* @__PURE__ */ d(i, { message: m("common.loadingPermissions", "Loading permissions...") })
32
+ children: /* @__PURE__ */ d(a, { message: m("common.loadingPermissions", "Loading permissions...") })
33
33
  }) : /* @__PURE__ */ f("div", {
34
34
  className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-200",
35
35
  children: [/* @__PURE__ */ f("div", {
@@ -63,7 +63,7 @@ function m() {
63
63
  treatment: "glass",
64
64
  glow: !0,
65
65
  className: "border-border-seam p-6",
66
- children: /* @__PURE__ */ d(o, {
66
+ children: /* @__PURE__ */ d(i, {
67
67
  tenantId: S?.tenantId,
68
68
  tenantName: S?.tenantId,
69
69
  organizationId: x,
@@ -77,7 +77,6 @@ function m() {
77
77
  })]
78
78
  });
79
79
  }
80
- //#endregion
81
80
  export { m as WorkspaceCreatePage };
82
81
 
83
82
  //# sourceMappingURL=WorkspaceCreatePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceCreatePage.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/pages/WorkspaceCreatePage.tsx"],"sourcesContent":["import { ArrowLeft } from 'lucide-react';\nimport { useSearchParams } from 'react-router';\nimport { toast } from 'sonner';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useCreateWorkspace } from '../hooks/useWorkspaces';\nimport { useOrganization } from '../../organizations/hooks/useOrganizations';\nimport { WorkspaceForm } from '../components/WorkspaceForm';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport type { CreateWorkspaceInput, UpdateWorkspaceInput } from '../types';\n\nexport function WorkspaceCreatePage() {\n const tr = useTr();\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n // `usePermissions` is still used for the permissionsLoading gate below\n // even though the static workspace:create page-level guard was removed\n // (see comment further down) — keep the hook call so the loading\n // skeleton still waits for the provider to settle before mounting the\n // form.\n const { isLoading: permissionsLoading } = usePermissions();\n const { createWorkspace, loading } = useCreateWorkspace();\n const [searchParams] = useSearchParams();\n\n // Get organizationId from URL query params (e.g., ?organizationId=xxx)\n const organizationIdFromUrl = searchParams.get('organizationId') || undefined;\n\n // Fetch organization details if ID is provided (to show org name and get tenantId)\n const { organization } = useOrganization(organizationIdFromUrl || '');\n\n const handleSubmit = async (data: CreateWorkspaceInput | UpdateWorkspaceInput) => {\n try {\n const createData = data as CreateWorkspaceInput;\n const result = await createWorkspace(createData);\n if (result.data?.createWorkspace) {\n toast.success(tr('workspaces.create.success', 'Workspace created successfully'));\n if (organizationIdFromUrl) {\n navigate(`${basePath}/${organizationIdFromUrl}`);\n } else {\n navigate(`${basePath}/workspaces/${result.data.createWorkspace.id}`);\n }\n } else if (result.errors && result.errors.length > 0) {\n // Handle GraphQL errors returned in result\n const errorMessage =\n result.errors[0]?.message || tr('workspaces.create.failed', 'Failed to create workspace');\n const errorCode = result.errors[0]?.extensions?.code;\n\n if (errorCode === 'UNAUTHENTICATED') {\n toast.error(tr('common.authRequired', 'Authentication required. Please log in again.'));\n } else {\n toast.error(errorMessage);\n }\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? error.message\n : tr('common.unexpectedError', 'An unexpected error occurred');\n toast.error(errorMessage);\n }\n };\n\n const handleCancel = () => {\n // Navigate back to organization if came from there, otherwise to workspaces list\n if (organizationIdFromUrl) {\n navigate(`${basePath}/${organizationIdFromUrl}`);\n } else {\n navigate(`${basePath}/workspaces`);\n }\n };\n\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 // NOTE: deliberately NOT gating on hasPermission(WORKSPACE_CREATE) at the\n // page level. `usePermissions()` here resolves at the outer tenant scope\n // (from OrgConsoleProvider), and `workspace:create` is an org-scope\n // permission — a user who is Owner of even one org would be incorrectly\n // denied entry to the form. WorkspaceForm's organization dropdown is\n // permission-filtered (only orgs where the user actually has\n // workspace:create are listed), and the backend @rbac directive on the\n // createWorkspace mutation is the authoritative enforcement point. If a\n // user has no orgs they can create a workspace in, the dropdown will\n // surface that message and submit will stay disabled.\n\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-200\">\n <div className=\"mb-6\">\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"\n inline-flex items-center gap-2 mb-4\n text-[var(--color-text-secondary)]\n hover:text-[var(--color-text-primary)]\n \n transition-all duration-200\n \"\n >\n <ArrowLeft size={20} />\n <span className=\"text-sm font-medium\">\n {organizationIdFromUrl\n ? `${tr('common.backTo', 'Back to')} ${organization?.name || tr('common.organization', 'Organization')}`\n : tr('workspaces.create.backToWorkspaces', 'Back to Workspaces')}\n </span>\n </button>\n\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)] mb-2\">\n {tr('workspaces.create.title', 'Create Workspace')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {organizationIdFromUrl && organization\n ? `${tr('workspaces.create.subtitleForOrg', 'Add a new workspace to')} ${organization.name}`\n : tr('workspaces.create.subtitle', 'Add a new workspace to an organization')}\n </p>\n <PagePurpose className=\"mt-2 max-w-2xl\">\n {tr(\n 'workspaces.create.purpose',\n 'A workspace gives a team or project its own dedicated space inside an organization. Create one to group the right people and their work — once it exists you can add members and start collaborating.'\n )}\n </PagePurpose>\n </div>\n\n <div className=\"max-w-2xl\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-6\">\n <WorkspaceForm\n tenantId={organization?.tenantId}\n tenantName={organization?.tenantId}\n organizationId={organizationIdFromUrl}\n organizationName={organization?.name}\n showOrganizationSelector={!organizationIdFromUrl}\n onSubmit={handleSubmit}\n onCancel={handleCancel}\n loading={loading}\n />\n </GlassCard>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,SAAgB,IAAsB;CACpC,IAAM,IAAK,GAAO,EACZ,EAAE,aAAU,cAAW,qBAAqB,GAAe,EAM3D,EAAE,WAAW,MAAuB,GAAgB,EACpD,EAAE,oBAAiB,eAAY,GAAoB,EACnD,CAAC,KAAgB,GAAiB,EAGlC,IAAwB,EAAa,IAAI,iBAAiB,IAAI,KAAA,GAG9D,EAAE,oBAAiB,EAAgB,KAAyB,GAAG,EAE/D,IAAe,OAAO,MAAsD;AAChF,MAAI;GAEF,IAAM,IAAS,MAAM,EADF,EAC6B;AAChD,OAAI,EAAO,MAAM,gBAEf,CADA,EAAM,QAAQ,EAAG,6BAA6B,iCAAiC,CAAC,EAE9E,EADE,IACO,GAAG,EAAS,GAAG,MAEf,GAAG,EAAS,cAAc,EAAO,KAAK,gBAAgB,KAAK;YAE7D,EAAO,UAAU,EAAO,OAAO,SAAS,GAAG;IAEpD,IAAM,IACJ,EAAO,OAAO,IAAI,WAAW,EAAG,4BAA4B,6BAA6B;AAG3F,IAFkB,EAAO,OAAO,IAAI,YAAY,SAE9B,oBAChB,EAAM,MAAM,EAAG,uBAAuB,gDAAgD,CAAC,GAEvF,EAAM,MAAM,EAAa;;WAGtB,GAAO;GACd,IAAM,IACJ,aAAiB,QACb,EAAM,UACN,EAAG,0BAA0B,+BAA+B;AAClE,KAAM,MAAM,EAAa;;IAIvB,UAAqB;AAEzB,EACE,EADE,IACO,GAAG,EAAS,GAAG,MAEf,GAAG,EAAS,aAAa;;AAuBtC,QAnBI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAc,SAAS,EAAG,6BAA6B,yBAAyB,EAAI,CAAA;EAChF,CAAA,GAgBR,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAHZ,CAWE,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA,EACvB,kBAAC,QAAD;MAAM,WAAU;gBACb,IACG,GAAG,EAAG,iBAAiB,UAAU,CAAC,GAAG,GAAc,QAAQ,EAAG,uBAAuB,eAAe,KACpG,EAAG,sCAAsC,qBAAqB;MAC7D,CAAA,CACA;;IAET,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,2BAA2B,mBAAmB;KAC/C,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eACV,KAAyB,IACtB,GAAG,EAAG,oCAAoC,yBAAyB,CAAC,GAAG,EAAa,SACpF,EAAG,8BAA8B,yCAAyC;KAC5E,CAAA;IACJ,kBAAC,GAAD;KAAa,WAAU;eACpB,EACC,6BACA,wMACD;KACW,CAAA;IACV;MAEN,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD;IAAW,WAAU;IAAQ,MAAA;IAAK,WAAU;cAC1C,kBAAC,GAAD;KACE,UAAU,GAAc;KACxB,YAAY,GAAc;KAC1B,gBAAgB;KAChB,kBAAkB,GAAc;KAChC,0BAA0B,CAAC;KAC3B,UAAU;KACV,UAAU;KACD;KACT,CAAA;IACQ,CAAA;GACR,CAAA,CACF"}
1
+ {"version":3,"file":"WorkspaceCreatePage.js","names":["createData","WorkspaceCreatePage","tr","useTr","useOrgConsole","permissionsLoading","usePermissions","useCreateWorkspace","searchParams","useSearchParams","organizationIdFromUrl","useOrganization","handleSubmit","result","createWorkspace","data","toast","navigate","basePath","errorMessage","error","handleCancel","LoadingState","ArrowLeft","organization","PagePurpose","GlassCard","WorkspaceForm"],"sources":["../../../../../src/organization-management/modules/workspaces/pages/WorkspaceCreatePage.tsx"],"sourcesContent":["import { ArrowLeft } from 'lucide-react';\nimport { useSearchParams } from 'react-router';\nimport { toast } from 'sonner';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useCreateWorkspace } from '../hooks/useWorkspaces';\nimport { useOrganization } from '../../organizations/hooks/useOrganizations';\nimport { WorkspaceForm } from '../components/WorkspaceForm';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport type { CreateWorkspaceInput, UpdateWorkspaceInput } from '../types';\n\nexport function WorkspaceCreatePage() {\n const tr = useTr();\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n // `usePermissions` is still used for the permissionsLoading gate below\n // even though the static workspace:create page-level guard was removed\n // (see comment further down) — keep the hook call so the loading\n // skeleton still waits for the provider to settle before mounting the\n // form.\n const { isLoading: permissionsLoading } = usePermissions();\n const { createWorkspace, loading } = useCreateWorkspace();\n const [searchParams] = useSearchParams();\n\n // Get organizationId from URL query params (e.g., ?organizationId=xxx)\n const organizationIdFromUrl = searchParams.get('organizationId') || undefined;\n\n // Fetch organization details if ID is provided (to show org name and get tenantId)\n const { organization } = useOrganization(organizationIdFromUrl || '');\n\n const handleSubmit = async (data: CreateWorkspaceInput | UpdateWorkspaceInput) => {\n try {\n const createData = data as CreateWorkspaceInput;\n const result = await createWorkspace(createData);\n if (result.data?.createWorkspace) {\n toast.success(tr('workspaces.create.success', 'Workspace created successfully'));\n if (organizationIdFromUrl) {\n navigate(`${basePath}/${organizationIdFromUrl}`);\n } else {\n navigate(`${basePath}/workspaces/${result.data.createWorkspace.id}`);\n }\n } else if (result.errors && result.errors.length > 0) {\n // Handle GraphQL errors returned in result\n const errorMessage =\n result.errors[0]?.message || tr('workspaces.create.failed', 'Failed to create workspace');\n const errorCode = result.errors[0]?.extensions?.code;\n\n if (errorCode === 'UNAUTHENTICATED') {\n toast.error(tr('common.authRequired', 'Authentication required. Please log in again.'));\n } else {\n toast.error(errorMessage);\n }\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? error.message\n : tr('common.unexpectedError', 'An unexpected error occurred');\n toast.error(errorMessage);\n }\n };\n\n const handleCancel = () => {\n // Navigate back to organization if came from there, otherwise to workspaces list\n if (organizationIdFromUrl) {\n navigate(`${basePath}/${organizationIdFromUrl}`);\n } else {\n navigate(`${basePath}/workspaces`);\n }\n };\n\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 // NOTE: deliberately NOT gating on hasPermission(WORKSPACE_CREATE) at the\n // page level. `usePermissions()` here resolves at the outer tenant scope\n // (from OrgConsoleProvider), and `workspace:create` is an org-scope\n // permission — a user who is Owner of even one org would be incorrectly\n // denied entry to the form. WorkspaceForm's organization dropdown is\n // permission-filtered (only orgs where the user actually has\n // workspace:create are listed), and the backend @rbac directive on the\n // createWorkspace mutation is the authoritative enforcement point. If a\n // user has no orgs they can create a workspace in, the dropdown will\n // surface that message and submit will stay disabled.\n\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-200\">\n <div className=\"mb-6\">\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"\n inline-flex items-center gap-2 mb-4\n text-[var(--color-text-secondary)]\n hover:text-[var(--color-text-primary)]\n \n transition-all duration-200\n \"\n >\n <ArrowLeft size={20} />\n <span className=\"text-sm font-medium\">\n {organizationIdFromUrl\n ? `${tr('common.backTo', 'Back to')} ${organization?.name || tr('common.organization', 'Organization')}`\n : tr('workspaces.create.backToWorkspaces', 'Back to Workspaces')}\n </span>\n </button>\n\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)] mb-2\">\n {tr('workspaces.create.title', 'Create Workspace')}\n </h1>\n <p className=\"text-[var(--color-text-secondary)]\">\n {organizationIdFromUrl && organization\n ? `${tr('workspaces.create.subtitleForOrg', 'Add a new workspace to')} ${organization.name}`\n : tr('workspaces.create.subtitle', 'Add a new workspace to an organization')}\n </p>\n <PagePurpose className=\"mt-2 max-w-2xl\">\n {tr(\n 'workspaces.create.purpose',\n 'A workspace gives a team or project its own dedicated space inside an organization. Create one to group the right people and their work — once it exists you can add members and start collaborating.'\n )}\n </PagePurpose>\n </div>\n\n <div className=\"max-w-2xl\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-6\">\n <WorkspaceForm\n tenantId={organization?.tenantId}\n tenantName={organization?.tenantId}\n organizationId={organizationIdFromUrl}\n organizationName={organization?.name}\n showOrganizationSelector={!organizationIdFromUrl}\n onSubmit={handleSubmit}\n onCancel={handleCancel}\n loading={loading}\n />\n </GlassCard>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,SAAgBC,IAAsB;CACpC,IAAMC,IAAKC,EAAM,GACX,EAAE,aAAU,cAAW,qBAAqBC,EAAc,GAM1D,EAAE,WAAWC,MAAuBC,EAAe,GACnD,EAAE,oBAAiB,eAAYC,EAAmB,GAClD,CAACC,KAAgBC,EAAgB,GAGjCC,IAAwBF,EAAa,IAAI,gBAAgB,KAAK,KAAA,GAG9D,EAAE,oBAAiBG,EAAgBD,KAAyB,EAAE,GAE9DE,IAAe,OAAO,MAAsD;EAChF,IAAI;GAEF,IAAMC,IAAS,MAAMC,EAAgBd,CAAU;GAC/C,IAAIa,EAAO,MAAM,iBAEf,AADAG,EAAM,QAAQd,EAAG,6BAA6B,gCAAgC,CAAC,GAE7Ee,EADEP,IACO,GAAGQ,EAAS,GAAGR,MAEf,GAAGQ,EAAS,cAAcL,EAAO,KAAK,gBAAgB,IAAI;QAEhE,IAAIA,EAAO,UAAUA,EAAO,OAAO,SAAS,GAAG;IAEpD,IAAMM,IACJN,EAAO,OAAO,EAAE,EAAE,WAAWX,EAAG,4BAA4B,4BAA4B;IAG1F,AAFkBW,EAAO,OAAO,EAAE,EAAE,YAAY,SAE9B,oBAChBG,EAAM,MAAMd,EAAG,uBAAuB,+CAA+C,CAAC,IAEtFc,EAAM,MAAMG,CAAY;GAE5B;EACF,SAASC,GAAO;GACd,IAAMD,IACJC,aAAiB,QACbA,EAAM,UACNlB,EAAG,0BAA0B,8BAA8B;GACjE,EAAM,MAAMiB,CAAY;EAC1B;CACF,GAEME,UAAqB;EAEzB,AACEJ,EADEP,IACO,GAAGQ,EAAS,GAAGR,MAEf,GAAGQ,EAAS,YAAY;CAErC;CAqBA,OAnBIb,IAEA,kBAAC,OAAD;EAAK,WAAU;EACb,UAAA,kBAACiB,GAAD,EAAc,SAASpB,EAAG,6BAA6B,wBAAwB,EAAI,CAAA;CAChF,CAAA,IAgBP,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,kBAAC,UAAD;KACE,MAAK;KACL,SAASmB;KACT,WAAU;KAHZ,UAAA,CAWE,kBAACE,GAAD,EAAW,MAAM,GAAK,CAAA,GACtB,kBAAC,QAAD;MAAM,WAAU;MACb,UAAAb,IACG,GAAGR,EAAG,iBAAiB,SAAS,EAAE,GAAGsB,GAAc,QAAQtB,EAAG,uBAAuB,cAAc,MACnGA,EAAG,sCAAsC,oBAAoB;KAC7D,CAAA,CACA;;IAER,kBAAC,MAAD;KAAI,WAAU;KACX,UAAAA,EAAG,2BAA2B,kBAAkB;IAC/C,CAAA;IACJ,kBAAC,KAAD;KAAG,WAAU;KACV,UAAAQ,KAAyBc,IACtB,GAAGtB,EAAG,oCAAoC,wBAAwB,EAAE,GAAGsB,EAAa,SACpFtB,EAAG,8BAA8B,wCAAwC;IAC5E,CAAA;IACH,kBAACuB,GAAD;KAAa,WAAU;KACpB,UAAAvB,EACC,6BACA,uMACF;IACW,CAAA;GACV;EAEL,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAU;GACb,UAAA,kBAACwB,GAAD;IAAW,WAAU;IAAQ,MAAA;IAAK,WAAU;IAC1C,UAAA,kBAACC,GAAD;KACE,UAAUH,GAAc;KACxB,YAAYA,GAAc;KAC1B,gBAAgBd;KAChB,kBAAkBc,GAAc;KAChC,0BAA0B,CAACd;KAC3B,UAAUE;KACV,UAAUS;KACD;IACV,CAAA;GACQ,CAAA;EACR,CAAA,CACF;;AAET"}
@@ -1,15 +1,15 @@
1
- import { useOrgConsole as e } from "../../../providers/OrgConsoleProvider.js";
2
- import { toast as t } from "../../../../node_modules/sonner/dist/index.js";
3
- import { useTr as n } from "../../../shared/hooks/useTr.js";
4
- import { LoadingState as r } from "../../../shared/components/feedback/LoadingState.js";
5
- import { ErrorState as i } from "../../../shared/components/feedback/ErrorState.js";
6
- import { useConfirmDialog as a } from "../../../shared/components/dialog/ConfirmDialog.js";
7
- import { PERMISSIONS as o } from "../../../constants/permissions.js";
8
- import { MemberRoleBadge as s } from "../../members/components/MemberRoleBadge.js";
9
- import { useWorkspace as ee } from "../hooks/useWorkspaces.js";
10
- import { WorkspaceStatusBadge as c } from "../components/WorkspaceStatusBadge.js";
11
- import { useRemoveWorkspaceMember as l, useWorkspaceMembers as u } from "../hooks/useWorkspaceMembers.js";
12
- import { AddWorkspaceMemberDialog as d } from "../components/AddWorkspaceMemberDialog.js";
1
+ import { toast as e } from "../../../../node_modules/sonner/dist/index.js";
2
+ import { useOrgConsole as t } from "../../../providers/OrgConsoleProvider.js";
3
+ import { useWorkspace as n } from "../hooks/useWorkspaces.js";
4
+ import { useRemoveWorkspaceMember as r, useWorkspaceMembers as i } from "../hooks/useWorkspaceMembers.js";
5
+ import { WorkspaceStatusBadge as a } from "../components/WorkspaceStatusBadge.js";
6
+ import { LoadingState as o } from "../../../shared/components/feedback/LoadingState.js";
7
+ import { ErrorState as s } from "../../../shared/components/feedback/ErrorState.js";
8
+ import { MemberRoleBadge as ee } from "../../members/components/MemberRoleBadge.js";
9
+ import { AddWorkspaceMemberDialog as c } from "../components/AddWorkspaceMemberDialog.js";
10
+ import { useConfirmDialog as l } from "../../../shared/components/dialog/ConfirmDialog.js";
11
+ import { PERMISSIONS as u } from "../../../constants/permissions.js";
12
+ import { useTr as d } from "../../../shared/hooks/useTr.js";
13
13
  import { useMemo as f, useState as p } from "react";
14
14
  import { ArrowLeft as m, Briefcase as h, Edit as g, Trash2 as _, UserPlus as v, Users as y } from "lucide-react";
15
15
  import { CTAOverflowMenu as b, EmphasisPanel as x, GlassCard as S, IllustratedEmptyState as C, NextSteps as w, PagePurpose as T, ResponsiveTable as E } from "@burdenoff/fe-libs/ui";
@@ -17,7 +17,7 @@ import { usePermissions as te } from "@burdenoff/fe-libs/shared/providers/shell"
17
17
  import { jsx as D, jsxs as O } from "react/jsx-runtime";
18
18
  import { useParams as ne } from "react-router";
19
19
  import { ActorIdentity as re, buildActorFallback as k, useActorProfiles as A } from "@burdenoff/fe-libs/shared";
20
- //#region src/organization-management/modules/workspaces/pages/WorkspaceDetailPage.tsx
20
+ // src/organization-management/modules/workspaces/pages/WorkspaceDetailPage.tsx
21
21
  function j(e) {
22
22
  return new Date(e).toLocaleDateString("en-US", {
23
23
  year: "numeric",
@@ -28,45 +28,45 @@ function j(e) {
28
28
  });
29
29
  }
30
30
  function M() {
31
- let M = n(), { id: N } = ne(), { navigate: P, basePath: F = "/organizations", apiGatewayUrl: I, authToken: L } = e(), { hasPermission: R, isLoading: z } = te(), { workspace: B, loading: V, error: H } = ee(N ?? ""), [U, W] = p("overview"), [G, K] = p(!1), { openConfirmDialog: q, ConfirmDialog: J } = a(), { members: Y, loading: X, error: Z, refetch: Q } = u(U === "members" && N ? N ?? "" : "", 50, 0), { removeWorkspaceMember: ie, loading: ae } = l(), $ = Y.length > 0 || U === "members" ? Y.length : B?.memberCount ?? 0, oe = A(f(() => Y.map((e) => ({
31
+ let M = d(), { id: N } = ne(), { navigate: P, basePath: F = "/organizations", apiGatewayUrl: I, authToken: L } = t(), { hasPermission: R, isLoading: z } = te(), { workspace: B, loading: V, error: H } = n(N ?? ""), [U, W] = p("overview"), [G, K] = p(!1), { openConfirmDialog: q, ConfirmDialog: J } = l(), { members: Y, loading: X, error: Z, refetch: Q } = i(U === "members" && N ? N ?? "" : "", 50, 0), { removeWorkspaceMember: ie, loading: ae } = r(), $ = Y.length > 0 || U === "members" ? Y.length : B?.memberCount ?? 0, oe = f(() => Y.map((e) => ({
32
32
  actorId: e.userId,
33
33
  actorType: "user"
34
- })), [Y]), {
34
+ })), [Y]), se = A(oe, {
35
35
  apiGatewayUrl: I,
36
36
  authToken: L,
37
37
  orgId: B?.organizationId,
38
38
  workspaceId: N
39
- }), se = f(() => [{
39
+ }), ce = f(() => [{
40
40
  id: "overview",
41
41
  label: M("workspaces.detail.tab.overview", "Overview")
42
42
  }, {
43
43
  id: "members",
44
44
  label: `${M("workspaces.detail.tab.members", "Members")} (${$})`
45
- }], [$, M]), ce = (e) => {
45
+ }], [$, M]), le = (t) => {
46
46
  N && q({
47
47
  title: M("workspaces.removeMember.title", "Remove workspace member"),
48
- description: `${M("workspaces.removeMember.prefix", "Remove")} ${e} ${M("workspaces.removeMember.suffix", "from this workspace? They will keep their organization membership.")}`,
48
+ description: `${M("workspaces.removeMember.prefix", "Remove")} ${t} ${M("workspaces.removeMember.suffix", "from this workspace? They will keep their organization membership.")}`,
49
49
  confirmText: M("common.remove", "Remove"),
50
50
  variant: "danger",
51
51
  onConfirm: () => {
52
52
  (async () => {
53
53
  try {
54
- let n = await ie(N, e);
54
+ let n = await ie(N, t);
55
55
  if (n.errors?.length) throw Error(n.errors[0]?.message ?? M("workspaces.removeMember.failed", "Failed to remove workspace member"));
56
- await Q(), t.success(M("workspaces.removeMember.success", "Workspace member removed successfully"));
57
- } catch (e) {
58
- t.error(e instanceof Error ? e.message : M("workspaces.removeMember.failed", "Failed to remove workspace member"));
56
+ await Q(), e.success(M("workspaces.removeMember.success", "Workspace member removed successfully"));
57
+ } catch (t) {
58
+ e.error(t instanceof Error ? t.message : M("workspaces.removeMember.failed", "Failed to remove workspace member"));
59
59
  }
60
60
  })();
61
61
  }
62
62
  });
63
- }, le = [
63
+ }, ue = [
64
64
  {
65
65
  key: "user",
66
66
  header: M("members.detail.userId", "User ID"),
67
67
  priority: "primary",
68
68
  cell: (e) => /* @__PURE__ */ D(re, {
69
- profile: oe[e.userId] ?? k({
69
+ profile: se[e.userId] ?? k({
70
70
  actorId: e.userId,
71
71
  actorType: "user"
72
72
  }),
@@ -77,7 +77,7 @@ function M() {
77
77
  key: "role",
78
78
  header: M("members.list.column.role", "Role"),
79
79
  priority: "secondary",
80
- cell: (e) => /* @__PURE__ */ D(s, { role: e.role })
80
+ cell: (e) => /* @__PURE__ */ D(ee, { role: e.role })
81
81
  },
82
82
  {
83
83
  key: "joined",
@@ -97,9 +97,9 @@ function M() {
97
97
  children: e.invitedBy || "—"
98
98
  })
99
99
  }
100
- ], ue = (e) => /* @__PURE__ */ D("button", {
100
+ ], de = (e) => /* @__PURE__ */ D("button", {
101
101
  type: "button",
102
- onClick: () => ce(e.userId),
102
+ onClick: () => le(e.userId),
103
103
  disabled: ae,
104
104
  className: "rounded-lg p-2 text-[var(--color-status-error-text)] transition-all duration-200 hover:bg-[var(--color-status-error-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50",
105
105
  "aria-label": `${M("workspaces.removeMember.ariaPrefix", "Remove")} ${e.userId} ${M("workspaces.removeMember.ariaSuffix", "from workspace")}`,
@@ -111,13 +111,13 @@ function M() {
111
111
  });
112
112
  return z ? /* @__PURE__ */ D("div", {
113
113
  className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
114
- children: /* @__PURE__ */ D(r, { message: M("common.loadingPermissions", "Loading permissions...") })
115
- }) : R(o.WORKSPACE_READ) ? V ? /* @__PURE__ */ D("div", {
114
+ children: /* @__PURE__ */ D(o, { message: M("common.loadingPermissions", "Loading permissions...") })
115
+ }) : R(u.WORKSPACE_READ) ? V ? /* @__PURE__ */ D("div", {
116
116
  className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6",
117
- children: /* @__PURE__ */ D(r, { message: M("workspaces.detail.loading", "Loading workspace details...") })
117
+ children: /* @__PURE__ */ D(o, { message: M("workspaces.detail.loading", "Loading workspace details...") })
118
118
  }) : H || !B ? /* @__PURE__ */ D("div", {
119
119
  className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6",
120
- children: /* @__PURE__ */ D(i, {
120
+ children: /* @__PURE__ */ D(s, {
121
121
  message: H?.message || M("workspaces.detail.notFound", "Workspace not found"),
122
122
  action: {
123
123
  label: M("workspaces.create.backToWorkspaces", "Back to Workspaces"),
@@ -161,7 +161,7 @@ function M() {
161
161
  children: [/* @__PURE__ */ D("h1", {
162
162
  className: "text-3xl font-bold text-[var(--color-text-primary)]",
163
163
  children: B.name
164
- }), /* @__PURE__ */ D(c, { status: B.status })]
164
+ }), /* @__PURE__ */ D(a, { status: B.status })]
165
165
  }),
166
166
  /* @__PURE__ */ O("p", {
167
167
  className: "break-all font-mono text-sm text-[var(--color-text-secondary)]",
@@ -174,7 +174,7 @@ function M() {
174
174
  ]
175
175
  })]
176
176
  }), /* @__PURE__ */ D(b, {
177
- primary: R(o.WORKSPACE_UPDATE) ? {
177
+ primary: R(u.WORKSPACE_UPDATE) ? {
178
178
  label: M("workspaces.edit.title", "Edit Workspace"),
179
179
  icon: /* @__PURE__ */ D(g, {
180
180
  size: 16,
@@ -196,7 +196,7 @@ function M() {
196
196
  /* @__PURE__ */ D(w, {
197
197
  storageKey: "organization-workspace-detail",
198
198
  steps: [
199
- ...R(o.MEMBER_INVITE) ? [{
199
+ ...R(u.MEMBER_INVITE) ? [{
200
200
  id: "add-member",
201
201
  label: M("workspaces.detail.next.addMember", "Add a member"),
202
202
  description: M("workspaces.detail.next.addMemberDesc", "Bring people from the parent organization into this workspace."),
@@ -218,7 +218,7 @@ function M() {
218
218
  }),
219
219
  onClick: () => W("members")
220
220
  },
221
- ...R(o.WORKSPACE_UPDATE) ? [{
221
+ ...R(u.WORKSPACE_UPDATE) ? [{
222
222
  id: "edit",
223
223
  label: M("workspaces.detail.next.edit", "Edit workspace settings"),
224
224
  description: M("workspaces.detail.next.editDesc", "Update the name, slug, or status of this workspace."),
@@ -247,7 +247,7 @@ function M() {
247
247
  className: "overflow-x-auto border-b border-[var(--color-border-seam)]",
248
248
  children: /* @__PURE__ */ D("div", {
249
249
  className: "flex min-w-max gap-2 px-4 pt-4 sm:px-6",
250
- children: se.map((e) => {
250
+ children: ce.map((e) => {
251
251
  let t = U === e.id;
252
252
  return /* @__PURE__ */ D("button", {
253
253
  type: "button",
@@ -290,7 +290,7 @@ function M() {
290
290
  children: M("common.status", "Status")
291
291
  }), /* @__PURE__ */ D("dd", {
292
292
  className: "mt-1",
293
- children: /* @__PURE__ */ D(c, { status: B.status })
293
+ children: /* @__PURE__ */ D(a, { status: B.status })
294
294
  })] }),
295
295
  /* @__PURE__ */ O("div", {
296
296
  className: "sm:col-span-2",
@@ -364,7 +364,7 @@ function M() {
364
364
  }), /* @__PURE__ */ D("p", {
365
365
  className: "text-sm text-[var(--color-text-secondary)]",
366
366
  children: M("workspaces.detail.membersSubtitle", "Add organization members to this workspace and manage access.")
367
- })] }), R(o.MEMBER_INVITE) && /* @__PURE__ */ O("button", {
367
+ })] }), R(u.MEMBER_INVITE) && /* @__PURE__ */ O("button", {
368
368
  type: "button",
369
369
  onClick: () => K(!0),
370
370
  className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2.5 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90",
@@ -375,8 +375,8 @@ function M() {
375
375
  })]
376
376
  }), X ? /* @__PURE__ */ D("div", {
377
377
  className: "py-8",
378
- children: /* @__PURE__ */ D(r, { message: M("workspaces.detail.loadingMembers", "Loading workspace members...") })
379
- }) : Z ? /* @__PURE__ */ D(i, {
378
+ children: /* @__PURE__ */ D(o, { message: M("workspaces.detail.loadingMembers", "Loading workspace members...") })
379
+ }) : Z ? /* @__PURE__ */ D(s, {
380
380
  message: Z.message,
381
381
  action: {
382
382
  label: M("common.retry", "Retry"),
@@ -387,10 +387,10 @@ function M() {
387
387
  }) : Y.length > 0 ? /* @__PURE__ */ D("div", {
388
388
  className: "overflow-hidden rounded-xl border border-[var(--color-border-seam)] bg-[var(--color-bg-canvas)] md:p-2",
389
389
  children: /* @__PURE__ */ D(E, {
390
- columns: le,
390
+ columns: ue,
391
391
  data: Y,
392
392
  rowKey: (e) => e.id,
393
- rowActions: ue
393
+ rowActions: de
394
394
  })
395
395
  }) : /* @__PURE__ */ D("div", {
396
396
  className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-6",
@@ -411,7 +411,7 @@ function M() {
411
411
  })
412
412
  ]
413
413
  }),
414
- /* @__PURE__ */ D(d, {
414
+ /* @__PURE__ */ D(c, {
415
415
  open: G,
416
416
  onOpenChange: K,
417
417
  workspaceId: B.id,
@@ -429,7 +429,6 @@ function M() {
429
429
  })
430
430
  });
431
431
  }
432
- //#endregion
433
432
  export { M as WorkspaceDetailPage };
434
433
 
435
434
  //# sourceMappingURL=WorkspaceDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceDetailPage.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/pages/WorkspaceDetailPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams } from 'react-router';\nimport { ArrowLeft, Briefcase, Edit, Trash2, UserPlus, Users } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n ActorIdentity,\n buildActorFallback,\n useActorProfiles,\n type ActorInput,\n} from '@burdenoff/fe-libs/shared';\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n GlassCard,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport type { WorkspaceMember } from '../types/workspace-member';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useWorkspace } from '../hooks/useWorkspaces';\nimport { useRemoveWorkspaceMember, useWorkspaceMembers } from '../hooks/useWorkspaceMembers';\nimport { WorkspaceStatusBadge } from '../components/WorkspaceStatusBadge';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { MemberRoleBadge } from '../../members/components/MemberRoleBadge';\nimport { AddWorkspaceMemberDialog } from '../components/AddWorkspaceMemberDialog';\nimport { useConfirmDialog } from '../../../shared/components/dialog/ConfirmDialog';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ntype ActiveTab = 'overview' | 'members';\n\nfunction formatDate(dateString: string) {\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function WorkspaceDetailPage() {\n const tr = useTr();\n const { id } = useParams<{ id: string }>();\n const { navigate, basePath = '/organizations', apiGatewayUrl, authToken } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const { workspace, loading, error } = useWorkspace(id ?? '');\n const [activeTab, setActiveTab] = useState<ActiveTab>('overview');\n const [isAddMemberDialogOpen, setIsAddMemberDialogOpen] = useState(false);\n const { openConfirmDialog, ConfirmDialog } = useConfirmDialog();\n\n const shouldFetchMembers = activeTab === 'members' && Boolean(id);\n const {\n members,\n loading: membersLoading,\n error: membersError,\n refetch: refetchMembers,\n } = useWorkspaceMembers(shouldFetchMembers ? (id ?? '') : '', 50, 0);\n const { removeWorkspaceMember, loading: removingMember } = useRemoveWorkspaceMember();\n const resolvedMemberCount =\n members.length > 0 || activeTab === 'members' ? members.length : (workspace?.memberCount ?? 0);\n\n const memberActors = useMemo<ActorInput[]>(\n () => members.map((member) => ({ actorId: member.userId, actorType: 'user' })),\n [members]\n );\n const profileMap = useActorProfiles(memberActors, {\n apiGatewayUrl,\n authToken,\n orgId: workspace?.organizationId,\n workspaceId: id,\n });\n\n const tabItems = useMemo(\n () => [\n { id: 'overview' as const, label: tr('workspaces.detail.tab.overview', 'Overview') },\n {\n id: 'members' as const,\n label: `${tr('workspaces.detail.tab.members', 'Members')} (${resolvedMemberCount})`,\n },\n ],\n [resolvedMemberCount, tr]\n );\n\n const handleRemoveMember = (userId: string) => {\n if (!id) return;\n\n openConfirmDialog({\n title: tr('workspaces.removeMember.title', 'Remove workspace member'),\n description: `${tr('workspaces.removeMember.prefix', 'Remove')} ${userId} ${tr('workspaces.removeMember.suffix', 'from this workspace? They will keep their organization membership.')}`,\n confirmText: tr('common.remove', 'Remove'),\n variant: 'danger',\n onConfirm: () => {\n void (async () => {\n try {\n const result = await removeWorkspaceMember(id, userId);\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr('workspaces.removeMember.failed', 'Failed to remove workspace member')\n );\n }\n\n await refetchMembers();\n toast.success(\n tr('workspaces.removeMember.success', 'Workspace member removed successfully')\n );\n } catch (removeError) {\n toast.error(\n removeError instanceof Error\n ? removeError.message\n : tr('workspaces.removeMember.failed', 'Failed to remove workspace member')\n );\n }\n })();\n },\n });\n };\n\n const memberColumns: ResponsiveTableColumn<WorkspaceMember>[] = [\n {\n key: 'user',\n header: tr('members.detail.userId', 'User ID'),\n priority: 'primary',\n cell: (member) => (\n <ActorIdentity\n profile={\n profileMap[member.userId] ??\n buildActorFallback({ actorId: member.userId, actorType: 'user' })\n }\n variant=\"cell\"\n />\n ),\n },\n {\n key: 'role',\n header: tr('members.list.column.role', 'Role'),\n priority: 'secondary',\n cell: (member) => <MemberRoleBadge role={member.role} />,\n },\n {\n key: 'joined',\n header: tr('members.list.joined', 'Joined'),\n priority: 'secondary',\n cell: (member) => (\n <span className=\"text-sm text-[var(--color-text-secondary)]\">\n {formatDate(member.joinedAt)}\n </span>\n ),\n },\n {\n key: 'invitedBy',\n header: tr('members.list.invitedBy', 'Invited by'),\n priority: 'secondary',\n cell: (member) => (\n <span className=\"break-all font-mono text-sm text-[var(--color-text-secondary)]\">\n {member.invitedBy || '—'}\n </span>\n ),\n },\n ];\n\n const renderMemberActions = (member: WorkspaceMember) => (\n <button\n type=\"button\"\n onClick={() => handleRemoveMember(member.userId)}\n disabled={removingMember}\n className=\"rounded-lg p-2 text-[var(--color-status-error-text)] transition-all duration-200 hover:bg-[var(--color-status-error-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label={`${tr('workspaces.removeMember.ariaPrefix', 'Remove')} ${member.userId} ${tr('workspaces.removeMember.ariaSuffix', 'from workspace')}`}\n title={`${tr('workspaces.removeMember.ariaPrefix', 'Remove')} ${member.userId} ${tr('workspaces.removeMember.ariaSuffix', 'from workspace')}`}\n >\n <Trash2 size={18} aria-hidden=\"true\" />\n </button>\n );\n\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 (!hasPermission(PERMISSIONS.WORKSPACE_READ)) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <div className=\"p-8 text-center text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.detail.noPermission',\n \"You don't have permission to view this workspace.\"\n )}\n </div>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <LoadingState message={tr('workspaces.detail.loading', 'Loading workspace details...')} />\n </div>\n );\n }\n\n if (error || !workspace) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <ErrorState\n message={error?.message || tr('workspaces.detail.notFound', 'Workspace not found')}\n action={{\n label: tr('workspaces.create.backToWorkspaces', 'Back to Workspaces'),\n onClick: () => navigate(`${basePath}/workspaces`),\n }}\n />\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 animate-in fade-in duration-200\">\n <div className=\"mx-auto flex w-full max-w-7xl flex-col gap-6\">\n <div className=\"space-y-4\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces`)}\n className=\"inline-flex min-h-10 items-center gap-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:text-[var(--color-text-primary)]\"\n >\n <ArrowLeft size={20} aria-hidden=\"true\" />\n <span className=\"text-sm font-medium\">\n {tr('workspaces.create.backToWorkspaces', 'Back to Workspaces')}\n </span>\n </button>\n\n <EmphasisPanel className=\"flex flex-col gap-4 p-5 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"flex min-w-0 items-start gap-4\">\n <div className=\"flex size-16 items-center justify-center rounded-xl bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]\">\n <Briefcase size={28} aria-hidden=\"true\" />\n </div>\n\n <div className=\"min-w-0 space-y-2\">\n <div className=\"flex flex-wrap items-start gap-2\">\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {workspace.name}\n </h1>\n <WorkspaceStatusBadge status={workspace.status} />\n </div>\n <p className=\"break-all font-mono text-sm text-[var(--color-text-secondary)]\">\n /{workspace.slug}\n </p>\n <PagePurpose className=\"max-w-2xl\">\n {tr(\n 'workspaces.detail.purpose',\n 'This is one workspace — a focused space where a team collaborates. Review its details here, switch to the Members tab to control who has access, or edit its settings. Use this page to keep the right people in and the workspace healthy.'\n )}\n </PagePurpose>\n </div>\n </div>\n\n <CTAOverflowMenu\n primary={\n hasPermission(PERMISSIONS.WORKSPACE_UPDATE)\n ? {\n label: tr('workspaces.edit.title', 'Edit Workspace'),\n icon: <Edit size={16} aria-hidden=\"true\" />,\n onSelect: () => navigate(`${basePath}/workspaces/${id}/edit`),\n }\n : undefined\n }\n actions={[\n {\n label: tr('workspaces.detail.viewOrganization', 'View Organization'),\n icon: <Users size={16} aria-hidden=\"true\" />,\n onSelect: () => navigate(`${basePath}/${workspace.organizationId}`),\n },\n ]}\n />\n </EmphasisPanel>\n </div>\n\n <NextSteps\n storageKey=\"organization-workspace-detail\"\n steps={[\n ...(hasPermission(PERMISSIONS.MEMBER_INVITE)\n ? [\n {\n id: 'add-member',\n label: tr('workspaces.detail.next.addMember', 'Add a member'),\n description: tr(\n 'workspaces.detail.next.addMemberDesc',\n 'Bring people from the parent organization into this workspace.'\n ),\n icon: <UserPlus size={16} aria-hidden=\"true\" />,\n onClick: () => {\n setActiveTab('members');\n setIsAddMemberDialogOpen(true);\n },\n },\n ]\n : []),\n {\n id: 'review-members',\n label: tr('workspaces.detail.next.reviewMembers', 'Review members & access'),\n description: tr(\n 'workspaces.detail.next.reviewMembersDesc',\n 'See who can access this workspace and their roles.'\n ),\n icon: <Users size={16} aria-hidden=\"true\" />,\n onClick: () => setActiveTab('members'),\n },\n ...(hasPermission(PERMISSIONS.WORKSPACE_UPDATE)\n ? [\n {\n id: 'edit',\n label: tr('workspaces.detail.next.edit', 'Edit workspace settings'),\n description: tr(\n 'workspaces.detail.next.editDesc',\n 'Update the name, slug, or status of this workspace.'\n ),\n icon: <Edit size={16} aria-hidden=\"true\" />,\n onClick: () => navigate(`${basePath}/workspaces/${id}/edit`),\n },\n ]\n : []),\n {\n id: 'view-org',\n label: tr('workspaces.detail.next.viewOrg', 'Open the parent organization'),\n description: tr(\n 'workspaces.detail.next.viewOrgDesc',\n 'Jump to the organization this workspace belongs to.'\n ),\n icon: <Briefcase size={16} aria-hidden=\"true\" />,\n onClick: () => navigate(`${basePath}/${workspace.organizationId}`),\n },\n ]}\n />\n\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-0\">\n <div className=\"overflow-x-auto border-b border-[var(--color-border-seam)]\">\n <div className=\"flex min-w-max gap-2 px-4 pt-4 sm:px-6\">\n {tabItems.map((tabItem) => {\n const isActive = activeTab === tabItem.id;\n return (\n <button\n type=\"button\"\n key={tabItem.id}\n onClick={() => setActiveTab(tabItem.id)}\n className={`inline-flex min-h-11 items-center rounded-t-lg border-b-2 px-4 py-3 text-sm font-medium transition-colors ${\n isActive\n ? 'border-[var(--color-action-primary-bg)] text-[var(--color-action-primary-bg)]'\n : 'border-transparent text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]'\n }`}\n aria-pressed={isActive}\n >\n {tabItem.label}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"p-4 sm:p-6\">\n {activeTab === 'overview' ? (\n <div className=\"grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_320px]\">\n <GlassCard\n treatment=\"plain\"\n className=\"border-border-seam bg-[var(--color-bg-canvas)] p-5\"\n >\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('workspaces.detail.detailsSection', 'Workspace details')}\n </h2>\n\n <dl className=\"mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.name', 'Name')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {workspace.name}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.slug', 'Slug')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {workspace.slug}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.status', 'Status')}\n </dt>\n <dd className=\"mt-1\">\n <WorkspaceStatusBadge status={workspace.status} />\n </dd>\n </div>\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('members.detail.orgId', 'Organization ID')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {workspace.organizationId}\n </dd>\n </div>\n {workspace.endpoint ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('workspaces.detail.endpoint', 'Endpoint')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {workspace.endpoint}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n\n <GlassCard\n treatment=\"plain\"\n className=\"border-border-seam bg-[var(--color-bg-canvas)] p-5 xl:sticky xl:top-6 xl:self-start\"\n >\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('common.metadata', 'Metadata')}\n </h2>\n\n <dl className=\"mt-5 space-y-4\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('workspaces.list.members', 'Members')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {resolvedMemberCount}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(workspace.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.lastUpdated', 'Last updated')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(workspace.updatedAt)}\n </dd>\n </div>\n {workspace.region ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('workspaces.detail.region', 'Region')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {workspace.region}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n </div>\n ) : (\n <section className=\"space-y-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('workspaces.detail.membersTitle', 'Workspace members')}\n </h2>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.detail.membersSubtitle',\n 'Add organization members to this workspace and manage access.'\n )}\n </p>\n </div>\n {hasPermission(PERMISSIONS.MEMBER_INVITE) && (\n <button\n type=\"button\"\n onClick={() => setIsAddMemberDialogOpen(true)}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2.5 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n <UserPlus size={16} aria-hidden=\"true\" />\n <span>{tr('workspaces.detail.addMember', 'Add Member')}</span>\n </button>\n )}\n </div>\n\n {membersLoading ? (\n <div className=\"py-8\">\n <LoadingState\n message={tr(\n 'workspaces.detail.loadingMembers',\n 'Loading workspace members...'\n )}\n />\n </div>\n ) : membersError ? (\n <ErrorState\n message={membersError.message}\n action={{\n label: tr('common.retry', 'Retry'),\n onClick: () => {\n void refetchMembers();\n },\n }}\n />\n ) : members.length > 0 ? (\n <div className=\"overflow-hidden rounded-xl border border-[var(--color-border-seam)] bg-[var(--color-bg-canvas)] md:p-2\">\n <ResponsiveTable\n columns={memberColumns}\n data={members}\n rowKey={(member) => member.id}\n rowActions={renderMemberActions}\n />\n </div>\n ) : (\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-6\">\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={tr('workspaces.detail.emptyMembersTitle', 'No workspace members yet')}\n description={tr(\n 'workspaces.detail.emptyMembersDescription',\n 'Add people from the parent organization to grant workspace access.'\n )}\n action={\n <button\n type=\"button\"\n onClick={() => setIsAddMemberDialogOpen(true)}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:bg-[var(--color-action-primary-bgHover)]\"\n >\n {tr('workspaces.detail.addMember', 'Add Member')}\n </button>\n }\n />\n </div>\n )}\n </section>\n )}\n </div>\n </GlassCard>\n </div>\n\n <AddWorkspaceMemberDialog\n open={isAddMemberDialogOpen}\n onOpenChange={setIsAddMemberDialogOpen}\n workspaceId={workspace.id}\n organizationId={workspace.organizationId}\n existingMembers={members}\n onInviteOrganizationMember={() =>\n navigate(`${basePath}/${workspace.organizationId}/members/invite`)\n }\n />\n {ConfirmDialog}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"WorkspaceDetailPage.js","names":["formatDate","dateString","WorkspaceDetailPage","tr","useTr","useParams","useOrgConsole","permissionsLoading","usePermissions","useWorkspace","id","activeTab","setActiveTab","useState","isAddMemberDialogOpen","setIsAddMemberDialogOpen","useConfirmDialog","membersLoading","membersError","refetchMembers","useWorkspaceMembers","removingMember","useRemoveWorkspaceMember","resolvedMemberCount","members","workspace","memberActors","useMemo","member","profileMap","useActorProfiles","tabItems","handleRemoveMember","openConfirmDialog","userId","result","removeWorkspaceMember","toast","removeError","memberColumns","ActorIdentity","buildActorFallback","MemberRoleBadge","renderMemberActions","Trash2","LoadingState","hasPermission","PERMISSIONS","loading","error","ErrorState","navigate","basePath","ArrowLeft","EmphasisPanel","Briefcase","WorkspaceStatusBadge","PagePurpose","CTAOverflowMenu","Edit","Users","NextSteps","UserPlus","GlassCard","isActive","tabItem","ResponsiveTable","IllustratedEmptyState","AddWorkspaceMemberDialog","ConfirmDialog"],"sources":["../../../../../src/organization-management/modules/workspaces/pages/WorkspaceDetailPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams } from 'react-router';\nimport { ArrowLeft, Briefcase, Edit, Trash2, UserPlus, Users } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n ActorIdentity,\n buildActorFallback,\n useActorProfiles,\n type ActorInput,\n} from '@burdenoff/fe-libs/shared';\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n GlassCard,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport type { WorkspaceMember } from '../types/workspace-member';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useWorkspace } from '../hooks/useWorkspaces';\nimport { useRemoveWorkspaceMember, useWorkspaceMembers } from '../hooks/useWorkspaceMembers';\nimport { WorkspaceStatusBadge } from '../components/WorkspaceStatusBadge';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { MemberRoleBadge } from '../../members/components/MemberRoleBadge';\nimport { AddWorkspaceMemberDialog } from '../components/AddWorkspaceMemberDialog';\nimport { useConfirmDialog } from '../../../shared/components/dialog/ConfirmDialog';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ntype ActiveTab = 'overview' | 'members';\n\nfunction formatDate(dateString: string) {\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function WorkspaceDetailPage() {\n const tr = useTr();\n const { id } = useParams<{ id: string }>();\n const { navigate, basePath = '/organizations', apiGatewayUrl, authToken } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const { workspace, loading, error } = useWorkspace(id ?? '');\n const [activeTab, setActiveTab] = useState<ActiveTab>('overview');\n const [isAddMemberDialogOpen, setIsAddMemberDialogOpen] = useState(false);\n const { openConfirmDialog, ConfirmDialog } = useConfirmDialog();\n\n const shouldFetchMembers = activeTab === 'members' && Boolean(id);\n const {\n members,\n loading: membersLoading,\n error: membersError,\n refetch: refetchMembers,\n } = useWorkspaceMembers(shouldFetchMembers ? (id ?? '') : '', 50, 0);\n const { removeWorkspaceMember, loading: removingMember } = useRemoveWorkspaceMember();\n const resolvedMemberCount =\n members.length > 0 || activeTab === 'members' ? members.length : (workspace?.memberCount ?? 0);\n\n const memberActors = useMemo<ActorInput[]>(\n () => members.map((member) => ({ actorId: member.userId, actorType: 'user' })),\n [members]\n );\n const profileMap = useActorProfiles(memberActors, {\n apiGatewayUrl,\n authToken,\n orgId: workspace?.organizationId,\n workspaceId: id,\n });\n\n const tabItems = useMemo(\n () => [\n { id: 'overview' as const, label: tr('workspaces.detail.tab.overview', 'Overview') },\n {\n id: 'members' as const,\n label: `${tr('workspaces.detail.tab.members', 'Members')} (${resolvedMemberCount})`,\n },\n ],\n [resolvedMemberCount, tr]\n );\n\n const handleRemoveMember = (userId: string) => {\n if (!id) return;\n\n openConfirmDialog({\n title: tr('workspaces.removeMember.title', 'Remove workspace member'),\n description: `${tr('workspaces.removeMember.prefix', 'Remove')} ${userId} ${tr('workspaces.removeMember.suffix', 'from this workspace? They will keep their organization membership.')}`,\n confirmText: tr('common.remove', 'Remove'),\n variant: 'danger',\n onConfirm: () => {\n void (async () => {\n try {\n const result = await removeWorkspaceMember(id, userId);\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr('workspaces.removeMember.failed', 'Failed to remove workspace member')\n );\n }\n\n await refetchMembers();\n toast.success(\n tr('workspaces.removeMember.success', 'Workspace member removed successfully')\n );\n } catch (removeError) {\n toast.error(\n removeError instanceof Error\n ? removeError.message\n : tr('workspaces.removeMember.failed', 'Failed to remove workspace member')\n );\n }\n })();\n },\n });\n };\n\n const memberColumns: ResponsiveTableColumn<WorkspaceMember>[] = [\n {\n key: 'user',\n header: tr('members.detail.userId', 'User ID'),\n priority: 'primary',\n cell: (member) => (\n <ActorIdentity\n profile={\n profileMap[member.userId] ??\n buildActorFallback({ actorId: member.userId, actorType: 'user' })\n }\n variant=\"cell\"\n />\n ),\n },\n {\n key: 'role',\n header: tr('members.list.column.role', 'Role'),\n priority: 'secondary',\n cell: (member) => <MemberRoleBadge role={member.role} />,\n },\n {\n key: 'joined',\n header: tr('members.list.joined', 'Joined'),\n priority: 'secondary',\n cell: (member) => (\n <span className=\"text-sm text-[var(--color-text-secondary)]\">\n {formatDate(member.joinedAt)}\n </span>\n ),\n },\n {\n key: 'invitedBy',\n header: tr('members.list.invitedBy', 'Invited by'),\n priority: 'secondary',\n cell: (member) => (\n <span className=\"break-all font-mono text-sm text-[var(--color-text-secondary)]\">\n {member.invitedBy || '—'}\n </span>\n ),\n },\n ];\n\n const renderMemberActions = (member: WorkspaceMember) => (\n <button\n type=\"button\"\n onClick={() => handleRemoveMember(member.userId)}\n disabled={removingMember}\n className=\"rounded-lg p-2 text-[var(--color-status-error-text)] transition-all duration-200 hover:bg-[var(--color-status-error-bgSubtle)] disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label={`${tr('workspaces.removeMember.ariaPrefix', 'Remove')} ${member.userId} ${tr('workspaces.removeMember.ariaSuffix', 'from workspace')}`}\n title={`${tr('workspaces.removeMember.ariaPrefix', 'Remove')} ${member.userId} ${tr('workspaces.removeMember.ariaSuffix', 'from workspace')}`}\n >\n <Trash2 size={18} aria-hidden=\"true\" />\n </button>\n );\n\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 (!hasPermission(PERMISSIONS.WORKSPACE_READ)) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <div className=\"p-8 text-center text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.detail.noPermission',\n \"You don't have permission to view this workspace.\"\n )}\n </div>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <LoadingState message={tr('workspaces.detail.loading', 'Loading workspace details...')} />\n </div>\n );\n }\n\n if (error || !workspace) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <ErrorState\n message={error?.message || tr('workspaces.detail.notFound', 'Workspace not found')}\n action={{\n label: tr('workspaces.create.backToWorkspaces', 'Back to Workspaces'),\n onClick: () => navigate(`${basePath}/workspaces`),\n }}\n />\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 animate-in fade-in duration-200\">\n <div className=\"mx-auto flex w-full max-w-7xl flex-col gap-6\">\n <div className=\"space-y-4\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces`)}\n className=\"inline-flex min-h-10 items-center gap-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:text-[var(--color-text-primary)]\"\n >\n <ArrowLeft size={20} aria-hidden=\"true\" />\n <span className=\"text-sm font-medium\">\n {tr('workspaces.create.backToWorkspaces', 'Back to Workspaces')}\n </span>\n </button>\n\n <EmphasisPanel className=\"flex flex-col gap-4 p-5 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"flex min-w-0 items-start gap-4\">\n <div className=\"flex size-16 items-center justify-center rounded-xl bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]\">\n <Briefcase size={28} aria-hidden=\"true\" />\n </div>\n\n <div className=\"min-w-0 space-y-2\">\n <div className=\"flex flex-wrap items-start gap-2\">\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {workspace.name}\n </h1>\n <WorkspaceStatusBadge status={workspace.status} />\n </div>\n <p className=\"break-all font-mono text-sm text-[var(--color-text-secondary)]\">\n /{workspace.slug}\n </p>\n <PagePurpose className=\"max-w-2xl\">\n {tr(\n 'workspaces.detail.purpose',\n 'This is one workspace — a focused space where a team collaborates. Review its details here, switch to the Members tab to control who has access, or edit its settings. Use this page to keep the right people in and the workspace healthy.'\n )}\n </PagePurpose>\n </div>\n </div>\n\n <CTAOverflowMenu\n primary={\n hasPermission(PERMISSIONS.WORKSPACE_UPDATE)\n ? {\n label: tr('workspaces.edit.title', 'Edit Workspace'),\n icon: <Edit size={16} aria-hidden=\"true\" />,\n onSelect: () => navigate(`${basePath}/workspaces/${id}/edit`),\n }\n : undefined\n }\n actions={[\n {\n label: tr('workspaces.detail.viewOrganization', 'View Organization'),\n icon: <Users size={16} aria-hidden=\"true\" />,\n onSelect: () => navigate(`${basePath}/${workspace.organizationId}`),\n },\n ]}\n />\n </EmphasisPanel>\n </div>\n\n <NextSteps\n storageKey=\"organization-workspace-detail\"\n steps={[\n ...(hasPermission(PERMISSIONS.MEMBER_INVITE)\n ? [\n {\n id: 'add-member',\n label: tr('workspaces.detail.next.addMember', 'Add a member'),\n description: tr(\n 'workspaces.detail.next.addMemberDesc',\n 'Bring people from the parent organization into this workspace.'\n ),\n icon: <UserPlus size={16} aria-hidden=\"true\" />,\n onClick: () => {\n setActiveTab('members');\n setIsAddMemberDialogOpen(true);\n },\n },\n ]\n : []),\n {\n id: 'review-members',\n label: tr('workspaces.detail.next.reviewMembers', 'Review members & access'),\n description: tr(\n 'workspaces.detail.next.reviewMembersDesc',\n 'See who can access this workspace and their roles.'\n ),\n icon: <Users size={16} aria-hidden=\"true\" />,\n onClick: () => setActiveTab('members'),\n },\n ...(hasPermission(PERMISSIONS.WORKSPACE_UPDATE)\n ? [\n {\n id: 'edit',\n label: tr('workspaces.detail.next.edit', 'Edit workspace settings'),\n description: tr(\n 'workspaces.detail.next.editDesc',\n 'Update the name, slug, or status of this workspace.'\n ),\n icon: <Edit size={16} aria-hidden=\"true\" />,\n onClick: () => navigate(`${basePath}/workspaces/${id}/edit`),\n },\n ]\n : []),\n {\n id: 'view-org',\n label: tr('workspaces.detail.next.viewOrg', 'Open the parent organization'),\n description: tr(\n 'workspaces.detail.next.viewOrgDesc',\n 'Jump to the organization this workspace belongs to.'\n ),\n icon: <Briefcase size={16} aria-hidden=\"true\" />,\n onClick: () => navigate(`${basePath}/${workspace.organizationId}`),\n },\n ]}\n />\n\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-0\">\n <div className=\"overflow-x-auto border-b border-[var(--color-border-seam)]\">\n <div className=\"flex min-w-max gap-2 px-4 pt-4 sm:px-6\">\n {tabItems.map((tabItem) => {\n const isActive = activeTab === tabItem.id;\n return (\n <button\n type=\"button\"\n key={tabItem.id}\n onClick={() => setActiveTab(tabItem.id)}\n className={`inline-flex min-h-11 items-center rounded-t-lg border-b-2 px-4 py-3 text-sm font-medium transition-colors ${\n isActive\n ? 'border-[var(--color-action-primary-bg)] text-[var(--color-action-primary-bg)]'\n : 'border-transparent text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]'\n }`}\n aria-pressed={isActive}\n >\n {tabItem.label}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"p-4 sm:p-6\">\n {activeTab === 'overview' ? (\n <div className=\"grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_320px]\">\n <GlassCard\n treatment=\"plain\"\n className=\"border-border-seam bg-[var(--color-bg-canvas)] p-5\"\n >\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('workspaces.detail.detailsSection', 'Workspace details')}\n </h2>\n\n <dl className=\"mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.name', 'Name')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {workspace.name}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.slug', 'Slug')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {workspace.slug}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.status', 'Status')}\n </dt>\n <dd className=\"mt-1\">\n <WorkspaceStatusBadge status={workspace.status} />\n </dd>\n </div>\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('members.detail.orgId', 'Organization ID')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {workspace.organizationId}\n </dd>\n </div>\n {workspace.endpoint ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('workspaces.detail.endpoint', 'Endpoint')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {workspace.endpoint}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n\n <GlassCard\n treatment=\"plain\"\n className=\"border-border-seam bg-[var(--color-bg-canvas)] p-5 xl:sticky xl:top-6 xl:self-start\"\n >\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('common.metadata', 'Metadata')}\n </h2>\n\n <dl className=\"mt-5 space-y-4\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('workspaces.list.members', 'Members')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {resolvedMemberCount}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(workspace.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.lastUpdated', 'Last updated')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(workspace.updatedAt)}\n </dd>\n </div>\n {workspace.region ? (\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('workspaces.detail.region', 'Region')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {workspace.region}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n </div>\n ) : (\n <section className=\"space-y-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('workspaces.detail.membersTitle', 'Workspace members')}\n </h2>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr(\n 'workspaces.detail.membersSubtitle',\n 'Add organization members to this workspace and manage access.'\n )}\n </p>\n </div>\n {hasPermission(PERMISSIONS.MEMBER_INVITE) && (\n <button\n type=\"button\"\n onClick={() => setIsAddMemberDialogOpen(true)}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2.5 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90\"\n >\n <UserPlus size={16} aria-hidden=\"true\" />\n <span>{tr('workspaces.detail.addMember', 'Add Member')}</span>\n </button>\n )}\n </div>\n\n {membersLoading ? (\n <div className=\"py-8\">\n <LoadingState\n message={tr(\n 'workspaces.detail.loadingMembers',\n 'Loading workspace members...'\n )}\n />\n </div>\n ) : membersError ? (\n <ErrorState\n message={membersError.message}\n action={{\n label: tr('common.retry', 'Retry'),\n onClick: () => {\n void refetchMembers();\n },\n }}\n />\n ) : members.length > 0 ? (\n <div className=\"overflow-hidden rounded-xl border border-[var(--color-border-seam)] bg-[var(--color-bg-canvas)] md:p-2\">\n <ResponsiveTable\n columns={memberColumns}\n data={members}\n rowKey={(member) => member.id}\n rowActions={renderMemberActions}\n />\n </div>\n ) : (\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-6\">\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={tr('workspaces.detail.emptyMembersTitle', 'No workspace members yet')}\n description={tr(\n 'workspaces.detail.emptyMembersDescription',\n 'Add people from the parent organization to grant workspace access.'\n )}\n action={\n <button\n type=\"button\"\n onClick={() => setIsAddMemberDialogOpen(true)}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:bg-[var(--color-action-primary-bgHover)]\"\n >\n {tr('workspaces.detail.addMember', 'Add Member')}\n </button>\n }\n />\n </div>\n )}\n </section>\n )}\n </div>\n </GlassCard>\n </div>\n\n <AddWorkspaceMemberDialog\n open={isAddMemberDialogOpen}\n onOpenChange={setIsAddMemberDialogOpen}\n workspaceId={workspace.id}\n organizationId={workspace.organizationId}\n existingMembers={members}\n onInviteOrganizationMember={() =>\n navigate(`${basePath}/${workspace.organizationId}/members/invite`)\n }\n />\n {ConfirmDialog}\n </div>\n );\n}\n"],"mappings":"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"}