diff --git a/apps/web/src/components/Popup.tsx b/apps/web/src/components/Popup.tsx index 72c8431b..7f46bb65 100644 --- a/apps/web/src/components/Popup.tsx +++ b/apps/web/src/components/Popup.tsx @@ -25,7 +25,7 @@ const Popup: React.FC = () => { return (
{ leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > -
-
+
+
-
+
{popupIcon === "success" && (
-

+

{popupHeader}

-

+

{popupMessage}

-
+
diff --git a/apps/web/src/views/members/index.tsx b/apps/web/src/views/members/index.tsx index a31e62d7..e40d5578 100644 --- a/apps/web/src/views/members/index.tsx +++ b/apps/web/src/views/members/index.tsx @@ -3,6 +3,7 @@ import { t } from "@lingui/core/macro"; import { env } from "next-runtime-env"; import { HiBolt, + HiChevronDown, HiEllipsisHorizontal, HiOutlinePlusSmall, } from "react-icons/hi2"; @@ -19,7 +20,9 @@ import FeedbackModal from "~/components/FeedbackModal"; import Modal from "~/components/modal"; import { NewWorkspaceForm } from "~/components/NewWorkspaceForm"; import { PageHead } from "~/components/PageHead"; +import { usePermissions } from "~/hooks/usePermissions"; import { useModal } from "~/providers/modal"; +import { usePopup } from "~/providers/popup"; import { useWorkspace } from "~/providers/workspace"; import { api } from "~/utils/api"; import { getAvatarUrl } from "~/utils/helpers"; @@ -29,6 +32,7 @@ import { InviteMemberForm } from "./components/InviteMemberForm"; export default function MembersPage() { const { modalContentType, openModal, isOpen } = useModal(); const { workspace } = useWorkspace(); + const { showPopup } = usePopup(); const { data, isLoading } = api.workspace.byId.useQuery( { workspacePublicId: workspace.publicId }, @@ -37,6 +41,31 @@ export default function MembersPage() { const { data: session } = authClient.useSession(); + const { canEditMember } = usePermissions(); + + const utils = api.useUtils(); + + const updateRoleMutation = api.member.updateRole.useMutation({ + onSuccess: async () => { + await utils.workspace.byId.invalidate({ + workspacePublicId: workspace.publicId, + }); + + showPopup({ + header: t`Role updated`, + message: t`The member's role has been updated.`, + icon: "success", + }); + }, + onError: () => { + showPopup({ + header: t`Unable to update role`, + message: t`Please try again later, or contact customer support.`, + icon: "error", + }); + }, + }); + const subscriptions = data?.subscriptions as Subscription[] | undefined; const teamSubscription = getSubscriptionByPlan(subscriptions, "team"); @@ -67,6 +96,16 @@ export default function MembersPage() { showSkeleton?: boolean; showPendingIcon?: boolean; }) => { + const handleRoleChange = (newRole: "admin" | "member" | "guest") => { + if (!memberPublicId) return; + + updateRoleMutation.mutate({ + workspacePublicId: workspace.publicId, + memberPublicId, + role: newRole, + }); + }; + return (
-
- + {showSkeleton ? ( + - {memberRole && - memberRole.charAt(0).toUpperCase() + memberRole.slice(1)} - + )} + /> + ) : ( +
+ + {memberRole && + memberRole.charAt(0).toUpperCase() + + memberRole.slice(1)} + {canEditMember && session?.user.id !== memberId && ( + + )} + + + {canEditMember && session?.user.id !== memberId && ( + + )} +
+ )} {(memberStatus === "invited" || memberStatus === "paused") && ( - + {memberStatus === "invited" ? t`Pending` : t`Paused`} )}