fix: hide team members details when hideOrganizerEmail is enabled (#26833)

* fix: hide organizer email

* update
This commit is contained in:
Anik Dhabal Babu
2026-01-15 09:39:51 +00:00
committed by GitHub
parent 1dd2652080
commit a8d559d331
5 changed files with 118 additions and 37 deletions
+77 -18
View File
@@ -431,6 +431,9 @@ function BookingListItem(booking: BookingItemProps) {
currentEmail={userEmail}
bookingUid={booking.uid}
isBookingInPast={isBookingInPast}
hideOrganizerEmail={booking.eventType?.hideOrganizerEmail}
organizerEmail={booking.user?.email}
eventTypeHosts={booking.eventType?.hosts}
/>
)}
{isCancelled && booking.rescheduled && (
@@ -686,14 +689,20 @@ interface UserProps {
const FirstAttendee = ({
user,
currentEmail,
hideOrganizerEmail,
}: {
user: UserProps;
currentEmail: string | null | undefined;
hideOrganizerEmail?: boolean;
}) => {
const { t } = useLocale();
return user.email === currentEmail ? (
<div className="inline-block">{t("you")}</div>
) : (
if (user.email === currentEmail) {
return <div className="inline-block">{t("you")}</div>;
}
if (hideOrganizerEmail) {
return <span className="inline-block">{user.name || ""}</span>;
}
return (
<a
key={user.email}
className="hover:text-blue-500"
@@ -709,8 +718,26 @@ type NoShowProps = {
isBookingInPast: boolean;
};
const Attendee = (attendeeProps: BookingAttendee & NoShowProps) => {
const { email, name, bookingUid, isBookingInPast, noShow, phoneNumber, user } = attendeeProps;
const Attendee = (
attendeeProps: BookingAttendee &
NoShowProps & {
hideOrganizerEmail?: boolean;
organizerEmail?: string | null;
eventTypeHosts?: Array<{ user: { email: string } | null }> | null;
}
) => {
const {
email,
name,
bookingUid,
isBookingInPast,
noShow,
phoneNumber,
user,
hideOrganizerEmail,
organizerEmail,
eventTypeHosts,
} = attendeeProps;
const { t } = useLocale();
const utils = trpc.useUtils();
@@ -718,17 +745,22 @@ const Attendee = (attendeeProps: BookingAttendee & NoShowProps) => {
const { copyToClipboard, isCopied } = useCopy();
const noShowMutation = trpc.viewer.loggedInViewerRouter.markNoShow.useMutation({
onSuccess: async (data) => {
showToast(data.message, "success");
await utils.viewer.bookings.invalidate();
},
onError: (err) => {
showToast(err.message, "error");
},
});
onSuccess: async (data) => {
showToast(data.message, "success");
await utils.viewer.bookings.invalidate();
},
onError: (err) => {
showToast(err.message, "error");
},
});
const displayName = user?.name || name || user?.email || email;
const isTeamMemberOrHost =
email === organizerEmail ||
eventTypeHosts?.some((host) => host.user?.email === email);
const shouldHideEmail = hideOrganizerEmail && isTeamMemberOrHost;
return (
<Dropdown open={openDropdown} onOpenChange={setOpenDropdown}>
<DropdownMenuTrigger asChild>
@@ -747,7 +779,7 @@ const Attendee = (attendeeProps: BookingAttendee & NoShowProps) => {
</DropdownMenuTrigger>
<DropdownMenuPortal>
<DropdownMenuContent>
{!isSmsCalEmail(email) && (
{!isSmsCalEmail(email) && !shouldHideEmail && (
<DropdownMenuItem className="focus:outline-none">
<DropdownItem
StartIcon="mail"
@@ -993,21 +1025,34 @@ const DisplayAttendees = ({
currentEmail,
bookingUid,
isBookingInPast,
hideOrganizerEmail,
organizerEmail,
eventTypeHosts,
}: {
attendees: BookingAttendee[];
user: UserProps | null;
currentEmail?: string | null;
bookingUid: string;
isBookingInPast: boolean;
hideOrganizerEmail?: boolean;
organizerEmail?: string | null;
eventTypeHosts?: Array<{ user: { email: string } | null }> | null;
}) => {
const { t } = useLocale();
attendees.sort((a, b) => a.id - b.id);
return (
<div className="text-emphasis text-sm" onClick={(e) => e.stopPropagation()}>
{user && <FirstAttendee user={user} currentEmail={currentEmail} />}
{user && <FirstAttendee user={user} currentEmail={currentEmail} hideOrganizerEmail={hideOrganizerEmail} />}
{attendees.length > 1 ? <span>,&nbsp;</span> : <span>&nbsp;{t("and")}&nbsp;</span>}
<Attendee {...attendees[0]} bookingUid={bookingUid} isBookingInPast={isBookingInPast} />
<Attendee
{...attendees[0]}
bookingUid={bookingUid}
isBookingInPast={isBookingInPast}
hideOrganizerEmail={hideOrganizerEmail}
organizerEmail={organizerEmail}
eventTypeHosts={eventTypeHosts}
/>
{attendees.length > 1 && (
<>
<div className="text-emphasis inline-block text-sm">&nbsp;{t("and")}&nbsp;</div>
@@ -1015,7 +1060,14 @@ const DisplayAttendees = ({
<Tooltip
content={attendees.slice(1).map((attendee) => (
<p key={attendee.email}>
<Attendee {...attendee} bookingUid={bookingUid} isBookingInPast={isBookingInPast} />
<Attendee
{...attendee}
bookingUid={bookingUid}
isBookingInPast={isBookingInPast}
hideOrganizerEmail={hideOrganizerEmail}
organizerEmail={organizerEmail}
eventTypeHosts={eventTypeHosts}
/>
</p>
))}>
{isBookingInPast ? (
@@ -1025,7 +1077,14 @@ const DisplayAttendees = ({
)}
</Tooltip>
) : (
<Attendee {...attendees[1]} bookingUid={bookingUid} isBookingInPast={isBookingInPast} />
<Attendee
{...attendees[1]}
bookingUid={bookingUid}
isBookingInPast={isBookingInPast}
hideOrganizerEmail={hideOrganizerEmail}
organizerEmail={organizerEmail}
eventTypeHosts={eventTypeHosts}
/>
)}
</>
)}
@@ -466,13 +466,17 @@ function WhoSection({ booking }: { booking: BookingOutput }) {
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<p className="text-emphasis truncate text-sm leading-[1.2]">
{booking.user.name || booking.user.email}
{booking.eventType?.hideOrganizerEmail
? booking.user.name || t("organizer")
: booking.user.name || booking.user.email}
</p>
<Badge variant="purple" size="sm" className="capitalize">
{t("host")}
</Badge>
</div>
<p className="text-default truncate text-sm leading-[1.2]">{booking.user.email}</p>
{!booking.eventType?.hideOrganizerEmail && (
<p className="text-default truncate text-sm leading-[1.2]">{booking.user.email}</p>
)}
</div>
</div>
)}
@@ -642,21 +642,30 @@ export default function Success(props: PageProps) {
)}
</div>
)}
{bookingInfo?.attendees.map((attendee) => (
<div key={attendee.name + attendee.email} className="mb-3 last:mb-0">
{attendee.name && (
<p data-testid={`attendee-name-${attendee.name}`}>{attendee.name}</p>
)}
{attendee.phoneNumber && (
<p data-testid={`attendee-phone-${attendee.phoneNumber}`}>
{attendee.phoneNumber}
</p>
)}
{!isSmsCalEmail(attendee.email) && (
<p data-testid={`attendee-email-${attendee.email}`}>{attendee.email}</p>
)}
</div>
))}
{bookingInfo?.attendees.map((attendee) => {
// Check if attendee is a team member/host (for round robin scenarios)
const isTeamMemberOrHost =
eventType.hosts?.some((host) => host.user.email === attendee.email) ||
eventType.users?.some((user) => user.email === attendee.email);
const shouldHideEmail =
bookingInfo.eventType?.hideOrganizerEmail && isTeamMemberOrHost;
return (
<div key={attendee.name + attendee.email} className="mb-3 last:mb-0">
{attendee.name && (
<p data-testid={`attendee-name-${attendee.name}`}>{attendee.name}</p>
)}
{attendee.phoneNumber && (
<p data-testid={`attendee-phone-${attendee.phoneNumber}`}>
{attendee.phoneNumber}
</p>
)}
{!isSmsCalEmail(attendee.email) && !shouldHideEmail && (
<p data-testid={`attendee-email-${attendee.email}`}>{attendee.email}</p>
)}
</div>
);
})}
</div>
</>
)}
+6 -1
View File
@@ -36,7 +36,12 @@ export function WhoInfo(props: { calEvent: CalendarEvent; t: TFunction }) {
email={props.calEvent.hideOrganizerEmail ? "" : props.calEvent.organizer.email}
/>
{props.calEvent.team?.members.map((member) => (
<PersonInfo key={member.name} name={member.name} role={t("team_member")} email={member?.email} />
<PersonInfo
key={member.name}
name={member.name}
role={t("team_member")}
email={props.calEvent.hideOrganizerEmail ? "" : member?.email}
/>
))}
{props.calEvent.attendees.map((attendee) => (
<PersonInfo
+5 -1
View File
@@ -55,7 +55,11 @@ export const getWho = (
const teamMembers = calEvent.team?.members
? calEvent.team.members
.map((member) => `${member.name} - ${t("team_member")}\n${member.email}`)
.map((member) =>
calEvent.hideOrganizerEmail
? `${member.name} - ${t("team_member")}`
: `${member.name} - ${t("team_member")}\n${member.email}`
)
.join("\n")
: [];