chore: [app-router-migration 21] Migrate "/d/*" pages (#13047)
* Migrate d/* page group * Fix metadata * manual: fix type of arg of getData * fix * manual: fix type errors * Fix type errors * fix type errors * fix error * fix * fix build error
This commit is contained in:
parent
a28b9cacd2
commit
b76a2a4019
|
@ -2,16 +2,20 @@ import type { GetServerSideProps, GetServerSidePropsContext } from "next";
|
||||||
import { notFound, redirect } from "next/navigation";
|
import { notFound, redirect } from "next/navigation";
|
||||||
|
|
||||||
export const withAppDir =
|
export const withAppDir =
|
||||||
(getServerSideProps: GetServerSideProps) => async (context: GetServerSidePropsContext) => {
|
<T extends Record<string, any>>(getServerSideProps: GetServerSideProps<T>) =>
|
||||||
|
async (context: GetServerSidePropsContext): Promise<T> => {
|
||||||
const ssrResponse = await getServerSideProps(context);
|
const ssrResponse = await getServerSideProps(context);
|
||||||
|
|
||||||
if ("redirect" in ssrResponse) {
|
if ("redirect" in ssrResponse) {
|
||||||
redirect(ssrResponse.redirect.destination);
|
redirect(ssrResponse.redirect.destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("notFound" in ssrResponse) {
|
if ("notFound" in ssrResponse) {
|
||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssrResponse.props;
|
return {
|
||||||
|
...ssrResponse.props,
|
||||||
|
// includes dehydratedState required for future page trpcPropvider
|
||||||
|
...("trpcState" in ssrResponse.props && { dehydratedState: ssrResponse.props.trpcState }),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
import LegacyPage, { type PageProps } from "@pages/d/[link]/[slug]";
|
||||||
|
import { withAppDir } from "app/AppDirSSRHOC";
|
||||||
|
import { _generateMetadata } from "app/_utils";
|
||||||
|
import { WithLayout } from "app/layoutHOC";
|
||||||
|
import type { GetServerSidePropsContext } from "next";
|
||||||
|
import { cookies, headers } from "next/headers";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||||
|
import { getBookingForReschedule, getMultipleDurationValue } from "@calcom/features/bookings/lib/get-booking";
|
||||||
|
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||||
|
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||||
|
import slugify from "@calcom/lib/slugify";
|
||||||
|
import prisma from "@calcom/prisma";
|
||||||
|
|
||||||
|
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||||
|
|
||||||
|
import { ssrInit } from "@server/lib/ssr";
|
||||||
|
|
||||||
|
export const generateMetadata = async ({ params }: { params: Record<string, string | string[]> }) => {
|
||||||
|
const pageProps = await getPageProps(
|
||||||
|
buildLegacyCtx(headers(), cookies(), params) as unknown as GetServerSidePropsContext
|
||||||
|
);
|
||||||
|
|
||||||
|
const { entity, booking, user, slug, isTeamEvent } = pageProps;
|
||||||
|
const rescheduleUid = booking?.uid;
|
||||||
|
const { trpc } = await import("@calcom/trpc");
|
||||||
|
const { data: event } = trpc.viewer.public.event.useQuery(
|
||||||
|
{ username: user ?? "", eventSlug: slug ?? "", isTeamEvent, org: entity.orgSlug ?? null },
|
||||||
|
{ refetchOnWindowFocus: false }
|
||||||
|
);
|
||||||
|
const profileName = event?.profile?.name ?? "";
|
||||||
|
const title = event?.title ?? "";
|
||||||
|
return await _generateMetadata(
|
||||||
|
(t) => `${rescheduleUid && !!booking ? t("reschedule") : ""} ${title} | ${profileName}`,
|
||||||
|
(t) => `${rescheduleUid ? t("reschedule") : ""} ${title}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getPageProps(context: GetServerSidePropsContext) {
|
||||||
|
const session = await getServerSession({ req: context.req });
|
||||||
|
const { link, slug } = paramsSchema.parse(context.params);
|
||||||
|
const { rescheduleUid, duration: queryDuration } = context.query;
|
||||||
|
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req);
|
||||||
|
const org = isValidOrgDomain ? currentOrgDomain : null;
|
||||||
|
|
||||||
|
const hashedLink = await prisma.hashedLink.findUnique({
|
||||||
|
where: {
|
||||||
|
link,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
eventTypeId: true,
|
||||||
|
eventType: {
|
||||||
|
select: {
|
||||||
|
users: {
|
||||||
|
select: {
|
||||||
|
username: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
team: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const username = hashedLink?.eventType.users[0]?.username;
|
||||||
|
|
||||||
|
if (!hashedLink || !username) {
|
||||||
|
return notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.user.findFirst({
|
||||||
|
where: {
|
||||||
|
username,
|
||||||
|
organization: isValidOrgDomain
|
||||||
|
? {
|
||||||
|
slug: currentOrgDomain,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
away: true,
|
||||||
|
hideBranding: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
let booking: GetBookingType | null = null;
|
||||||
|
if (rescheduleUid) {
|
||||||
|
booking = await getBookingForReschedule(`${rescheduleUid}`, session?.user?.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isTeamEvent = !!hashedLink.eventType?.team?.id;
|
||||||
|
const ssr = await ssrInit(context);
|
||||||
|
|
||||||
|
// We use this to both prefetch the query on the server,
|
||||||
|
// as well as to check if the event exist, so we c an show a 404 otherwise.
|
||||||
|
const eventData = await ssr.viewer.public.event.fetch({ username, eventSlug: slug, isTeamEvent, org });
|
||||||
|
|
||||||
|
if (!eventData) {
|
||||||
|
return notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
entity: eventData.entity,
|
||||||
|
duration: getMultipleDurationValue(eventData.metadata?.multipleDuration, queryDuration, eventData.length),
|
||||||
|
booking,
|
||||||
|
away: user?.away,
|
||||||
|
user: username,
|
||||||
|
slug,
|
||||||
|
dehydratedState: ssr.dehydrate(),
|
||||||
|
isBrandingHidden: user?.hideBranding,
|
||||||
|
// Sending the team event from the server, because this template file
|
||||||
|
// is reused for both team and user events.
|
||||||
|
isTeamEvent,
|
||||||
|
hashedLink: link,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const paramsSchema = z.object({ link: z.string(), slug: z.string().transform((s) => slugify(s)) });
|
||||||
|
|
||||||
|
// @ts-expect-error arg
|
||||||
|
const getData = withAppDir<PageProps>(getPageProps);
|
||||||
|
export default WithLayout({ getLayout: null, Page: LegacyPage, getData })<"P">;
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
import type { GetServerSidePropsContext } from "next";
|
import type { GetServerSidePropsContext } from "next";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
@ -16,7 +18,7 @@ import type { EmbedProps } from "@lib/withEmbedSsr";
|
||||||
|
|
||||||
import PageWrapper from "@components/PageWrapper";
|
import PageWrapper from "@components/PageWrapper";
|
||||||
|
|
||||||
type PageProps = inferSSRProps<typeof getServerSideProps> & EmbedProps;
|
export type PageProps = Omit<inferSSRProps<typeof getServerSideProps>, "trpcState"> & EmbedProps;
|
||||||
|
|
||||||
export default function Type({
|
export default function Type({
|
||||||
slug,
|
slug,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user