@burdenoff/microfe-workspaces 2026.531.2 → 2026.531.4

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 (44) hide show
  1. package/dist/WorkspacesRoutes.js +36 -17
  2. package/dist/WorkspacesRoutes.js.map +1 -1
  3. package/dist/components/InviteMemberDialog.js +204 -117
  4. package/dist/components/InviteMemberDialog.js.map +1 -1
  5. package/dist/components/MemberListItem.js +2 -1
  6. package/dist/components/MemberListItem.js.map +1 -1
  7. package/dist/components/ProjectMemberPickerDialog.js +211 -0
  8. package/dist/components/ProjectMemberPickerDialog.js.map +1 -0
  9. package/dist/hooks/index.js +1 -1
  10. package/dist/hooks/useMemberMutations.js +13 -13
  11. package/dist/hooks/useMemberMutations.js.map +1 -1
  12. package/dist/hooks/useProjectMemberMutations.js +104 -0
  13. package/dist/hooks/useProjectMemberMutations.js.map +1 -0
  14. package/dist/hooks/useProjectMembers.js +42 -0
  15. package/dist/hooks/useProjectMembers.js.map +1 -0
  16. package/dist/hooks/useWorkspaceMembers.js +60 -24
  17. package/dist/hooks/useWorkspaceMembers.js.map +1 -1
  18. package/dist/hooks/useWorkspacePermissions.js +4 -0
  19. package/dist/hooks/useWorkspacePermissions.js.map +1 -1
  20. package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
  21. package/dist/index.js +16 -15
  22. package/dist/pages/ActivityListPage.js +5 -5
  23. package/dist/pages/InviteAcceptancePage.js +211 -207
  24. package/dist/pages/InviteAcceptancePage.js.map +1 -1
  25. package/dist/pages/MembersListPage.js +210 -208
  26. package/dist/pages/MembersListPage.js.map +1 -1
  27. package/dist/pages/PendingInvitesPage.js +124 -120
  28. package/dist/pages/PendingInvitesPage.js.map +1 -1
  29. package/dist/pages/ProjectDetailPage.js +249 -213
  30. package/dist/pages/ProjectDetailPage.js.map +1 -1
  31. package/dist/pages/ProjectMembersPage.js +265 -0
  32. package/dist/pages/ProjectMembersPage.js.map +1 -0
  33. package/dist/pages/ProjectsListPage.js +9 -9
  34. package/dist/pages/WorkspaceDetailPage.js +119 -111
  35. package/dist/pages/WorkspaceDetailPage.js.map +1 -1
  36. package/dist/pages/WorkspaceInvitePage.js +790 -0
  37. package/dist/pages/WorkspaceInvitePage.js.map +1 -0
  38. package/dist/pages/WorkspacesListPage.js +115 -100
  39. package/dist/pages/WorkspacesListPage.js.map +1 -1
  40. package/dist/utils/invitationDisplay.js +25 -0
  41. package/dist/utils/invitationDisplay.js.map +1 -0
  42. package/dist/utils/workspaceBulkInviteCsv.js +42 -0
  43. package/dist/utils/workspaceBulkInviteCsv.js.map +1 -0
  44. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MemberListItem.js","names":[],"sources":["../../src/components/MemberListItem.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Card,\n CardContent,\n Button,\n Badge,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuTrigger,\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { MoreHorizontal, UserMinus } from 'lucide-react';\nimport { ActorIdentity, useActorProfiles, type ActorInput } from '@burdenoff/fe-libs/shared';\nimport { useRemoveWorkspaceMember } from '../hooks/useMemberMutations';\nimport { nativeImpact, nativeNotify } from '../utils/nativeBridge';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport type { WorkspaceMember } from '../types';\n\nexport interface MemberListItemProps {\n member: WorkspaceMember;\n onUpdateRoles?: (memberId: string, roleIds: string[]) => void;\n selected?: boolean;\n onToggleSelect?: (checked: boolean) => void;\n canRemove?: boolean;\n}\n\nexport function MemberListItem({\n member,\n selected = false,\n onToggleSelect,\n canRemove = false,\n}: MemberListItemProps) {\n const [showRemoveDialog, setShowRemoveDialog] = useState(false);\n const { mutate: removeMember, isPending: isRemoving } = useRemoveWorkspaceMember(\n member.workspaceId\n );\n const { apiGatewayUrl, authToken, organizationId } = useWorkspacesContext();\n\n // Resolve userId → displayName + email via the shared actor profile cache.\n // UUIDs must never headline a row — the resolved identity goes in primary\n // position; the raw ID lives in the drill-down inside ActorIdentity.\n const actors = useMemo<ActorInput[]>(\n () => [{ actorId: member.userId, actorType: 'user' }],\n [member.userId]\n );\n const profileMap = useActorProfiles(actors, {\n apiGatewayUrl,\n authToken,\n orgId: organizationId,\n });\n const profile = profileMap[member.userId];\n\n const handleRemove = () => {\n void nativeImpact('medium');\n removeMember(member.id, {\n onSuccess: () => {\n void nativeNotify('success');\n setShowRemoveDialog(false);\n },\n onError: () => {\n void nativeNotify('error');\n },\n });\n };\n\n return (\n <>\n <Card\n className={`hover:bg-bg-canvas transition-all duration-200 ${\n selected ? 'ring-2 ring-action-primary-bg/25 border-action-primary-bg/50' : ''\n }`}\n >\n <CardContent className=\"p-4\">\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"flex items-center gap-3 flex-1 min-w-0\">\n {onToggleSelect && (\n <input\n type=\"checkbox\"\n checked={selected}\n onChange={(event) => onToggleSelect(event.target.checked)}\n className=\"size-4 rounded border-border-default text-action-primary-bg\"\n aria-label={`Select member ${profile?.displayName ?? ''}`}\n />\n )}\n\n <div className=\"flex-1 min-w-0\">\n {profile ? <ActorIdentity profile={profile} variant=\"cell\" /> : null}\n <div className=\"mt-1 flex items-center gap-2\">\n <Badge variant=\"secondary\" className=\"text-xs\">\n Workspace member\n </Badge>\n <span className=\"text-xs text-text-secondary\">\n Joined {formatRelativeTime(member.createdAt)}\n </span>\n </div>\n </div>\n </div>\n\n {canRemove && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"size-8 flex-shrink-0\">\n <MoreHorizontal className=\"size-4\" />\n <span className=\"sr-only\">Open member actions</span>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <button\n type=\"button\"\n onClick={() => setShowRemoveDialog(true)}\n className=\"flex w-full items-center rounded-sm px-2 py-1.5 text-sm text-status-danger-text outline-none transition-colors hover:bg-action-ghost-bg-hover focus:bg-action-ghost-bg-hover\"\n >\n <UserMinus className=\"mr-2 size-4\" />\n Remove Member\n </button>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n </CardContent>\n </Card>\n\n <AlertDialog open={showRemoveDialog} onOpenChange={setShowRemoveDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Remove Member</AlertDialogTitle>\n <AlertDialogDescription>\n Are you sure you want to remove {profile?.displayName ?? 'this member'} from the\n workspace? This action cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isRemoving}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={handleRemove}\n disabled={isRemoving}\n className=\"bg-status-danger-bg text-status-danger-text hover:bg-status-danger-bg/90\"\n >\n {isRemoving ? 'Removing...' : 'Remove Member'}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;AAkCA,SAAgB,EAAe,EAC7B,WACA,cAAW,IACX,mBACA,eAAY,MACU;CACtB,IAAM,CAAC,GAAkB,KAAuB,EAAS,GAAM,EACzD,EAAE,QAAQ,GAAc,WAAW,MAAe,EACtD,EAAO,YACR,EACK,EAAE,kBAAe,cAAW,sBAAmB,GAAsB,EAcrE,IALa,EAJJ,QACP,CAAC;EAAE,SAAS,EAAO;EAAQ,WAAW;EAAQ,CAAC,EACrD,CAAC,EAAO,OAAO,CAChB,EAC2C;EAC1C;EACA;EACA,OAAO;EACR,CAAC,CACyB,EAAO;AAelC,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,WAAW,kDACT,IAAW,iEAAiE;YAG9E,kBAAC,GAAD;GAAa,WAAU;aACrB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,KACC,kBAAC,SAAD;MACE,MAAK;MACL,SAAS;MACT,WAAW,MAAU,EAAe,EAAM,OAAO,QAAQ;MACzD,WAAU;MACV,cAAY,iBAAiB,GAAS,eAAe;MACrD,CAAA,EAGJ,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,IAAU,kBAAC,GAAD;OAAwB;OAAS,SAAQ;OAAS,CAAA,GAAG,MAChE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;QAAY,WAAU;kBAAU;QAEvC,CAAA,EACR,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CAA8C,WACpC,EAAmB,EAAO,UAAU,CACvC;UACH;SACF;QACF;QAEL,KACC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAqB,SAAA;eACnB,kBAAC,GAAD;MAAQ,SAAQ;MAAQ,MAAK;MAAO,WAAU;gBAA9C,CACE,kBAAC,GAAD,EAAgB,WAAU,UAAW,CAAA,EACrC,kBAAC,QAAD;OAAM,WAAU;iBAAU;OAA0B,CAAA,CAC7C;;KACW,CAAA,EACtB,kBAAC,GAAD;KAAqB,OAAM;eACzB,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAoB,GAAK;MACxC,WAAU;gBAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,eAAgB,CAAA,EAAA,gBAE9B;;KACW,CAAA,CACT,EAAA,CAAA,CAEb;;GACM,CAAA;EACT,CAAA,EAEP,kBAAC,GAAD;EAAa,MAAM;EAAkB,cAAc;YACjD,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAkB,iBAAgC,CAAA,EAClD,kBAAC,GAAD,EAAA,UAAA;GAAwB;GACW,GAAS,eAAe;GAAc;GAEhD,EAAA,CAAA,CACP,EAAA,CAAA,EACpB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAmB,UAAU;aAAY;GAA0B,CAAA,EACnE,kBAAC,GAAD;GACE,eAlFe;AAEzB,IADK,EAAa,SAAS,EAC3B,EAAa,EAAO,IAAI;KACtB,iBAAiB;AAEf,MADK,EAAa,UAAU,EAC5B,EAAoB,GAAM;;KAE5B,eAAe;AACR,QAAa,QAAQ;;KAE7B,CAAC;;GAyEQ,UAAU;GACV,WAAU;aAET,IAAa,gBAAgB;GACZ,CAAA,CACF,EAAA,CAAA,CACD,EAAA,CAAA;EACT,CAAA,CACb,EAAA,CAAA"}
1
+ {"version":3,"file":"MemberListItem.js","names":[],"sources":["../../src/components/MemberListItem.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Card,\n CardContent,\n Button,\n Badge,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuTrigger,\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { MoreHorizontal, UserMinus } from 'lucide-react';\nimport { ActorIdentity, useActorProfiles, type ActorInput } from '@burdenoff/fe-libs/shared';\nimport { useRemoveWorkspaceMember } from '../hooks/useMemberMutations';\nimport { nativeImpact, nativeNotify } from '../utils/nativeBridge';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport type { WorkspaceMember } from '../types';\n\nexport interface MemberListItemProps {\n member: WorkspaceMember;\n onUpdateRoles?: (memberId: string, roleIds: string[]) => void;\n selected?: boolean;\n onToggleSelect?: (checked: boolean) => void;\n canRemove?: boolean;\n}\n\nexport function MemberListItem({\n member,\n selected = false,\n onToggleSelect,\n canRemove = false,\n}: MemberListItemProps) {\n const [showRemoveDialog, setShowRemoveDialog] = useState(false);\n const { mutate: removeMember, isPending: isRemoving } = useRemoveWorkspaceMember(\n member.workspaceId\n );\n const { apiGatewayUrl, authToken, organizationId } = useWorkspacesContext();\n\n // Resolve userId → displayName + email via the shared actor profile cache.\n // UUIDs must never headline a row — the resolved identity goes in primary\n // position; the raw ID lives in the drill-down inside ActorIdentity.\n const actors = useMemo<ActorInput[]>(\n () => [{ actorId: member.userId, actorType: 'user' }],\n [member.userId]\n );\n const profileMap = useActorProfiles(actors, {\n apiGatewayUrl,\n authToken,\n orgId: organizationId,\n workspaceId: member.workspaceId,\n });\n const profile = profileMap[member.userId];\n\n const handleRemove = () => {\n void nativeImpact('medium');\n removeMember(member.id, {\n onSuccess: () => {\n void nativeNotify('success');\n setShowRemoveDialog(false);\n },\n onError: () => {\n void nativeNotify('error');\n },\n });\n };\n\n return (\n <>\n <Card\n className={`hover:bg-bg-canvas transition-all duration-200 ${\n selected ? 'ring-2 ring-action-primary-bg/25 border-action-primary-bg/50' : ''\n }`}\n >\n <CardContent className=\"p-4\">\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"flex items-center gap-3 flex-1 min-w-0\">\n {onToggleSelect && (\n <input\n type=\"checkbox\"\n checked={selected}\n onChange={(event) => onToggleSelect(event.target.checked)}\n className=\"size-4 rounded border-border-default text-action-primary-bg\"\n aria-label={`Select member ${profile?.displayName ?? ''}`}\n />\n )}\n\n <div className=\"flex-1 min-w-0\">\n {profile ? <ActorIdentity profile={profile} variant=\"cell\" /> : null}\n <div className=\"mt-1 flex items-center gap-2\">\n <Badge variant=\"secondary\" className=\"text-xs\">\n Workspace member\n </Badge>\n <span className=\"text-xs text-text-secondary\">\n Joined {formatRelativeTime(member.createdAt)}\n </span>\n </div>\n </div>\n </div>\n\n {canRemove && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"size-8 flex-shrink-0\">\n <MoreHorizontal className=\"size-4\" />\n <span className=\"sr-only\">Open member actions</span>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <button\n type=\"button\"\n onClick={() => setShowRemoveDialog(true)}\n className=\"flex w-full items-center rounded-sm px-2 py-1.5 text-sm text-status-danger-text outline-none transition-colors hover:bg-action-ghost-bg-hover focus:bg-action-ghost-bg-hover\"\n >\n <UserMinus className=\"mr-2 size-4\" />\n Remove Member\n </button>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n </CardContent>\n </Card>\n\n <AlertDialog open={showRemoveDialog} onOpenChange={setShowRemoveDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Remove Member</AlertDialogTitle>\n <AlertDialogDescription>\n Are you sure you want to remove {profile?.displayName ?? 'this member'} from the\n workspace? This action cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isRemoving}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={handleRemove}\n disabled={isRemoving}\n className=\"bg-status-danger-bg text-status-danger-text hover:bg-status-danger-bg/90\"\n >\n {isRemoving ? 'Removing...' : 'Remove Member'}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;AAkCA,SAAgB,EAAe,EAC7B,WACA,cAAW,IACX,mBACA,eAAY,MACU;CACtB,IAAM,CAAC,GAAkB,KAAuB,EAAS,GAAM,EACzD,EAAE,QAAQ,GAAc,WAAW,MAAe,EACtD,EAAO,YACR,EACK,EAAE,kBAAe,cAAW,sBAAmB,GAAsB,EAerE,IANa,EAJJ,QACP,CAAC;EAAE,SAAS,EAAO;EAAQ,WAAW;EAAQ,CAAC,EACrD,CAAC,EAAO,OAAO,CAChB,EAC2C;EAC1C;EACA;EACA,OAAO;EACP,aAAa,EAAO;EACrB,CAAC,CACyB,EAAO;AAelC,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,WAAW,kDACT,IAAW,iEAAiE;YAG9E,kBAAC,GAAD;GAAa,WAAU;aACrB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,KACC,kBAAC,SAAD;MACE,MAAK;MACL,SAAS;MACT,WAAW,MAAU,EAAe,EAAM,OAAO,QAAQ;MACzD,WAAU;MACV,cAAY,iBAAiB,GAAS,eAAe;MACrD,CAAA,EAGJ,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,IAAU,kBAAC,GAAD;OAAwB;OAAS,SAAQ;OAAS,CAAA,GAAG,MAChE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;QAAY,WAAU;kBAAU;QAEvC,CAAA,EACR,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CAA8C,WACpC,EAAmB,EAAO,UAAU,CACvC;UACH;SACF;QACF;QAEL,KACC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAqB,SAAA;eACnB,kBAAC,GAAD;MAAQ,SAAQ;MAAQ,MAAK;MAAO,WAAU;gBAA9C,CACE,kBAAC,GAAD,EAAgB,WAAU,UAAW,CAAA,EACrC,kBAAC,QAAD;OAAM,WAAU;iBAAU;OAA0B,CAAA,CAC7C;;KACW,CAAA,EACtB,kBAAC,GAAD;KAAqB,OAAM;eACzB,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAoB,GAAK;MACxC,WAAU;gBAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,eAAgB,CAAA,EAAA,gBAE9B;;KACW,CAAA,CACT,EAAA,CAAA,CAEb;;GACM,CAAA;EACT,CAAA,EAEP,kBAAC,GAAD;EAAa,MAAM;EAAkB,cAAc;YACjD,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAkB,iBAAgC,CAAA,EAClD,kBAAC,GAAD,EAAA,UAAA;GAAwB;GACW,GAAS,eAAe;GAAc;GAEhD,EAAA,CAAA,CACP,EAAA,CAAA,EACpB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAmB,UAAU;aAAY;GAA0B,CAAA,EACnE,kBAAC,GAAD;GACE,eAlFe;AAEzB,IADK,EAAa,SAAS,EAC3B,EAAa,EAAO,IAAI;KACtB,iBAAiB;AAEf,MADK,EAAa,UAAU,EAC5B,EAAoB,GAAM;;KAE5B,eAAe;AACR,QAAa,QAAQ;;KAE7B,CAAC;;GAyEQ,UAAU;GACV,WAAU;aAET,IAAa,gBAAgB;GACZ,CAAA,CACF,EAAA,CAAA,CACD,EAAA,CAAA;EACT,CAAA,CACb,EAAA,CAAA"}
@@ -0,0 +1,211 @@
1
+ import { useWorkspacesContext as e } from "../providers/WorkspacesProvider.js";
2
+ import { nativeImpact as t, nativeNotify as n } from "../utils/nativeBridge.js";
3
+ import { useInfiniteWorkspaceMembers as r } from "../hooks/useWorkspaceMembers.js";
4
+ import { useAddProjectMember as ee } from "../hooks/useProjectMemberMutations.js";
5
+ import { useInfiniteProjectMembers as te } from "../hooks/useProjectMembers.js";
6
+ import { useEffect as ne, useMemo as i, useState as a } from "react";
7
+ import { AlertCircle as o, Search as re, UserPlus as s } from "lucide-react";
8
+ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
9
+ import { Badge as ie, Button as d, Input as f, ResponsiveDialog as p, ResponsiveDialogContent as ae, ResponsiveDialogDescription as m, ResponsiveDialogHeader as h, ResponsiveDialogTitle as g, Skeleton as _ } from "@burdenoff/fe-libs/ui";
10
+ import { ActorIdentity as v, useActorProfiles as y } from "@burdenoff/fe-libs/shared";
11
+ //#region src/components/ProjectMemberPickerDialog.tsx
12
+ var b = 100, x = 10;
13
+ function S(e) {
14
+ let t = e.context?.metadata;
15
+ return {
16
+ name: typeof t?.displayName == "string" ? t.displayName : typeof t?.name == "string" ? t.name : e.userId,
17
+ email: typeof t?.email == "string" ? t.email : void 0
18
+ };
19
+ }
20
+ function C({ open: C, onOpenChange: w, workspaceId: T, projectId: E, projectName: D }) {
21
+ let { apiGatewayUrl: O, authToken: oe, organizationId: se } = e(), { mutate: ce, isPending: k } = ee(T), [A, j] = a(""), [le, M] = a(null), [N, P] = a(null), { data: F, isLoading: I, isError: L, error: R, hasNextPage: z, fetchNextPage: B, isFetchingNextPage: V, refetch: H } = r(T, b, C), { data: U, isLoading: ue, isError: W, error: G, hasNextPage: K, fetchNextPage: q, isFetchingNextPage: J } = te(E, T, b, C);
22
+ ne(() => {
23
+ !C || !K || J || W || (U?.pages.length ?? 0) >= x || q();
24
+ }, [
25
+ q,
26
+ K,
27
+ W,
28
+ J,
29
+ C,
30
+ U?.pages.length
31
+ ]);
32
+ let Y = i(() => F?.pages.flatMap((e) => e.items) ?? [], [F?.pages]), X = i(() => new Set(U?.pages.flatMap((e) => e.items.map((e) => e.userId)) ?? []), [U?.pages]), de = F?.pages[0]?.total ?? Y.length, Z = (U?.pages.length ?? 0) >= x, fe = !W && K && !Z, Q = y(i(() => Y.map((e) => ({
33
+ actorId: e.userId,
34
+ actorType: "user"
35
+ })), [Y]), {
36
+ apiGatewayUrl: O,
37
+ authToken: oe,
38
+ orgId: se,
39
+ workspaceId: T
40
+ }), $ = i(() => {
41
+ let e = A.trim().toLowerCase();
42
+ return Y.filter((t) => {
43
+ if (X.has(t.userId)) return !1;
44
+ if (!e) return !0;
45
+ let n = Q[t.userId];
46
+ if (n && (n.displayName.toLowerCase().includes(e) || n.email?.toLowerCase().includes(e))) return !0;
47
+ let r = S(t);
48
+ return r.name.toLowerCase().includes(e) || r.email?.toLowerCase().includes(e) || t.userId.toLowerCase().includes(e);
49
+ });
50
+ }, [
51
+ X,
52
+ Q,
53
+ A,
54
+ Y
55
+ ]), pe = (e) => {
56
+ t("medium"), M(e), P(null), ce({
57
+ projectId: E,
58
+ userId: e
59
+ }, {
60
+ onSuccess: () => {
61
+ n("success"), M(null), w(!1);
62
+ },
63
+ onError: (e) => {
64
+ n("error"), M(null), P(e instanceof Error ? e.message : "Failed to add member to project");
65
+ }
66
+ });
67
+ };
68
+ return /* @__PURE__ */ l(p, {
69
+ open: C,
70
+ onOpenChange: w,
71
+ children: /* @__PURE__ */ u(ae, {
72
+ className: "z-[120] flex h-[min(85vh,760px)] flex-col overflow-hidden sm:max-w-[720px]",
73
+ children: [/* @__PURE__ */ u(h, { children: [/* @__PURE__ */ l(g, { children: "Add member to project" }), /* @__PURE__ */ u(m, { children: [
74
+ "Add an existing workspace member to ",
75
+ D || "this project",
76
+ ". Only current workspace members are eligible."
77
+ ] })] }), /* @__PURE__ */ u("div", {
78
+ className: "space-y-4 overflow-hidden",
79
+ children: [
80
+ N ? /* @__PURE__ */ u("div", {
81
+ className: "flex items-center gap-2 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive",
82
+ children: [/* @__PURE__ */ l(o, { className: "size-4 shrink-0" }), /* @__PURE__ */ l("span", { children: N })]
83
+ }) : null,
84
+ G instanceof Error ? /* @__PURE__ */ u("div", {
85
+ className: "flex items-center gap-2 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive",
86
+ children: [/* @__PURE__ */ l(o, { className: "size-4 shrink-0" }), /* @__PURE__ */ l("span", { children: G.message })]
87
+ }) : null,
88
+ R instanceof Error ? /* @__PURE__ */ u("div", {
89
+ className: "space-y-3 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive",
90
+ children: [/* @__PURE__ */ u("div", {
91
+ className: "flex items-center gap-2",
92
+ children: [/* @__PURE__ */ l(o, { className: "size-4 shrink-0" }), /* @__PURE__ */ l("span", { children: R.message })]
93
+ }), /* @__PURE__ */ l(d, {
94
+ variant: "outline",
95
+ onClick: () => void H(),
96
+ children: "Retry Loading Members"
97
+ })]
98
+ }) : null,
99
+ /* @__PURE__ */ u("div", {
100
+ className: "flex items-center gap-2",
101
+ children: [/* @__PURE__ */ u("div", {
102
+ className: "relative flex-1",
103
+ children: [/* @__PURE__ */ l(re, { className: "absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }), /* @__PURE__ */ l(f, {
104
+ value: A,
105
+ onChange: (e) => j(e.target.value),
106
+ placeholder: "Search workspace members",
107
+ className: "pl-9",
108
+ disabled: k
109
+ })]
110
+ }), /* @__PURE__ */ u(ie, {
111
+ variant: "secondary",
112
+ children: [
113
+ z ? `${$.length}+` : $.length,
114
+ " ",
115
+ "eligible"
116
+ ]
117
+ })]
118
+ }),
119
+ /* @__PURE__ */ l("div", {
120
+ className: "max-h-[480px] space-y-3 overflow-y-auto pr-1",
121
+ children: L ? null : I || ue || fe || J ? Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ u("div", {
122
+ className: "rounded-lg border bg-card p-4",
123
+ children: [/* @__PURE__ */ l(_, { className: "h-5 w-40" }), /* @__PURE__ */ l(_, { className: "mt-2 h-4 w-56" })]
124
+ }, t)) : G instanceof Error ? null : $.length === 0 ? /* @__PURE__ */ u("div", {
125
+ className: "rounded-lg border bg-card p-8 text-center",
126
+ children: [
127
+ /* @__PURE__ */ l(s, { className: "mx-auto mb-3 size-10 text-muted-foreground" }),
128
+ /* @__PURE__ */ l("h3", {
129
+ className: "text-lg font-semibold",
130
+ children: "No eligible members found"
131
+ }),
132
+ /* @__PURE__ */ l("p", {
133
+ className: "mt-2 text-sm text-muted-foreground",
134
+ children: "All workspace members are already part of this project, or nothing matched your search."
135
+ }),
136
+ Z ? /* @__PURE__ */ u("p", {
137
+ className: "mt-3 text-xs text-muted-foreground",
138
+ children: [
139
+ "Loaded the first ",
140
+ x * b,
141
+ " ",
142
+ "project members to avoid an excessively long blocking load."
143
+ ]
144
+ }) : null,
145
+ z ? /* @__PURE__ */ l("div", {
146
+ className: "mt-4",
147
+ children: /* @__PURE__ */ l(d, {
148
+ variant: "outline",
149
+ onClick: () => void B(),
150
+ disabled: V || k,
151
+ children: V ? "Loading more…" : "Load More Members"
152
+ })
153
+ }) : null
154
+ ]
155
+ }) : /* @__PURE__ */ u(c, { children: [$.map((e) => {
156
+ let t = Q[e.userId], n = S(e), r = k && le === e.userId;
157
+ return /* @__PURE__ */ u("div", {
158
+ className: "flex items-center justify-between gap-4 rounded-lg border bg-card p-4",
159
+ children: [/* @__PURE__ */ l("div", {
160
+ className: "min-w-0 flex-1",
161
+ children: t ? /* @__PURE__ */ l(v, {
162
+ profile: t,
163
+ variant: "cell"
164
+ }) : /* @__PURE__ */ u("div", {
165
+ className: "min-w-0",
166
+ children: [/* @__PURE__ */ l("p", {
167
+ className: "truncate font-medium",
168
+ children: n.name
169
+ }), n.email ? /* @__PURE__ */ l("p", {
170
+ className: "truncate text-sm text-muted-foreground",
171
+ children: n.email
172
+ }) : /* @__PURE__ */ l("p", {
173
+ className: "truncate text-xs text-muted-foreground",
174
+ children: e.userId
175
+ })]
176
+ })
177
+ }), /* @__PURE__ */ u(d, {
178
+ size: "sm",
179
+ onClick: () => pe(e.userId),
180
+ disabled: k,
181
+ children: [/* @__PURE__ */ l(s, { className: "mr-2 size-4" }), r ? "Adding..." : "Add"]
182
+ })]
183
+ }, e.id);
184
+ }), z ? /* @__PURE__ */ u("div", {
185
+ className: "flex flex-col items-center gap-2 rounded-lg border border-dashed bg-muted/20 p-4 text-center",
186
+ children: [/* @__PURE__ */ u("p", {
187
+ className: "text-sm text-muted-foreground",
188
+ children: [
189
+ "Showing ",
190
+ Y.length,
191
+ " of ",
192
+ de,
193
+ " workspace members."
194
+ ]
195
+ }), /* @__PURE__ */ l(d, {
196
+ variant: "outline",
197
+ onClick: () => void B(),
198
+ disabled: V || k,
199
+ children: V ? "Loading more…" : "Load More Members"
200
+ })]
201
+ }) : null] })
202
+ })
203
+ ]
204
+ })]
205
+ })
206
+ });
207
+ }
208
+ //#endregion
209
+ export { C as ProjectMemberPickerDialog };
210
+
211
+ //# sourceMappingURL=ProjectMemberPickerDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectMemberPickerDialog.js","names":[],"sources":["../../src/components/ProjectMemberPickerDialog.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { AlertCircle, Search, UserPlus } from 'lucide-react';\nimport {\n ActorIdentity,\n useActorProfiles,\n type ActorInput,\n type ActorProfileMap,\n} from '@burdenoff/fe-libs/shared';\nimport {\n Badge,\n Button,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n Skeleton,\n} from '@burdenoff/fe-libs/ui';\nimport { useAddProjectMember } from '../hooks/useProjectMemberMutations';\nimport { useInfiniteProjectMembers } from '../hooks/useProjectMembers';\nimport { useInfiniteWorkspaceMembers } from '../hooks/useWorkspaceMembers';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { nativeImpact, nativeNotify } from '../utils/nativeBridge';\nimport type { WorkspaceMember } from '../types';\n\nconst MEMBER_PAGE_SIZE = 100;\nconst MAX_AUTOLOADED_PROJECT_MEMBER_PAGES = 10;\n\nfunction getFallbackDisplay(member: WorkspaceMember): { name: string; email?: string } {\n const meta = member.context?.metadata;\n const name =\n typeof meta?.displayName === 'string'\n ? meta.displayName\n : typeof meta?.name === 'string'\n ? meta.name\n : member.userId;\n const email = typeof meta?.email === 'string' ? meta.email : undefined;\n return { name, email };\n}\n\nexport interface ProjectMemberPickerDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n workspaceId: string;\n projectId: string;\n projectName?: string;\n}\n\nexport function ProjectMemberPickerDialog({\n open,\n onOpenChange,\n workspaceId,\n projectId,\n projectName,\n}: ProjectMemberPickerDialogProps) {\n const { apiGatewayUrl, authToken, organizationId } = useWorkspacesContext();\n const { mutate: addProjectMember, isPending: isAdding } = useAddProjectMember(workspaceId);\n const [searchValue, setSearchValue] = useState('');\n const [addingUserId, setAddingUserId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const {\n data: workspaceMembersPages,\n isLoading: isLoadingMembers,\n isError: isErrorWorkspaceMembers,\n error: workspaceMembersError,\n hasNextPage: hasMoreWorkspaceMembers,\n fetchNextPage: fetchNextWorkspaceMembersPage,\n isFetchingNextPage: isFetchingNextWorkspaceMembersPage,\n refetch: refetchWorkspaceMembers,\n } = useInfiniteWorkspaceMembers(workspaceId, MEMBER_PAGE_SIZE, open);\n\n const {\n data: projectMembersPages,\n isLoading: isLoadingProjectMembers,\n isError: isErrorProjectMembers,\n error: projectMembersError,\n hasNextPage: hasMoreProjectMembers,\n fetchNextPage: fetchNextProjectMembersPage,\n isFetchingNextPage: isFetchingNextProjectMembersPage,\n } = useInfiniteProjectMembers(projectId, workspaceId, MEMBER_PAGE_SIZE, open);\n\n useEffect(() => {\n if (\n !open ||\n !hasMoreProjectMembers ||\n isFetchingNextProjectMembersPage ||\n isErrorProjectMembers ||\n (projectMembersPages?.pages.length ?? 0) >= MAX_AUTOLOADED_PROJECT_MEMBER_PAGES\n ) {\n return;\n }\n\n void fetchNextProjectMembersPage();\n }, [\n fetchNextProjectMembersPage,\n hasMoreProjectMembers,\n isErrorProjectMembers,\n isFetchingNextProjectMembersPage,\n open,\n projectMembersPages?.pages.length,\n ]);\n\n const workspaceMembers = useMemo(\n () => workspaceMembersPages?.pages.flatMap((page) => page.items) ?? [],\n [workspaceMembersPages?.pages]\n );\n const existingUserIdSet = useMemo(\n () =>\n new Set(\n projectMembersPages?.pages.flatMap((page) => page.items.map((member) => member.userId)) ??\n []\n ),\n [projectMembersPages?.pages]\n );\n const totalWorkspaceMembers = workspaceMembersPages?.pages[0]?.total ?? workspaceMembers.length;\n const reachedProjectMemberAutoloadCap =\n (projectMembersPages?.pages.length ?? 0) >= MAX_AUTOLOADED_PROJECT_MEMBER_PAGES;\n const isAutoloadingProjectMembers =\n !isErrorProjectMembers && hasMoreProjectMembers && !reachedProjectMemberAutoloadCap;\n\n const actors = useMemo<ActorInput[]>(\n () => workspaceMembers.map((member) => ({ actorId: member.userId, actorType: 'user' })),\n [workspaceMembers]\n );\n const profileMap: ActorProfileMap = useActorProfiles(actors, {\n apiGatewayUrl,\n authToken,\n orgId: organizationId,\n workspaceId,\n });\n\n const eligibleMembers = useMemo(() => {\n const needle = searchValue.trim().toLowerCase();\n\n return workspaceMembers.filter((member) => {\n if (existingUserIdSet.has(member.userId)) {\n return false;\n }\n\n if (!needle) {\n return true;\n }\n\n const profile = profileMap[member.userId];\n if (profile) {\n if (profile.displayName.toLowerCase().includes(needle)) return true;\n if (profile.email?.toLowerCase().includes(needle)) return true;\n }\n\n const fallback = getFallbackDisplay(member);\n return (\n fallback.name.toLowerCase().includes(needle) ||\n fallback.email?.toLowerCase().includes(needle) ||\n member.userId.toLowerCase().includes(needle)\n );\n });\n }, [existingUserIdSet, profileMap, searchValue, workspaceMembers]);\n\n const handleAddMember = (userId: string) => {\n void nativeImpact('medium');\n setAddingUserId(userId);\n setError(null);\n\n addProjectMember(\n { projectId, userId },\n {\n onSuccess: () => {\n void nativeNotify('success');\n setAddingUserId(null);\n onOpenChange(false);\n },\n onError: (mutationError) => {\n void nativeNotify('error');\n setAddingUserId(null);\n setError(\n mutationError instanceof Error\n ? mutationError.message\n : 'Failed to add member to project'\n );\n },\n }\n );\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"z-[120] flex h-[min(85vh,760px)] flex-col overflow-hidden sm:max-w-[720px]\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add member to project</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Add an existing workspace member to {projectName || 'this project'}. Only current\n workspace members are eligible.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"space-y-4 overflow-hidden\">\n {error ? (\n <div className=\"flex items-center gap-2 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"size-4 shrink-0\" />\n <span>{error}</span>\n </div>\n ) : null}\n\n {projectMembersError instanceof Error ? (\n <div className=\"flex items-center gap-2 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive\">\n <AlertCircle className=\"size-4 shrink-0\" />\n <span>{projectMembersError.message}</span>\n </div>\n ) : null}\n\n {workspaceMembersError instanceof Error ? (\n <div className=\"space-y-3 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive\">\n <div className=\"flex items-center gap-2\">\n <AlertCircle className=\"size-4 shrink-0\" />\n <span>{workspaceMembersError.message}</span>\n </div>\n <Button variant=\"outline\" onClick={() => void refetchWorkspaceMembers()}>\n Retry Loading Members\n </Button>\n </div>\n ) : null}\n\n <div className=\"flex items-center gap-2\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={searchValue}\n onChange={(event) => setSearchValue(event.target.value)}\n placeholder=\"Search workspace members\"\n className=\"pl-9\"\n disabled={isAdding}\n />\n </div>\n <Badge variant=\"secondary\">\n {hasMoreWorkspaceMembers ? `${eligibleMembers.length}+` : eligibleMembers.length}{' '}\n eligible\n </Badge>\n </div>\n\n <div className=\"max-h-[480px] space-y-3 overflow-y-auto pr-1\">\n {isErrorWorkspaceMembers ? null : isLoadingMembers ||\n isLoadingProjectMembers ||\n isAutoloadingProjectMembers ||\n isFetchingNextProjectMembersPage ? (\n Array.from({ length: 5 }).map((_, index) => (\n <div key={index} className=\"rounded-lg border bg-card p-4\">\n <Skeleton className=\"h-5 w-40\" />\n <Skeleton className=\"mt-2 h-4 w-56\" />\n </div>\n ))\n ) : projectMembersError instanceof Error ? null : eligibleMembers.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-8 text-center\">\n <UserPlus className=\"mx-auto mb-3 size-10 text-muted-foreground\" />\n <h3 className=\"text-lg font-semibold\">No eligible members found</h3>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n All workspace members are already part of this project, or nothing matched your\n search.\n </p>\n {reachedProjectMemberAutoloadCap ? (\n <p className=\"mt-3 text-xs text-muted-foreground\">\n Loaded the first {MAX_AUTOLOADED_PROJECT_MEMBER_PAGES * MEMBER_PAGE_SIZE}{' '}\n project members to avoid an excessively long blocking load.\n </p>\n ) : null}\n {hasMoreWorkspaceMembers ? (\n <div className=\"mt-4\">\n <Button\n variant=\"outline\"\n onClick={() => void fetchNextWorkspaceMembersPage()}\n disabled={isFetchingNextWorkspaceMembersPage || isAdding}\n >\n {isFetchingNextWorkspaceMembersPage ? 'Loading more…' : 'Load More Members'}\n </Button>\n </div>\n ) : null}\n </div>\n ) : (\n <>\n {eligibleMembers.map((member) => {\n const profile = profileMap[member.userId];\n const fallback = getFallbackDisplay(member);\n const isSubmitting = isAdding && addingUserId === member.userId;\n\n return (\n <div\n key={member.id}\n className=\"flex items-center justify-between gap-4 rounded-lg border bg-card p-4\"\n >\n <div className=\"min-w-0 flex-1\">\n {profile ? (\n <ActorIdentity profile={profile} variant=\"cell\" />\n ) : (\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\">{fallback.name}</p>\n {fallback.email ? (\n <p className=\"truncate text-sm text-muted-foreground\">\n {fallback.email}\n </p>\n ) : (\n <p className=\"truncate text-xs text-muted-foreground\">\n {member.userId}\n </p>\n )}\n </div>\n )}\n </div>\n\n <Button\n size=\"sm\"\n onClick={() => handleAddMember(member.userId)}\n disabled={isAdding}\n >\n <UserPlus className=\"mr-2 size-4\" />\n {isSubmitting ? 'Adding...' : 'Add'}\n </Button>\n </div>\n );\n })}\n\n {hasMoreWorkspaceMembers ? (\n <div className=\"flex flex-col items-center gap-2 rounded-lg border border-dashed bg-muted/20 p-4 text-center\">\n <p className=\"text-sm text-muted-foreground\">\n Showing {workspaceMembers.length} of {totalWorkspaceMembers} workspace\n members.\n </p>\n <Button\n variant=\"outline\"\n onClick={() => void fetchNextWorkspaceMembersPage()}\n disabled={isFetchingNextWorkspaceMembersPage || isAdding}\n >\n {isFetchingNextWorkspaceMembersPage ? 'Loading more…' : 'Load More Members'}\n </Button>\n </div>\n ) : null}\n </>\n )}\n </div>\n </div>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;;;;;;;AA0BA,IAAM,IAAmB,KACnB,IAAsC;AAE5C,SAAS,EAAmB,GAA2D;CACrF,IAAM,IAAO,EAAO,SAAS;AAQ7B,QAAO;EAAE,MANP,OAAO,GAAM,eAAgB,WACzB,EAAK,cACL,OAAO,GAAM,QAAS,WACpB,EAAK,OACL,EAAO;EAEA,OADD,OAAO,GAAM,SAAU,WAAW,EAAK,QAAQ,KAAA;EACvC;;AAWxB,SAAgB,EAA0B,EACxC,SACA,iBACA,gBACA,cACA,kBACiC;CACjC,IAAM,EAAE,kBAAe,eAAW,uBAAmB,GAAsB,EACrE,EAAE,QAAQ,IAAkB,WAAW,MAAa,GAAoB,EAAY,EACpF,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,IAAc,KAAmB,EAAwB,KAAK,EAC/D,CAAC,GAAO,KAAY,EAAwB,KAAK,EAEjD,EACJ,MAAM,GACN,WAAW,GACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,eAAe,GACf,oBAAoB,GACpB,SAAS,MACP,EAA4B,GAAa,GAAkB,EAAK,EAE9D,EACJ,MAAM,GACN,WAAW,IACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,eAAe,GACf,oBAAoB,MAClB,GAA0B,GAAW,GAAa,GAAkB,EAAK;AAE7E,UAAgB;AAEZ,GAAC,KACD,CAAC,KACD,KACA,MACC,GAAqB,MAAM,UAAU,MAAM,KAKzC,GAA6B;IACjC;EACD;EACA;EACA;EACA;EACA;EACA,GAAqB,MAAM;EAC5B,CAAC;CAEF,IAAM,IAAmB,QACjB,GAAuB,MAAM,SAAS,MAAS,EAAK,MAAM,IAAI,EAAE,EACtE,CAAC,GAAuB,MAAM,CAC/B,EACK,IAAoB,QAEtB,IAAI,IACF,GAAqB,MAAM,SAAS,MAAS,EAAK,MAAM,KAAK,MAAW,EAAO,OAAO,CAAC,IACrF,EAAE,CACL,EACH,CAAC,GAAqB,MAAM,CAC7B,EACK,KAAwB,GAAuB,MAAM,IAAI,SAAS,EAAiB,QACnF,KACH,GAAqB,MAAM,UAAU,MAAM,GACxC,KACJ,CAAC,KAAyB,KAAyB,CAAC,GAMhD,IAA8B,EAJrB,QACP,EAAiB,KAAK,OAAY;EAAE,SAAS,EAAO;EAAQ,WAAW;EAAQ,EAAE,EACvF,CAAC,EAAiB,CACnB,EAC4D;EAC3D;EACA;EACA,OAAO;EACP;EACD,CAAC,EAEI,IAAkB,QAAc;EACpC,IAAM,IAAS,EAAY,MAAM,CAAC,aAAa;AAE/C,SAAO,EAAiB,QAAQ,MAAW;AACzC,OAAI,EAAkB,IAAI,EAAO,OAAO,CACtC,QAAO;AAGT,OAAI,CAAC,EACH,QAAO;GAGT,IAAM,IAAU,EAAW,EAAO;AAClC,OAAI,MACE,EAAQ,YAAY,aAAa,CAAC,SAAS,EAAO,IAClD,EAAQ,OAAO,aAAa,CAAC,SAAS,EAAO,EAAE,QAAO;GAG5D,IAAM,IAAW,EAAmB,EAAO;AAC3C,UACE,EAAS,KAAK,aAAa,CAAC,SAAS,EAAO,IAC5C,EAAS,OAAO,aAAa,CAAC,SAAS,EAAO,IAC9C,EAAO,OAAO,aAAa,CAAC,SAAS,EAAO;IAE9C;IACD;EAAC;EAAmB;EAAY;EAAa;EAAiB,CAAC,EAE5D,MAAmB,MAAmB;AAK1C,EAJK,EAAa,SAAS,EAC3B,EAAgB,EAAO,EACvB,EAAS,KAAK,EAEd,GACE;GAAE;GAAW;GAAQ,EACrB;GACE,iBAAiB;AAGf,IAFK,EAAa,UAAU,EAC5B,EAAgB,KAAK,EACrB,EAAa,GAAM;;GAErB,UAAU,MAAkB;AAG1B,IAFK,EAAa,QAAQ,EAC1B,EAAgB,KAAK,EACrB,EACE,aAAyB,QACrB,EAAc,UACd,kCACL;;GAEJ,CACF;;AAGH,QACE,kBAAC,GAAD;EAAwB;EAAoB;YAC1C,kBAAC,IAAD;GAAyB,WAAU;aAAnC,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAuB,yBAA6C,CAAA,EACpE,kBAAC,GAAD,EAAA,UAAA;IAA6B;IACU,KAAe;IAAe;IAEvC,EAAA,CAAA,CACP,EAAA,CAAA,EAEzB,kBAAC,OAAD;IAAK,WAAU;cAAf;KACG,IACC,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAa,WAAU,mBAAoB,CAAA,EAC3C,kBAAC,QAAD,EAAA,UAAO,GAAa,CAAA,CAChB;UACJ;KAEH,aAA+B,QAC9B,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAa,WAAU,mBAAoB,CAAA,EAC3C,kBAAC,QAAD,EAAA,UAAO,EAAoB,SAAe,CAAA,CACtC;UACJ;KAEH,aAAiC,QAChC,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAa,WAAU,mBAAoB,CAAA,EAC3C,kBAAC,QAAD,EAAA,UAAO,EAAsB,SAAe,CAAA,CACxC;UACN,kBAAC,GAAD;OAAQ,SAAQ;OAAU,eAAe,KAAK,GAAyB;iBAAE;OAEhE,CAAA,CACL;UACJ;KAEJ,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,IAAD,EAAQ,WAAU,yEAA0E,CAAA,EAC5F,kBAAC,GAAD;QACE,OAAO;QACP,WAAW,MAAU,EAAe,EAAM,OAAO,MAAM;QACvD,aAAY;QACZ,WAAU;QACV,UAAU;QACV,CAAA,CACE;UACN,kBAAC,IAAD;OAAO,SAAQ;iBAAf;QACG,IAA0B,GAAG,EAAgB,OAAO,KAAK,EAAgB;QAAQ;QAAI;QAEhF;SACJ;;KAEN,kBAAC,OAAD;MAAK,WAAU;gBACZ,IAA0B,OAAO,KAChC,MACA,MACA,IACA,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MAChC,kBAAC,OAAD;OAAiB,WAAU;iBAA3B,CACE,kBAAC,GAAD,EAAU,WAAU,YAAa,CAAA,EACjC,kBAAC,GAAD,EAAU,WAAU,iBAAkB,CAAA,CAClC;SAHI,EAGJ,CACN,GACA,aAA+B,QAAQ,OAAO,EAAgB,WAAW,IAC3E,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAU,WAAU,8CAA+C,CAAA;QACnE,kBAAC,MAAD;SAAI,WAAU;mBAAwB;SAA8B,CAAA;QACpE,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAG9C,CAAA;QACH,IACC,kBAAC,KAAD;SAAG,WAAU;mBAAb;UAAkD;UAC9B,IAAsC;UAAkB;UAAI;UAE5E;aACF;QACH,IACC,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,GAAD;UACE,SAAQ;UACR,eAAe,KAAK,GAA+B;UACnD,UAAU,KAAsC;oBAE/C,IAAqC,kBAAkB;UACjD,CAAA;SACL,CAAA,GACJ;QACA;WAEN,kBAAA,GAAA,EAAA,UAAA,CACG,EAAgB,KAAK,MAAW;OAC/B,IAAM,IAAU,EAAW,EAAO,SAC5B,IAAW,EAAmB,EAAO,EACrC,IAAe,KAAY,OAAiB,EAAO;AAEzD,cACE,kBAAC,OAAD;QAEE,WAAU;kBAFZ,CAIE,kBAAC,OAAD;SAAK,WAAU;mBACZ,IACC,kBAAC,GAAD;UAAwB;UAAS,SAAQ;UAAS,CAAA,GAElD,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAwB,EAAS;WAAS,CAAA,EACtD,EAAS,QACR,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAS;WACR,CAAA,GAEJ,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAO;WACN,CAAA,CAEF;;SAEJ,CAAA,EAEN,kBAAC,GAAD;SACE,MAAK;SACL,eAAe,GAAgB,EAAO,OAAO;SAC7C,UAAU;mBAHZ,CAKE,kBAAC,GAAD,EAAU,WAAU,eAAgB,CAAA,EACnC,IAAe,cAAc,MACvB;WACL;UA9BC,EAAO,GA8BR;QAER,EAED,IACC,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAb;SAA6C;SAClC,EAAiB;SAAO;SAAK;SAAsB;SAE1D;WACJ,kBAAC,GAAD;QACE,SAAQ;QACR,eAAe,KAAK,GAA+B;QACnD,UAAU,KAAsC;kBAE/C,IAAqC,kBAAkB;QACjD,CAAA,CACL;WACJ,KACH,EAAA,CAAA;MAED,CAAA;KACF;MACkB;;EACT,CAAA"}
@@ -2,7 +2,7 @@ import "./useWorkspaces.js";
2
2
  import "./usePendingInvitations.js";
3
3
  import "./useWorkspaceMembers.js";
4
4
  import "./useMemberMutations.js";
5
- import "./useWorkspaceMutations.js";
6
5
  import "./useProjects.js";
6
+ import "./useWorkspaceMutations.js";
7
7
  import "./useProjectMutations.js";
8
8
  import "./useTenants.js";
@@ -22,7 +22,7 @@ var v = () => {
22
22
  return i.data.addWorkspaceMember;
23
23
  },
24
24
  onSuccess: (e) => {
25
- i.invalidateQueries({ queryKey: ["workspaceMembers", e.workspaceId] }), i.invalidateQueries({ queryKey: ["userWorkspaces"] }), a("workspace-member.added", {
25
+ i.invalidateQueries({ queryKey: ["workspaceMembers", e.workspaceId] }), i.invalidateQueries({ queryKey: ["workspaceMembersInfinite", e.workspaceId] }), i.invalidateQueries({ queryKey: ["userWorkspaces"] }), a("workspace-member.added", {
26
26
  memberId: e.id,
27
27
  workspaceId: e.workspaceId,
28
28
  userId: e.userId,
@@ -54,7 +54,7 @@ var v = () => {
54
54
  return t.data.removeWorkspaceMember;
55
55
  },
56
56
  onSuccess: (e, t) => {
57
- i.invalidateQueries({ queryKey: ["workspaceMembers"] }), i.invalidateQueries({ queryKey: ["userWorkspaces"] }), a("workspace-member.removed", {
57
+ i.invalidateQueries({ queryKey: ["workspaceMembers"] }), i.invalidateQueries({ queryKey: ["workspaceMembersInfinite"] }), i.invalidateQueries({ queryKey: ["userWorkspaces"] }), a("workspace-member.removed", {
58
58
  memberId: t,
59
59
  source: "microfe-workspaces"
60
60
  });
@@ -84,7 +84,7 @@ var v = () => {
84
84
  return t.data.removeUserFromWorkspace;
85
85
  },
86
86
  onSuccess: (e, t) => {
87
- i.invalidateQueries({ queryKey: ["workspaceMembers"] }), i.invalidateQueries({ queryKey: ["userWorkspaces", t] }), a("workspace-member.removed", {
87
+ i.invalidateQueries({ queryKey: ["workspaceMembers"] }), i.invalidateQueries({ queryKey: ["workspaceMembersInfinite"] }), i.invalidateQueries({ queryKey: ["userWorkspaces", t] }), a("workspace-member.removed", {
88
88
  userId: t,
89
89
  source: "microfe-workspaces"
90
90
  });
@@ -227,32 +227,32 @@ var v = () => {
227
227
  });
228
228
  }
229
229
  });
230
- }, T = () => {
231
- let { authToken: t, workspaceId: n } = e(), r = h(), { emit: a } = f();
230
+ }, T = (t) => {
231
+ let { authToken: n, workspaceId: r } = e(), a = h(), { emit: o } = f(), s = t || r;
232
232
  return m({
233
233
  mutationFn: async (e) => {
234
- let r = await _({
234
+ let t = await _({
235
235
  gateway: "workspace",
236
- authToken: t || void 0,
236
+ authToken: n || void 0,
237
237
  query: g(i),
238
238
  variables: { id: e },
239
- workspaceId: n || void 0,
239
+ workspaceId: s || void 0,
240
240
  workspaceToken: !0
241
241
  });
242
- if (r.errors?.length) throw Error(r.errors[0]?.message || "GraphQL error");
243
- return r.data.cancelInvitation;
242
+ if (t.errors?.length) throw Error(t.errors[0]?.message || "GraphQL error");
243
+ return t.data.cancelInvitation;
244
244
  },
245
245
  onSuccess: (e) => {
246
- r.invalidateQueries({ queryKey: ["workspaceInvitations"] }), a("workspace-invitation.cancelled", {
246
+ a.invalidateQueries({ queryKey: ["workspaceInvitations"] }), o("workspace-invitation.cancelled", {
247
247
  invitationId: e.id,
248
248
  workspaceId: e.workspaceId,
249
249
  source: "microfe-workspaces"
250
250
  });
251
251
  },
252
252
  onError: (e, t) => {
253
- a("workspace-invitation.cancel_failed", {
253
+ o("workspace-invitation.cancel_failed", {
254
254
  invitationId: t,
255
- workspaceId: n || void 0,
255
+ workspaceId: s || void 0,
256
256
  source: "microfe-workspaces",
257
257
  errorMessage: p(e)
258
258
  });
@@ -1 +1 @@
1
- {"version":3,"file":"useMemberMutations.js","names":[],"sources":["../../src/hooks/useMemberMutations.ts"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n AddWorkspaceMemberDocument,\n RemoveWorkspaceMemberDocument,\n RemoveUserFromWorkspaceDocument,\n CreateInvitationDocument,\n UpdateInvitationDocument,\n AcceptInvitationDocument,\n RejectInvitationDocument,\n CancelInvitationDocument,\n ResendInvitationDocument,\n DeleteInvitationDocument,\n BulkCreateInvitationsDocument,\n} from '../generated/wspace-operations';\nimport type {\n WorkspaceMember,\n WorkspaceInvitation,\n AddWorkspaceMemberInput,\n CreateInvitationInput,\n UpdateInvitationInput,\n} from '../types';\nimport { useWorkspacesEventEmitter } from './useWorkspacesEventEmitter';\nimport { safeTelemetryError } from '../utils/telemetryError';\n\n/**\n * Hook to add a member to a workspace\n * Requires x-workspace-id header for workspace context\n */\nexport const useAddWorkspaceMember = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (input: AddWorkspaceMemberInput): Promise<WorkspaceMember> => {\n const result = await graphqlFetch<{ addWorkspaceMember: WorkspaceMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(AddWorkspaceMemberDocument),\n variables: { input },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.addWorkspaceMember;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers', data.workspaceId] });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces'] });\n emit('workspace-member.added', {\n memberId: data.id,\n workspaceId: data.workspaceId,\n userId: data.userId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, input) => {\n emit('workspace-member.add_failed', {\n workspaceId: workspaceId || undefined,\n userId: input?.userId,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to remove a member from a workspace by member ID\n */\nexport const useRemoveWorkspaceMember = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (id: string): Promise<boolean> => {\n const result = await graphqlFetch<{ removeWorkspaceMember: boolean }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(RemoveWorkspaceMemberDocument),\n variables: { id },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.removeWorkspaceMember;\n },\n onSuccess: (_, id) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers'] });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces'] });\n emit('workspace-member.removed', { memberId: id, source: 'microfe-workspaces' });\n },\n onError: (err, id) => {\n emit('workspace-member.remove_failed', {\n memberId: id,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to remove a user from a workspace\n * Requires x-workspace-id header for workspace context\n */\nexport const useRemoveUserFromWorkspace = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (userId: string): Promise<boolean> => {\n const result = await graphqlFetch<{ removeUserFromWorkspace: boolean }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(RemoveUserFromWorkspaceDocument),\n variables: { userId },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.removeUserFromWorkspace;\n },\n onSuccess: (_, userId) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers'] });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces', userId] });\n emit('workspace-member.removed', { userId, source: 'microfe-workspaces' });\n },\n onError: (err, userId) => {\n emit('workspace-member.remove_failed', {\n userId,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * NOTE: The updateWorkspaceMemberRoles mutation has been removed from the backend.\n * Role management is now handled via invitations - when creating an invitation,\n * you can specify roleIds that will be assigned when the invitation is accepted.\n *\n * Use CreateInvitationInput.roleIds to assign roles to new members.\n */\n\n/**\n * Hook to create a workspace invitation\n * Uses x-workspace-id header as fallback when input.workspaceId is not provided\n */\nexport const useCreateInvitation = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (input: CreateInvitationInput): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ createInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(CreateInvitationDocument),\n variables: { input },\n workspaceId: input.workspaceId || effectiveWorkspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header fallback\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.createInvitation;\n },\n onSuccess: (data) => {\n const wsId = data.workspaceId ?? effectiveWorkspaceId;\n if (wsId) {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations', wsId] });\n }\n emit('workspace-invitation.created', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n email: data.email,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, input) => {\n emit('workspace-invitation.create_failed', {\n workspaceId: input?.workspaceId || effectiveWorkspaceId || undefined,\n email: input?.email,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to update an invitation\n */\nexport const useUpdateInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async ({\n id,\n input,\n }: {\n id: string;\n input: UpdateInvitationInput;\n }): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ updateInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(UpdateInvitationDocument),\n variables: { id, input },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.updateInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.updated', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, variables) => {\n emit('workspace-invitation.update_failed', {\n invitationId: variables?.id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to accept an invitation\n */\nexport const useAcceptInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ acceptInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(AcceptInvitationDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.acceptInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n queryClient.invalidateQueries({ queryKey: ['myPendingInvitations'] });\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers'] });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces'] });\n queryClient.invalidateQueries({ queryKey: ['myWorkspaces'] });\n emit('workspace-invitation.accepted', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.accept_failed', {\n invitationId: id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to reject an invitation\n */\nexport const useRejectInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ rejectInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(RejectInvitationDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.rejectInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n queryClient.invalidateQueries({ queryKey: ['myPendingInvitations'] });\n emit('workspace-invitation.rejected', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.reject_failed', {\n invitationId: id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to cancel an invitation\n */\nexport const useCancelInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ cancelInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(CancelInvitationDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.cancelInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.cancelled', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.cancel_failed', {\n invitationId: id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to resend an invitation\n */\nexport const useResendInvitation = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ resendInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(ResendInvitationDocument),\n variables: { id },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.resendInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.resent', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.resend_failed', {\n invitationId: id,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to delete an invitation\n */\nexport const useDeleteInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (id: string): Promise<boolean> => {\n const result = await graphqlFetch<{ deleteInvitation: boolean }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(DeleteInvitationDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.deleteInvitation;\n },\n onSuccess: (_, id) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.deleted', { invitationId: id, source: 'microfe-workspaces' });\n },\n onError: (err, id) => {\n emit('workspace-invitation.delete_failed', {\n invitationId: id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to bulk create invitations\n * Uses x-workspace-id header as fallback when inputs[].workspaceId is not provided\n */\nexport const useBulkCreateInvitations = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (inputs: CreateInvitationInput[]): Promise<WorkspaceInvitation[]> => {\n const result = await graphqlFetch<{ bulkCreateInvitations: WorkspaceInvitation[] }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(BulkCreateInvitationsDocument),\n variables: { inputs },\n workspaceId: inputs[0]?.workspaceId || workspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header fallback\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.bulkCreateInvitations;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n },\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useMemberMutations.js","names":[],"sources":["../../src/hooks/useMemberMutations.ts"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n AddWorkspaceMemberDocument,\n RemoveWorkspaceMemberDocument,\n RemoveUserFromWorkspaceDocument,\n CreateInvitationDocument,\n UpdateInvitationDocument,\n AcceptInvitationDocument,\n RejectInvitationDocument,\n CancelInvitationDocument,\n ResendInvitationDocument,\n DeleteInvitationDocument,\n BulkCreateInvitationsDocument,\n} from '../generated/wspace-operations';\nimport type {\n WorkspaceMember,\n WorkspaceInvitation,\n AddWorkspaceMemberInput,\n CreateInvitationInput,\n UpdateInvitationInput,\n} from '../types';\nimport { useWorkspacesEventEmitter } from './useWorkspacesEventEmitter';\nimport { safeTelemetryError } from '../utils/telemetryError';\n\n/**\n * Hook to add a member to a workspace\n * Requires x-workspace-id header for workspace context\n */\nexport const useAddWorkspaceMember = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (input: AddWorkspaceMemberInput): Promise<WorkspaceMember> => {\n const result = await graphqlFetch<{ addWorkspaceMember: WorkspaceMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(AddWorkspaceMemberDocument),\n variables: { input },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.addWorkspaceMember;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers', data.workspaceId] });\n queryClient.invalidateQueries({\n queryKey: ['workspaceMembersInfinite', data.workspaceId],\n });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces'] });\n emit('workspace-member.added', {\n memberId: data.id,\n workspaceId: data.workspaceId,\n userId: data.userId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, input) => {\n emit('workspace-member.add_failed', {\n workspaceId: workspaceId || undefined,\n userId: input?.userId,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to remove a member from a workspace by member ID\n */\nexport const useRemoveWorkspaceMember = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (id: string): Promise<boolean> => {\n const result = await graphqlFetch<{ removeWorkspaceMember: boolean }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(RemoveWorkspaceMemberDocument),\n variables: { id },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.removeWorkspaceMember;\n },\n onSuccess: (_, id) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers'] });\n queryClient.invalidateQueries({ queryKey: ['workspaceMembersInfinite'] });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces'] });\n emit('workspace-member.removed', { memberId: id, source: 'microfe-workspaces' });\n },\n onError: (err, id) => {\n emit('workspace-member.remove_failed', {\n memberId: id,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to remove a user from a workspace\n * Requires x-workspace-id header for workspace context\n */\nexport const useRemoveUserFromWorkspace = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (userId: string): Promise<boolean> => {\n const result = await graphqlFetch<{ removeUserFromWorkspace: boolean }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(RemoveUserFromWorkspaceDocument),\n variables: { userId },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.removeUserFromWorkspace;\n },\n onSuccess: (_, userId) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers'] });\n queryClient.invalidateQueries({ queryKey: ['workspaceMembersInfinite'] });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces', userId] });\n emit('workspace-member.removed', { userId, source: 'microfe-workspaces' });\n },\n onError: (err, userId) => {\n emit('workspace-member.remove_failed', {\n userId,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * NOTE: The updateWorkspaceMemberRoles mutation has been removed from the backend.\n * Role management is now handled via invitations - when creating an invitation,\n * you can specify roleIds that will be assigned when the invitation is accepted.\n *\n * Use CreateInvitationInput.roleIds to assign roles to new members.\n */\n\n/**\n * Hook to create a workspace invitation\n * Uses x-workspace-id header as fallback when input.workspaceId is not provided\n */\nexport const useCreateInvitation = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (input: CreateInvitationInput): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ createInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(CreateInvitationDocument),\n variables: { input },\n workspaceId: input.workspaceId || effectiveWorkspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header fallback\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.createInvitation;\n },\n onSuccess: (data) => {\n const wsId = data.workspaceId ?? effectiveWorkspaceId;\n if (wsId) {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations', wsId] });\n }\n emit('workspace-invitation.created', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n email: data.email,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, input) => {\n emit('workspace-invitation.create_failed', {\n workspaceId: input?.workspaceId || effectiveWorkspaceId || undefined,\n email: input?.email,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to update an invitation\n */\nexport const useUpdateInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async ({\n id,\n input,\n }: {\n id: string;\n input: UpdateInvitationInput;\n }): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ updateInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(UpdateInvitationDocument),\n variables: { id, input },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.updateInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.updated', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, variables) => {\n emit('workspace-invitation.update_failed', {\n invitationId: variables?.id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to accept an invitation\n */\nexport const useAcceptInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ acceptInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(AcceptInvitationDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.acceptInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n queryClient.invalidateQueries({ queryKey: ['myPendingInvitations'] });\n queryClient.invalidateQueries({ queryKey: ['workspaceMembers'] });\n queryClient.invalidateQueries({ queryKey: ['userWorkspaces'] });\n queryClient.invalidateQueries({ queryKey: ['myWorkspaces'] });\n emit('workspace-invitation.accepted', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.accept_failed', {\n invitationId: id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to reject an invitation\n */\nexport const useRejectInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ rejectInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(RejectInvitationDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.rejectInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n queryClient.invalidateQueries({ queryKey: ['myPendingInvitations'] });\n emit('workspace-invitation.rejected', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.reject_failed', {\n invitationId: id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to cancel an invitation\n */\nexport const useCancelInvitation = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ cancelInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(CancelInvitationDocument),\n variables: { id },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.cancelInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.cancelled', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.cancel_failed', {\n invitationId: id,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to resend an invitation\n */\nexport const useResendInvitation = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (id: string): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ resendInvitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(ResendInvitationDocument),\n variables: { id },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.resendInvitation;\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.resent', {\n invitationId: data.id,\n workspaceId: data.workspaceId,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, id) => {\n emit('workspace-invitation.resend_failed', {\n invitationId: id,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to delete an invitation\n */\nexport const useDeleteInvitation = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n\n return useMutation({\n mutationFn: async (id: string): Promise<boolean> => {\n const result = await graphqlFetch<{ deleteInvitation: boolean }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(DeleteInvitationDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.deleteInvitation;\n },\n onSuccess: (_, id) => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n emit('workspace-invitation.deleted', { invitationId: id, source: 'microfe-workspaces' });\n },\n onError: (err, id) => {\n emit('workspace-invitation.delete_failed', {\n invitationId: id,\n workspaceId: workspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\n/**\n * Hook to bulk create invitations\n * Uses x-workspace-id header as fallback when inputs[].workspaceId is not provided\n */\nexport const useBulkCreateInvitations = () => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (inputs: CreateInvitationInput[]): Promise<WorkspaceInvitation[]> => {\n const result = await graphqlFetch<{ bulkCreateInvitations: WorkspaceInvitation[] }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(BulkCreateInvitationsDocument),\n variables: { inputs },\n workspaceId: inputs[0]?.workspaceId || workspaceId || undefined,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header fallback\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.bulkCreateInvitations;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['workspaceInvitations'] });\n },\n });\n};\n"],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ import { useWorkspacesContext as e } from "../providers/WorkspacesProvider.js";
2
+ import { useWorkspacesEventEmitter as t } from "./useWorkspacesEventEmitter.js";
3
+ import { safeTelemetryError as n } from "../utils/telemetryError.js";
4
+ import { useMutation as r, useQueryClient as i } from "@tanstack/react-query";
5
+ import { graphqlFetch as a } from "@burdenoff/fe-libs/shared/graphql";
6
+ //#region src/hooks/useProjectMemberMutations.ts
7
+ var o = "\n mutation AddProjectMember($input: AddProjectMemberInput!) {\n addProjectMember(input: $input) {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n }\n", s = "\n mutation RemoveProjectMember($input: RemoveProjectMemberInput!) {\n removeProjectMember(input: $input)\n }\n", c = (s) => {
8
+ let { authToken: c, workspaceId: l } = e(), u = i(), { emit: d } = t(), f = s || l;
9
+ return r({
10
+ mutationFn: async (e) => {
11
+ let t = await a({
12
+ gateway: "workspace",
13
+ authToken: c || void 0,
14
+ query: o,
15
+ variables: { input: e },
16
+ workspaceId: f || void 0,
17
+ workspaceToken: !0
18
+ });
19
+ if (t.errors?.length) throw Error(t.errors[0]?.message || "GraphQL error");
20
+ if (!t.data?.addProjectMember) throw Error("No data returned from addProjectMember mutation");
21
+ return t.data.addProjectMember;
22
+ },
23
+ onSuccess: (e, t) => {
24
+ u.invalidateQueries({ queryKey: [
25
+ "projectMembers",
26
+ f,
27
+ t.projectId
28
+ ] }), u.invalidateQueries({ queryKey: [
29
+ "projectMembersInfinite",
30
+ f,
31
+ t.projectId
32
+ ] }), u.invalidateQueries({ queryKey: [
33
+ "projectMembersCount",
34
+ f,
35
+ t.projectId
36
+ ] }), d("project-member.added", {
37
+ memberId: e.id,
38
+ projectId: t.projectId,
39
+ userId: t.userId,
40
+ workspaceId: f || void 0,
41
+ source: "microfe-workspaces"
42
+ });
43
+ },
44
+ onError: (e, t) => {
45
+ d("project-member.add_failed", {
46
+ projectId: t?.projectId,
47
+ userId: t?.userId,
48
+ workspaceId: f || void 0,
49
+ source: "microfe-workspaces",
50
+ errorMessage: n(e)
51
+ });
52
+ }
53
+ });
54
+ }, l = (o) => {
55
+ let { authToken: c, workspaceId: l } = e(), u = i(), { emit: d } = t(), f = o || l;
56
+ return r({
57
+ mutationFn: async (e) => {
58
+ let t = await a({
59
+ gateway: "workspace",
60
+ authToken: c || void 0,
61
+ query: s,
62
+ variables: { input: e },
63
+ workspaceId: f || void 0,
64
+ workspaceToken: !0
65
+ });
66
+ if (t.errors?.length) throw Error(t.errors[0]?.message || "GraphQL error");
67
+ if (typeof t.data?.removeProjectMember != "boolean") throw Error("No data returned from removeProjectMember mutation");
68
+ return t.data.removeProjectMember;
69
+ },
70
+ onSuccess: (e, t) => {
71
+ u.invalidateQueries({ queryKey: [
72
+ "projectMembers",
73
+ f,
74
+ t.projectId
75
+ ] }), u.invalidateQueries({ queryKey: [
76
+ "projectMembersInfinite",
77
+ f,
78
+ t.projectId
79
+ ] }), u.invalidateQueries({ queryKey: [
80
+ "projectMembersCount",
81
+ f,
82
+ t.projectId
83
+ ] }), d("project-member.removed", {
84
+ projectId: t.projectId,
85
+ userId: t.userId,
86
+ workspaceId: f || void 0,
87
+ source: "microfe-workspaces"
88
+ });
89
+ },
90
+ onError: (e, t) => {
91
+ d("project-member.remove_failed", {
92
+ projectId: t?.projectId,
93
+ userId: t?.userId,
94
+ workspaceId: f || void 0,
95
+ source: "microfe-workspaces",
96
+ errorMessage: n(e)
97
+ });
98
+ }
99
+ });
100
+ };
101
+ //#endregion
102
+ export { c as useAddProjectMember, l as useRemoveProjectMember };
103
+
104
+ //# sourceMappingURL=useProjectMemberMutations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useProjectMemberMutations.js","names":[],"sources":["../../src/hooks/useProjectMemberMutations.ts"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport type { AddProjectMemberInput, ProjectMember, RemoveProjectMemberInput } from '../types';\nimport { safeTelemetryError } from '../utils/telemetryError';\nimport { useWorkspacesEventEmitter } from './useWorkspacesEventEmitter';\n\nconst ADD_PROJECT_MEMBER_MUTATION = `\n mutation AddProjectMember($input: AddProjectMemberInput!) {\n addProjectMember(input: $input) {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n }\n`;\n\nconst REMOVE_PROJECT_MEMBER_MUTATION = `\n mutation RemoveProjectMember($input: RemoveProjectMemberInput!) {\n removeProjectMember(input: $input)\n }\n`;\n\nexport const useAddProjectMember = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (input: AddProjectMemberInput): Promise<ProjectMember> => {\n const result = await graphqlFetch<{ addProjectMember: ProjectMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: ADD_PROJECT_MEMBER_MUTATION,\n variables: { input },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.addProjectMember) {\n throw new Error('No data returned from addProjectMember mutation');\n }\n\n return result.data.addProjectMember;\n },\n onSuccess: (data, input) => {\n queryClient.invalidateQueries({\n queryKey: ['projectMembers', effectiveWorkspaceId, input.projectId],\n });\n queryClient.invalidateQueries({\n queryKey: ['projectMembersInfinite', effectiveWorkspaceId, input.projectId],\n });\n queryClient.invalidateQueries({\n queryKey: ['projectMembersCount', effectiveWorkspaceId, input.projectId],\n });\n emit('project-member.added', {\n memberId: data.id,\n projectId: input.projectId,\n userId: input.userId,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, input) => {\n emit('project-member.add_failed', {\n projectId: input?.projectId,\n userId: input?.userId,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n\nexport const useRemoveProjectMember = (workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const queryClient = useQueryClient();\n const { emit } = useWorkspacesEventEmitter();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useMutation({\n mutationFn: async (input: RemoveProjectMemberInput): Promise<boolean> => {\n const result = await graphqlFetch<{ removeProjectMember: boolean }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: REMOVE_PROJECT_MEMBER_MUTATION,\n variables: { input },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (typeof result.data?.removeProjectMember !== 'boolean') {\n throw new Error('No data returned from removeProjectMember mutation');\n }\n\n return result.data.removeProjectMember;\n },\n onSuccess: (_, input) => {\n queryClient.invalidateQueries({\n queryKey: ['projectMembers', effectiveWorkspaceId, input.projectId],\n });\n queryClient.invalidateQueries({\n queryKey: ['projectMembersInfinite', effectiveWorkspaceId, input.projectId],\n });\n queryClient.invalidateQueries({\n queryKey: ['projectMembersCount', effectiveWorkspaceId, input.projectId],\n });\n emit('project-member.removed', {\n projectId: input.projectId,\n userId: input.userId,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n });\n },\n onError: (err, input) => {\n emit('project-member.remove_failed', {\n projectId: input?.projectId,\n userId: input?.userId,\n workspaceId: effectiveWorkspaceId || undefined,\n source: 'microfe-workspaces',\n errorMessage: safeTelemetryError(err),\n });\n },\n });\n};\n"],"mappings":";;;;;;AAOA,IAAM,IAA8B,oNAa9B,IAAiC,wHAM1B,KAAuB,MAAiC;CACnE,IAAM,EAAE,cAAW,mBAAgB,GAAsB,EACnD,IAAc,GAAgB,EAC9B,EAAE,YAAS,GAA2B,EACtC,IAAuB,KAAuB;AAEpD,QAAO,EAAY;EACjB,YAAY,OAAO,MAAyD;GAC1E,IAAM,IAAS,MAAM,EAAkD;IACrE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO;IACP,WAAW,EAAE,UAAO;IACpB,aAAa,KAAwB,KAAA;IACrC,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,OAAI,CAAC,EAAO,MAAM,iBAChB,OAAU,MAAM,kDAAkD;AAGpE,UAAO,EAAO,KAAK;;EAErB,YAAY,GAAM,MAAU;AAU1B,GATA,EAAY,kBAAkB,EAC5B,UAAU;IAAC;IAAkB;IAAsB,EAAM;IAAU,EACpE,CAAC,EACF,EAAY,kBAAkB,EAC5B,UAAU;IAAC;IAA0B;IAAsB,EAAM;IAAU,EAC5E,CAAC,EACF,EAAY,kBAAkB,EAC5B,UAAU;IAAC;IAAuB;IAAsB,EAAM;IAAU,EACzE,CAAC,EACF,EAAK,wBAAwB;IAC3B,UAAU,EAAK;IACf,WAAW,EAAM;IACjB,QAAQ,EAAM;IACd,aAAa,KAAwB,KAAA;IACrC,QAAQ;IACT,CAAC;;EAEJ,UAAU,GAAK,MAAU;AACvB,KAAK,6BAA6B;IAChC,WAAW,GAAO;IAClB,QAAQ,GAAO;IACf,aAAa,KAAwB,KAAA;IACrC,QAAQ;IACR,cAAc,EAAmB,EAAI;IACtC,CAAC;;EAEL,CAAC;GAGS,KAA0B,MAAiC;CACtE,IAAM,EAAE,cAAW,mBAAgB,GAAsB,EACnD,IAAc,GAAgB,EAC9B,EAAE,YAAS,GAA2B,EACtC,IAAuB,KAAuB;AAEpD,QAAO,EAAY;EACjB,YAAY,OAAO,MAAsD;GACvE,IAAM,IAAS,MAAM,EAA+C;IAClE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO;IACP,WAAW,EAAE,UAAO;IACpB,aAAa,KAAwB,KAAA;IACrC,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,OAAI,OAAO,EAAO,MAAM,uBAAwB,UAC9C,OAAU,MAAM,qDAAqD;AAGvE,UAAO,EAAO,KAAK;;EAErB,YAAY,GAAG,MAAU;AAUvB,GATA,EAAY,kBAAkB,EAC5B,UAAU;IAAC;IAAkB;IAAsB,EAAM;IAAU,EACpE,CAAC,EACF,EAAY,kBAAkB,EAC5B,UAAU;IAAC;IAA0B;IAAsB,EAAM;IAAU,EAC5E,CAAC,EACF,EAAY,kBAAkB,EAC5B,UAAU;IAAC;IAAuB;IAAsB,EAAM;IAAU,EACzE,CAAC,EACF,EAAK,0BAA0B;IAC7B,WAAW,EAAM;IACjB,QAAQ,EAAM;IACd,aAAa,KAAwB,KAAA;IACrC,QAAQ;IACT,CAAC;;EAEJ,UAAU,GAAK,MAAU;AACvB,KAAK,gCAAgC;IACnC,WAAW,GAAO;IAClB,QAAQ,GAAO;IACf,aAAa,KAAwB,KAAA;IACrC,QAAQ;IACR,cAAc,EAAmB,EAAI;IACtC,CAAC;;EAEL,CAAC"}