diff --git a/apps/web/app/error.tsx b/apps/web/app/error.tsx new file mode 100644 index 0000000000..b804d677ac --- /dev/null +++ b/apps/web/app/error.tsx @@ -0,0 +1,64 @@ +"use client"; + +/** + * Typescript class based component for custom-error + * @link https://nextjs.org/docs/advanced-features/custom-error-page + */ +import type { NextPage } from "next"; +import type { ErrorProps } from "next/error"; +import React from "react"; + +import { HttpError } from "@calcom/lib/http-error"; +import logger from "@calcom/lib/logger"; +import { redactError } from "@calcom/lib/redactError"; + +import { ErrorPage } from "@components/error/error-page"; + +type NextError = Error & { digest?: string }; + +// Ref: https://nextjs.org/docs/app/api-reference/file-conventions/error#props +export type DefaultErrorProps = { + error: NextError; + reset: () => void; // A function to reset the error boundary +}; + +type AugmentedError = NextError | HttpError | null; + +type CustomErrorProps = { + err?: AugmentedError; + statusCode?: number; + message?: string; +} & Omit; + +const log = logger.getSubLogger({ prefix: ["[error]"] }); + +const CustomError: NextPage = (props) => { + const { error } = props; + let errorObject: CustomErrorProps = { + message: error.message, + err: error, + }; + + if (error instanceof HttpError) { + const redactedError = redactError(error); + errorObject = { + statusCode: error.statusCode, + title: redactedError.name, + message: redactedError.message, + err: { + ...redactedError, + ...error, + }, + }; + } + + // `error.digest` property contains an automatically generated hash of the error that can be used to match the corresponding error in server-side logs + log.debug(`${error?.toString() ?? JSON.stringify(error)}`); + log.info("errorObject: ", errorObject); + + return ( + + ); +}; + +export default CustomError; diff --git a/apps/web/app/global-error.tsx b/apps/web/app/global-error.tsx new file mode 100644 index 0000000000..ecf7247dbb --- /dev/null +++ b/apps/web/app/global-error.tsx @@ -0,0 +1,17 @@ +"use client"; + +import { type NextPage } from "next"; + +import CustomError, { type DefaultErrorProps } from "./error"; + +export const GlobalError: NextPage = (props) => { + return ( + + + + + + ); +}; + +export default GlobalError; diff --git a/apps/web/app/not-found.tsx b/apps/web/app/not-found.tsx index e13815993b..ff586f73ea 100644 --- a/apps/web/app/not-found.tsx +++ b/apps/web/app/not-found.tsx @@ -1,10 +1,9 @@ +import NotFoundPage from "@pages/404"; +import { WithLayout } from "app/layoutHOC"; import type { GetStaticPropsContext } from "next"; import { getTranslations } from "@server/lib/getTranslations"; -import NotFoundPage from "./404/page"; -import { WithLayout } from "./layoutHOC"; - const getData = async (context: GetStaticPropsContext) => { const i18n = await getTranslations(context); diff --git a/apps/web/app/404/page.tsx b/apps/web/pages/404.tsx similarity index 96% rename from apps/web/app/404/page.tsx rename to apps/web/pages/404.tsx index dbf3dde22d..4b759f1498 100644 --- a/apps/web/app/404/page.tsx +++ b/apps/web/pages/404.tsx @@ -1,5 +1,6 @@ "use client"; +import type { GetStaticPropsContext } from "next"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { useEffect, useState } from "react"; @@ -10,11 +11,14 @@ import { } from "@calcom/features/ee/organizations/lib/orgDomains"; import { DOCS_URL, IS_CALCOM, JOIN_DISCORD, WEBSITE_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { HeadSeo, Icon } from "@calcom/ui"; +import { HeadSeo } from "@calcom/ui"; +import { Icon } from "@calcom/ui"; import { Discord } from "@calcom/ui/components/icon/Discord"; import PageWrapper from "@components/PageWrapper"; +import { getTranslations } from "@server/lib/getTranslations"; + enum pageType { ORG = "org", TEAM = "team", @@ -267,3 +271,13 @@ export default function Custom404() { } Custom404.PageWrapper = PageWrapper; + +export const getStaticProps = async (context: GetStaticPropsContext) => { + const i18n = await getTranslations(context); + + return { + props: { + i18n, + }, + }; +}; diff --git a/apps/web/playwright/lib/testUtils.ts b/apps/web/playwright/lib/testUtils.ts index 39e52c4806..01720d5947 100644 --- a/apps/web/playwright/lib/testUtils.ts +++ b/apps/web/playwright/lib/testUtils.ts @@ -370,5 +370,4 @@ export async function doOnOrgDomain( // When App directory is there, this is the 404 page text. We should work on fixing the 404 page as it changed due to app directory. export const NotFoundPageTextAppDir = "This page does not exist."; -export const NotFoundPageTextPages = "404: This page could not be found."; // export const NotFoundPageText = "ERROR 404";