From 214917cdb882b794a11f2076f72b5d436d3fc7ef Mon Sep 17 00:00:00 2001 From: Naitik Kapadia <88614335+KapadiaNaitik@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:51:21 +0530 Subject: [PATCH] fix: Preview for short urls (#2174) Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com> Co-authored-by: Shubham Palriwala Co-authored-by: Johannes --- apps/web/app/[shortUrlId]/page.tsx | 25 ++++++++++++++ apps/web/app/s/[surveyId]/metadata.ts | 50 +++++++++++++++++++++++++++ apps/web/app/s/[surveyId]/page.tsx | 48 ++----------------------- 3 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 apps/web/app/s/[surveyId]/metadata.ts diff --git a/apps/web/app/[shortUrlId]/page.tsx b/apps/web/app/[shortUrlId]/page.tsx index 79280ab3cc..15e35c3b0a 100644 --- a/apps/web/app/[shortUrlId]/page.tsx +++ b/apps/web/app/[shortUrlId]/page.tsx @@ -1,8 +1,33 @@ +import { getMetadataForLinkSurvey } from "@/app/s/[surveyId]/metadata"; +import type { Metadata } from "next"; import { notFound, redirect } from "next/navigation"; import { getShortUrl } from "@formbricks/lib/shortUrl/service"; import { ZShortUrlId } from "@formbricks/types/shortUrl"; +export async function generateMetadata({ params }): Promise { + if (!params.shortUrlId) { + notFound(); + } + + if (ZShortUrlId.safeParse(params.shortUrlId).success !== true) { + notFound(); + } + + let shortUrl; + + try { + shortUrl = await getShortUrl(params.shortUrlId); + if (!shortUrl) { + notFound(); + } + } catch (error) { + console.error(error); + } + + const surveyId = shortUrl.url.substring(shortUrl.url.lastIndexOf("/") + 1); + return getMetadataForLinkSurvey(surveyId); +} export default async function ShortUrlPage({ params }) { if (!params.shortUrlId) { notFound(); diff --git a/apps/web/app/s/[surveyId]/metadata.ts b/apps/web/app/s/[surveyId]/metadata.ts new file mode 100644 index 0000000000..259427aae1 --- /dev/null +++ b/apps/web/app/s/[surveyId]/metadata.ts @@ -0,0 +1,50 @@ +import { Metadata } from "next"; +import { notFound } from "next/navigation"; + +import { WEBAPP_URL } from "@formbricks/lib/constants"; +import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; +import { COLOR_DEFAULTS } from "@formbricks/lib/styling/constants"; +import { getSurvey } from "@formbricks/lib/survey/service"; + +export const getMetadataForLinkSurvey = async (surveyId: string): Promise => { + const survey = await getSurvey(surveyId); + + if (!survey || survey.type !== "link" || survey.status === "draft") { + notFound(); + } + + const product = await getProductByEnvironmentId(survey.environmentId); + + if (!product) { + throw new Error("Product not found"); + } + + const brandColor = getBrandColorForURL(survey.styling?.brandColor?.light || COLOR_DEFAULTS.brandColor); + const surveyName = getNameForURL(survey.name); + + const ogImgURL = `/api/v1/og?brandColor=${brandColor}&name=${surveyName}`; + + return { + title: survey.name, + metadataBase: new URL(WEBAPP_URL), + openGraph: { + title: survey.name, + description: "Thanks a lot for your time 🙏", + url: `/s/${survey.id}`, + siteName: "", + images: [ogImgURL], + locale: "en_US", + type: "website", + }, + twitter: { + card: "summary_large_image", + title: survey.name, + description: "Thanks a lot for your time 🙏", + images: [ogImgURL], + }, + }; +}; + +const getNameForURL = (url: string) => url.replace(/ /g, "%20"); + +const getBrandColorForURL = (url: string) => url.replace(/#/g, "%23"); diff --git a/apps/web/app/s/[surveyId]/page.tsx b/apps/web/app/s/[surveyId]/page.tsx index 01872d65cb..598937cd3d 100644 --- a/apps/web/app/s/[surveyId]/page.tsx +++ b/apps/web/app/s/[surveyId]/page.tsx @@ -5,6 +5,7 @@ import { MediaBackground } from "@/app/s/[surveyId]/components/MediaBackground"; import PinScreen from "@/app/s/[surveyId]/components/PinScreen"; import SurveyInactive from "@/app/s/[surveyId]/components/SurveyInactive"; import { checkValidity } from "@/app/s/[surveyId]/lib/prefilling"; +import { getMetadataForLinkSurvey } from "@/app/s/[surveyId]/metadata"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; @@ -13,7 +14,6 @@ import { IMPRINT_URL, IS_FORMBRICKS_CLOUD, PRIVACY_URL, WEBAPP_URL } from "@form import { createPerson, getPersonByUserId } from "@formbricks/lib/person/service"; import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; import { getResponseBySingleUseId, getResponseCountBySurveyId } from "@formbricks/lib/response/service"; -import { COLOR_DEFAULTS } from "@formbricks/lib/styling/constants"; import { getSurvey } from "@formbricks/lib/survey/service"; import { getTeamByEnvironmentId } from "@formbricks/lib/team/service"; import { ZId } from "@formbricks/types/environment"; @@ -39,51 +39,7 @@ export async function generateMetadata({ params }: LinkSurveyPageProps): Promise notFound(); } - const survey = await getSurvey(params.surveyId); - - if (!survey || survey.type !== "link" || survey.status === "draft") { - notFound(); - } - - const product = await getProductByEnvironmentId(survey.environmentId); - - if (!product) { - throw new Error("Product not found"); - } - - function getNameForURL(url: string) { - return url.replace(/ /g, "%20"); - } - - function getBrandColorForURL(url: string) { - return url.replace(/#/g, "%23"); - } - - // const brandColor = getBrandColorForURL(product.brandColor); - const brandColor = getBrandColorForURL(survey.styling?.brandColor?.light || COLOR_DEFAULTS.brandColor); - const surveyName = getNameForURL(survey.name); - - const ogImgURL = `/api/v1/og?brandColor=${brandColor}&name=${surveyName}`; - - return { - title: survey.name, - metadataBase: new URL(WEBAPP_URL), - openGraph: { - title: survey.name, - description: "Create your own survey like this with Formbricks' open source survey suite.", - url: `/s/${survey.id}`, - siteName: "", - images: [ogImgURL], - locale: "en_US", - type: "website", - }, - twitter: { - card: "summary_large_image", - title: survey.name, - description: "Create your own survey like this with Formbricks' open source survey suite.", - images: [ogImgURL], - }, - }; + return getMetadataForLinkSurvey(params.surveyId); } export default async function LinkSurveyPage({ params, searchParams }: LinkSurveyPageProps) {