diff --git a/.env.example b/.env.example index 91c78b5a65..d38b9fafed 100644 --- a/.env.example +++ b/.env.example @@ -314,3 +314,4 @@ APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0 APP_ROUTER_APPS_CATEGORIES_ENABLED=0 # whether we redirect to the future/apps/categories/[category] from /apps/categories/[category] or not APP_ROUTER_APPS_CATEGORIES_CATEGORY_ENABLED=0 +APP_ROUTER_BOOKINGS_STATUS_ENABLED=0 diff --git a/apps/web/abTest/middlewareFactory.ts b/apps/web/abTest/middlewareFactory.ts index 3f23bde3e4..e3eb328beb 100644 --- a/apps/web/abTest/middlewareFactory.ts +++ b/apps/web/abTest/middlewareFactory.ts @@ -11,6 +11,7 @@ const ROUTES: [URLPattern, boolean][] = [ ["/apps/:slug/setup", process.env.APP_ROUTER_APPS_SLUG_SETUP_ENABLED === "1"] as const, ["/apps/categories", process.env.APP_ROUTER_APPS_CATEGORIES_ENABLED === "1"] as const, ["/apps/categories/:category", process.env.APP_ROUTER_APPS_CATEGORIES_CATEGORY_ENABLED === "1"] as const, + ["/bookings/:status", process.env.APP_ROUTER_BOOKINGS_STATUS_ENABLED === "1"] as const, ].map(([pathname, enabled]) => [ new URLPattern({ pathname, diff --git a/apps/web/app/future/(individual-page-wrapper)/bookings/[status]/layout.tsx b/apps/web/app/future/(individual-page-wrapper)/bookings/[status]/layout.tsx new file mode 100644 index 0000000000..ad00ceeb78 --- /dev/null +++ b/apps/web/app/future/(individual-page-wrapper)/bookings/[status]/layout.tsx @@ -0,0 +1,56 @@ +import { ssgInit } from "app/_trpc/ssgInit"; +import type { Params } from "app/_types"; +import { _generateMetadata } from "app/_utils"; +import { notFound } from "next/navigation"; +import type { ReactElement } from "react"; +import { z } from "zod"; + +import { getLayout } from "@calcom/features/MainLayoutAppDir"; +import { APP_NAME } from "@calcom/lib/constants"; + +import PageWrapper from "@components/PageWrapperAppDir"; + +const validStatuses = ["upcoming", "recurring", "past", "cancelled", "unconfirmed"] as const; + +const querySchema = z.object({ + status: z.enum(validStatuses), +}); + +type Props = { params: Params; children: ReactElement }; + +export const generateMetadata = async () => + await _generateMetadata( + (t) => `${APP_NAME} | ${t("bookings")}`, + () => "" + ); + +export const generateStaticParams = async () => { + return validStatuses.map((status) => ({ status })); +}; + +const getData = async ({ params }: { params: Params }) => { + const parsedParams = querySchema.safeParse(params); + + if (!parsedParams.success) { + notFound(); + } + + const ssg = await ssgInit(); + + return { + status: parsedParams.data.status, + dehydratedState: await ssg.dehydrate(), + }; +}; + +export default async function BookingPageLayout({ params, children }: Props) { + const props = await getData({ params }); + + return ( + + {children} + + ); +} + +export const dynamic = "force-static"; diff --git a/apps/web/app/future/(individual-page-wrapper)/bookings/[status]/page.tsx b/apps/web/app/future/(individual-page-wrapper)/bookings/[status]/page.tsx new file mode 100644 index 0000000000..bd24129e55 --- /dev/null +++ b/apps/web/app/future/(individual-page-wrapper)/bookings/[status]/page.tsx @@ -0,0 +1 @@ +export { default } from "@pages/bookings/[status]"; diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts index dac4ef0d21..1d4fcaccbe 100644 --- a/apps/web/middleware.ts +++ b/apps/web/middleware.ts @@ -130,6 +130,8 @@ export const config = { "/future/apps/categories/", "/apps/categories/:category/", "/future/apps/categories/:category/", + "/bookings/:status/", + "/future/bookings/:status/", ], }; diff --git a/apps/web/pages/bookings/[status].tsx b/apps/web/pages/bookings/[status].tsx index 988325fae9..878d344620 100644 --- a/apps/web/pages/bookings/[status].tsx +++ b/apps/web/pages/bookings/[status].tsx @@ -1,3 +1,5 @@ +"use client"; + import { useAutoAnimate } from "@formkit/auto-animate/react"; import type { GetStaticPaths, GetStaticProps } from "next"; import { Fragment, useState } from "react"; diff --git a/apps/web/playwright/ab-tests-redirect.e2e.ts b/apps/web/playwright/ab-tests-redirect.e2e.ts index 330da414c1..afa1b9547e 100644 --- a/apps/web/playwright/ab-tests-redirect.e2e.ts +++ b/apps/web/playwright/ab-tests-redirect.e2e.ts @@ -139,4 +139,31 @@ test.describe("apps/ A/B tests", () => { await expect(locator).toBeVisible(); }); + + test("should point to the /future/bookings/[status]", async ({ page, users, context }) => { + await context.addCookies([ + { + name: "x-calcom-future-routes-override", + value: "1", + url: "http://localhost:3000", + }, + ]); + const user = await users.create(); + + await user.apiLogin(); + + await page.goto("/bookings/upcoming/"); + + await page.waitForLoadState(); + + const dataNextJsRouter = await page.evaluate(() => + window.document.documentElement.getAttribute("data-nextjs-router") + ); + + expect(dataNextJsRouter).toEqual("app"); + + const locator = page.getByTestId("horizontal-tab-upcoming"); + + await expect(locator).toHaveClass(/bg-emphasis/); + }); }); diff --git a/turbo.json b/turbo.json index 32319c2703..4a1bcabc9c 100644 --- a/turbo.json +++ b/turbo.json @@ -203,6 +203,7 @@ "APP_ROUTER_APPS_CATEGORIES_ENABLED", "APP_ROUTER_APPS_SLUG_ENABLED", "APP_ROUTER_APPS_SLUG_SETUP_ENABLED", + "APP_ROUTER_BOOKINGS_STATUS_ENABLED", "APP_ROUTER_EVENT_TYPES_ENABLED", "APP_ROUTER_SETTINGS_ADMIN_ENABLED", "APP_USER_NAME",