feat: Toggle to hide Team Profile link on Booker (#20369)

* hide team profile link on booker

* fix ts errors

---------

Co-authored-by: amrit <iamamrit27@gmail.com>
This commit is contained in:
Hariom Balhara
2025-03-27 15:00:35 +00:00
committed by GitHub
co-authored by amrit
parent ea250febbc
commit 2aa583bb6d
9 changed files with 29 additions and 3 deletions
@@ -3038,6 +3038,8 @@
"tip_username_plus": "Tip: You can a '+' between usernames: cal.com/anna+brian to make a dynamic group meeting",
"user_has_no_team_yet": "You don't have a team yet",
"no_team_members": "You don't have team members yet",
"hide_team_profile_link": "Hide Team Profile Link",
"hide_team_profile_link_description": "Hide the team profile link on booking pages",
"display": "Display",
"could_not_find_slug_to_publish_org": "Could not find slug to publish the organization",
"picklist": "Picklist",
@@ -47,7 +47,7 @@ export const EventMembers = ({
{
// We don't want booker to be able to see the list of other users or teams inside the embed
href:
isEmbed || isPlatform || isPrivateLink
isEmbed || isPlatform || isPrivateLink || entity.hideProfileLink
? null
: entity.teamSlug
? getTeamUrlSync({ orgSlug: entity.orgSlug, teamSlug: entity.teamSlug })
@@ -67,7 +67,7 @@ export const EventMembers = ({
...orgOrTeamAvatarItem,
...shownUsers.map((user) => ({
href:
isPlatform || isPrivateLink
isPlatform || isPrivateLink || entity.hideProfileLink
? null
: `${getBookerBaseUrlSync(user.profile?.organization?.slug ?? null)}/${
user.profile?.username
@@ -14,9 +14,9 @@ import { useParamsWithFallback } from "@calcom/lib/hooks/useParamsWithFallback";
import { MembershipRole } from "@calcom/prisma/enums";
import { trpc } from "@calcom/trpc/react";
import type { RouterOutputs } from "@calcom/trpc/react";
import { Button } from "@calcom/ui/components/button";
import { Form } from "@calcom/ui/components/form";
import { SettingsToggle } from "@calcom/ui/components/form";
import { Button } from "@calcom/ui/components/button";
import { showToast } from "@calcom/ui/components/toast";
import ThemeLabel from "../../../settings/ThemeLabel";
@@ -34,6 +34,7 @@ const ProfileView = ({ team }: ProfileViewProps) => {
const [hideBrandingValue, setHideBrandingValue] = useState(team?.hideBranding ?? false);
const [hideBookATeamMember, setHideBookATeamMember] = useState(team?.hideBookATeamMember ?? false);
const [hideTeamProfileLink, setHideTeamProfileLink] = useState(team?.hideTeamProfileLink ?? false);
const themeForm = useForm<{ theme: string | null | undefined }>({
defaultValues: {
@@ -168,6 +169,18 @@ const ProfileView = ({ team }: ProfileViewProps) => {
mutation.mutate({ id: team.id, hideBookATeamMember: checked });
}}
/>
<SettingsToggle
toggleSwitchAtTheEnd={true}
title={t("hide_team_profile_link")}
disabled={mutation?.isPending}
description={t("hide_team_profile_link_description")}
checked={hideTeamProfileLink ?? false}
onCheckedChange={(checked) => {
setHideTeamProfileLink(checked);
mutation.mutate({ id: team.id, hideTeamProfileLink: checked });
}}
/>
</div>
</>
) : (
@@ -94,6 +94,7 @@ const getPublicEventSelect = (fetchAllUsers: boolean) => {
name: true,
logoUrl: true,
theme: true,
hideTeamProfileLink: true,
parent: {
select: {
slug: true,
@@ -309,6 +310,7 @@ export const getPublicEvent = async (
name: unPublishedOrgUser?.profile?.organization?.name ?? null,
teamSlug: null,
logoUrl: null,
hideProfileLink: false,
},
isInstantEvent: false,
instantMeetingParameters: [],
@@ -470,6 +472,7 @@ export const getPublicEvent = async (
if (event.team?.isPrivate && !isTeamAdminOrOwner && !isOrgAdminOrOwner) {
users = [];
}
return {
...eventWithUserProfiles,
bookerLayouts: bookerLayoutsSchema.parse(eventMetaData?.bookerLayouts || null),
@@ -499,6 +502,7 @@ export const getPublicEvent = async (
eventWithUserProfiles.team?.parent?.name ||
eventWithUserProfiles.team?.name) ??
null,
hideProfileLink: eventWithUserProfiles.team?.hideTeamProfileLink ?? false,
...(orgDetails
? {
logoUrl: getPlaceholderAvatar(orgDetails?.logoUrl, orgDetails?.name),
@@ -310,6 +310,7 @@ export async function getTeamWithoutMembers(args: {
bio: true,
hideBranding: true,
hideBookATeamMember: true,
hideTeamProfileLink: true,
isPrivate: true,
metadata: true,
bookingLimits: true,
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Team" ADD COLUMN "hideTeamProfileLink" BOOLEAN NOT NULL DEFAULT false;
+1
View File
@@ -440,6 +440,7 @@ model Team {
appIconLogo String?
bio String?
hideBranding Boolean @default(false)
hideTeamProfileLink Boolean @default(false)
isPrivate Boolean @default(false)
hideBookATeamMember Boolean @default(false)
members Membership[]
@@ -60,6 +60,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
hideBranding: input.hideBranding,
isPrivate: input.isPrivate,
hideBookATeamMember: input.hideBookATeamMember,
hideTeamProfileLink: input.hideTeamProfileLink,
brandColor: input.brandColor,
darkBrandColor: input.darkBrandColor,
theme: input.theme,
@@ -13,6 +13,7 @@ export type TUpdateInputSchema = {
slug?: string;
hideBranding?: boolean;
hideBookATeamMember?: boolean;
hideTeamProfileLink?: boolean;
isPrivate?: boolean;
brandColor?: string;
darkBrandColor?: string;
@@ -37,6 +38,7 @@ export const ZUpdateInputSchema: z.Schema<TUpdateInputSchema> = z.object({
.optional(),
hideBranding: z.boolean().optional(),
hideBookATeamMember: z.boolean().optional(),
hideTeamProfileLink: z.boolean().optional(),
isPrivate: z.boolean().optional(),
brandColor: z.string().optional(),
darkBrandColor: z.string().optional(),