import classNames from "classnames"; import type { GetServerSidePropsContext } from "next"; import Link from "next/link"; import { useRouter } from "next/router"; import { useEffect } from "react"; import { sdkActionManager, useIsEmbed } from "@calcom/embed-core/embed-iframe"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import EventTypeDescription from "@calcom/features/eventtypes/components/EventTypeDescription"; import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import useTheme from "@calcom/lib/hooks/useTheme"; import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import { getTeamWithMembers } from "@calcom/lib/server/queries/teams"; import { stripMarkdown } from "@calcom/lib/stripMarkdown"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import prisma from "@calcom/prisma"; import { teamMetadataSchema } from "@calcom/prisma/zod-utils"; import { Avatar, AvatarGroup, Button, EmptyScreen, HeadSeo } from "@calcom/ui"; import { ArrowRight } from "@calcom/ui/components/icon"; import { useToggleQuery } from "@lib/hooks/useToggleQuery"; import type { inferSSRProps } from "@lib/types/inferSSRProps"; import PageWrapper from "@components/PageWrapper"; import Team from "@components/team/screens/Team"; import { ssrInit } from "@server/lib/ssr"; export type PageProps = inferSSRProps; function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain }: PageProps) { useTheme(team.theme); const showMembers = useToggleQuery("members"); const { t } = useLocale(); const isEmbed = useIsEmbed(); const telemetry = useTelemetry(); const router = useRouter(); const teamName = team.name || "Nameless Team"; const isBioEmpty = !team.bio || !team.bio.replace("


", "").length; const metadata = teamMetadataSchema.parse(team.metadata); useEffect(() => { telemetry.event( telemetryEventTypes.pageView, collectPageParameters("/team/[slug]", { isTeamBooking: true }) ); }, [telemetry, router.asPath]); if (isUnpublished) { return (
} headline={t("team_is_unpublished", { team: teamName, })} description={t("team_is_unpublished_description", { entity: metadata?.isOrganization ? t("organization").toLowerCase() : t("team").toLowerCase(), })} />
); } // slug is a route parameter, we don't want to forward it to the next route const { slug: _slug, ...queryParamsToForward } = router.query; const EventTypes = () => ( ); const SubTeams = () => team.children.length ? ( ) : (

{" " + t("no_teams_yet")}

{t("no_teams_yet_description")}

); return ( <>

{team.parent && `${team.parent.name} `} {teamName}

{!isBioEmpty && ( <>
)}
{metadata?.isOrganization ? ( ) : ( <> {(showMembers.isOn || !team.eventTypes.length) && } {!showMembers.isOn && team.eventTypes.length > 0 && (
{!team.hideBookATeamMember && (
)}
)} )}
); } export const getServerSideProps = async (context: GetServerSidePropsContext) => { const ssr = await ssrInit(context); const slug = Array.isArray(context.query?.slug) ? context.query.slug.pop() : context.query.slug; const { isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? ""); const team = await getTeamWithMembers(undefined, slug); const metadata = teamMetadataSchema.parse(team?.metadata ?? {}); // Taking care of sub-teams and orgs if ( (isValidOrgDomain && team?.parent && !!metadata?.isOrganization) || (!isValidOrgDomain && team?.parent) || (!isValidOrgDomain && !!metadata?.isOrganization) ) { return { notFound: true } as const; } if (!team) { const unpublishedTeam = await prisma.team.findFirst({ where: { metadata: { path: ["requestedSlug"], equals: slug, }, }, }); if (!unpublishedTeam) return { notFound: true } as const; return { props: { isUnpublished: true, team: { ...unpublishedTeam, createdAt: null }, trpcState: ssr.dehydrate(), }, } as const; } team.eventTypes = team.eventTypes.map((type) => ({ ...type, users: type.users.map((user) => ({ ...user, avatar: "/" + user.username + "/avatar.png", })), descriptionAsSafeHTML: markdownToSafeHTML(type.description), })); const safeBio = markdownToSafeHTML(team.bio) || ""; const members = team.members.map((member) => { return { ...member, safeBio: markdownToSafeHTML(member.bio || "") }; }); const markdownStrippedBio = stripMarkdown(team?.bio || ""); const { inviteToken: _inviteToken, ...serializableTeam } = team; return { props: { team: { ...serializableTeam, safeBio, members }, themeBasis: serializableTeam.slug, trpcState: ssr.dehydrate(), markdownStrippedBio, isValidOrgDomain, }, } as const; }; TeamPage.isBookingPage = true; TeamPage.PageWrapper = PageWrapper; export default TeamPage;