diff --git a/apps/web/pages/team/[slug].tsx b/apps/web/pages/team/[slug].tsx index a168a56c43..5250faf3ed 100644 --- a/apps/web/pages/team/[slug].tsx +++ b/apps/web/pages/team/[slug].tsx @@ -187,7 +187,7 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain } {!isBioEmpty && ( <>
@@ -197,21 +197,26 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain } ) : ( <> - {(showMembers.isOn || !team.eventTypes.length) && } + {(showMembers.isOn || !team.eventTypes.length) && + (team.isPrivate ? ( +
+

{t("you_cannot_see_team_members")}

+
+ ) : ( + + ))} {!showMembers.isOn && team.eventTypes.length > 0 && (
- {!team.hideBookATeamMember && ( + {!(team.hideBookATeamMember || team.isPrivate) && (
diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 41fcac295c..ece4273076 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -1003,6 +1003,9 @@ "user_impersonation_heading": "User Impersonation", "user_impersonation_description": "Allows our support team to temporarily sign in as you to help us quickly resolve any issues you report to us.", "team_impersonation_description": "Allows your team Owners/Admins to temporarily sign in as you.", + "make_team_private": "Make team private", + "make_team_private_description": "Your team members won't be able to see other team members when this is turned on.", + "you_cannot_see_team_members": "You cannot see all the team members of a private team.", "allow_booker_to_select_duration": "Allow booker to select duration", "impersonate_user_tip": "All uses of this feature is audited.", "impersonating_user_warning": "Impersonating username \"{{user}}\".", diff --git a/packages/features/ee/teams/components/MakeTeamPrivateSwitch.tsx b/packages/features/ee/teams/components/MakeTeamPrivateSwitch.tsx new file mode 100644 index 0000000000..e36a989126 --- /dev/null +++ b/packages/features/ee/teams/components/MakeTeamPrivateSwitch.tsx @@ -0,0 +1,60 @@ +import { classNames } from "@calcom/lib"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; +import { trpc } from "@calcom/trpc/react"; +import { showToast, Switch } from "@calcom/ui"; + +const MakeTeamPrivateSwitch = ({ + teamId, + isPrivate, + disabled, +}: { + teamId: number; + isPrivate: boolean; + disabled: boolean; +}) => { + const { t } = useLocale(); + + const utils = trpc.useContext(); + + const mutation = trpc.viewer.teams.update.useMutation({ + onError: (err) => { + showToast(err.message, "error"); + }, + async onSuccess() { + await utils.viewer.teams.get.invalidate(); + showToast(t("your_team_updated_successfully"), "success"); + }, + }); + + return ( + <> +
+
+
+

+ {t("make_team_private")} +

+
+

+ {t("make_team_private_description")} +

+
+
+ { + mutation.mutate({ id: teamId, isPrivate: isChecked }); + }} + /> +
+
+ + ); +}; + +export default MakeTeamPrivateSwitch; diff --git a/packages/features/ee/teams/pages/team-members-view.tsx b/packages/features/ee/teams/pages/team-members-view.tsx index 24b4095fdd..e938707185 100644 --- a/packages/features/ee/teams/pages/team-members-view.tsx +++ b/packages/features/ee/teams/pages/team-members-view.tsx @@ -12,6 +12,7 @@ import { Plus } from "@calcom/ui/components/icon"; import { getLayout } from "../../../settings/layouts/SettingsLayout"; import DisableTeamImpersonation from "../components/DisableTeamImpersonation"; import InviteLinkSettingsModal from "../components/InviteLinkSettingsModal"; +import MakeTeamPrivateSwitch from "../components/MakeTeamPrivateSwitch"; import MemberInvitationModal from "../components/MemberInvitationModal"; import MemberListItem from "../components/MemberListItem"; import TeamInviteList from "../components/TeamInviteList"; @@ -67,6 +68,7 @@ const MembersView = () => { const router = useRouter(); const session = useSession(); + const utils = trpc.useContext(); const teamId = Number(router.query.id); @@ -132,8 +134,13 @@ const MembersView = () => { )} )} - -
+ + {((team?.isPrivate && isAdmin) || !team?.isPrivate) && ( + <> + +
+ + )} {team && session.data && ( { disabled={isInviteOpen} /> )} -
+ + {team && isAdmin && ( + <> +
+ + + )}
{showMemberInvitationModal && team && ( { logo: input.logo, bio: input.bio, hideBranding: input.hideBranding, + isPrivate: input.isPrivate, hideBookATeamMember: input.hideBookATeamMember, brandColor: input.brandColor, darkBrandColor: input.darkBrandColor, diff --git a/packages/trpc/server/routers/viewer/teams/update.schema.ts b/packages/trpc/server/routers/viewer/teams/update.schema.ts index 3a35131461..7da9261808 100644 --- a/packages/trpc/server/routers/viewer/teams/update.schema.ts +++ b/packages/trpc/server/routers/viewer/teams/update.schema.ts @@ -8,6 +8,7 @@ export const ZUpdateInputSchema = z.object({ slug: z.string().optional(), hideBranding: z.boolean().optional(), hideBookATeamMember: z.boolean().optional(), + isPrivate: z.boolean().optional(), brandColor: z.string().optional(), darkBrandColor: z.string().optional(), theme: z.string().optional().nullable(),