feat(BOOK-57): Adjusted metadata for destination pages with active seo filter
Approved-by: Chuma Mcphoy (We Ahead)
This commit is contained in:
61
apps/scandic-web/utils/metadata/title/destinationPage.ts
Normal file
61
apps/scandic-web/utils/metadata/title/destinationPage.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import type { RawMetadataSchema } from "@scandic-hotels/trpc/routers/contentstack/metadata/output"
|
||||
|
||||
export async function getDestinationPageTitle(
|
||||
data: RawMetadataSchema,
|
||||
pageType: "city" | "country",
|
||||
suffix: string
|
||||
) {
|
||||
const intl = await getIntl()
|
||||
const { destinationData } = data
|
||||
if (!destinationData) {
|
||||
return null
|
||||
}
|
||||
|
||||
const location = destinationData.location
|
||||
|
||||
if (!location) {
|
||||
return null
|
||||
}
|
||||
const destinationTitle =
|
||||
pageType === "country"
|
||||
? intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Destinations in {location}",
|
||||
},
|
||||
{ location }
|
||||
)
|
||||
: intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Hotels in {location}",
|
||||
},
|
||||
{ location }
|
||||
)
|
||||
|
||||
return `${destinationTitle}${suffix}`
|
||||
}
|
||||
|
||||
export function getDestinationFilterSeoMetaTitle(
|
||||
data: RawMetadataSchema,
|
||||
suffix: string
|
||||
) {
|
||||
const filter = data.destinationData?.filter
|
||||
|
||||
if (!filter) {
|
||||
return null
|
||||
}
|
||||
const foundSeoFilter = data.seo_filters?.find(
|
||||
(f) => f.filterConnection.edges[0]?.node?.slug === filter
|
||||
)
|
||||
|
||||
if (foundSeoFilter) {
|
||||
if (foundSeoFilter.seo_metadata?.title) {
|
||||
return `${foundSeoFilter.seo_metadata.title}${suffix}`
|
||||
}
|
||||
|
||||
return `${foundSeoFilter.heading}${suffix}`
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
148
apps/scandic-web/utils/metadata/title/hotelPage.ts
Normal file
148
apps/scandic-web/utils/metadata/title/hotelPage.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import type { RawMetadataSchema } from "@scandic-hotels/trpc/routers/contentstack/metadata/output"
|
||||
|
||||
async function getSubpageTitle(
|
||||
subpageUrl: string,
|
||||
additionalHotelData: RawMetadataSchema["additionalHotelData"],
|
||||
hotelRestaurants: RawMetadataSchema["hotelRestaurants"],
|
||||
hotelName: string,
|
||||
destination: string
|
||||
) {
|
||||
const intl = await getIntl()
|
||||
const restaurantSubPage = hotelRestaurants?.find(
|
||||
(restaurant) => restaurant.nameInUrl === subpageUrl
|
||||
)
|
||||
if (restaurantSubPage) {
|
||||
const restaurantTitleLong = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"Explore {restaurantName} at {hotelName} in {destination}",
|
||||
},
|
||||
{
|
||||
restaurantName: restaurantSubPage.name,
|
||||
hotelName,
|
||||
destination,
|
||||
}
|
||||
)
|
||||
const restaurantTitleShort = intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Explore {restaurantName} at {hotelName}",
|
||||
},
|
||||
{
|
||||
restaurantName: restaurantSubPage.name,
|
||||
hotelName,
|
||||
}
|
||||
)
|
||||
|
||||
if (restaurantTitleLong.length > 60) {
|
||||
return restaurantTitleShort
|
||||
}
|
||||
return restaurantTitleLong
|
||||
}
|
||||
|
||||
if (!additionalHotelData) {
|
||||
return null
|
||||
}
|
||||
|
||||
switch (subpageUrl) {
|
||||
case additionalHotelData.hotelParking.nameInUrl:
|
||||
const parkingTitleLong = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"Parking information for {hotelName} in {destination}",
|
||||
},
|
||||
{ hotelName, destination }
|
||||
)
|
||||
const parkingTitleShort = intl.formatMessage(
|
||||
{ defaultMessage: "Parking information for {hotelName}" },
|
||||
{ hotelName }
|
||||
)
|
||||
|
||||
if (parkingTitleLong.length > 60) {
|
||||
return parkingTitleShort
|
||||
}
|
||||
return parkingTitleLong
|
||||
case additionalHotelData.healthAndFitness.nameInUrl:
|
||||
const wellnessTitleLong = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"Gym & health facilities at {hotelName} in {destination}",
|
||||
},
|
||||
{ hotelName, destination }
|
||||
)
|
||||
const wellnessTitleShort = intl.formatMessage(
|
||||
{ defaultMessage: "Gym & health facilities at {hotelName}" },
|
||||
{ hotelName }
|
||||
)
|
||||
|
||||
if (wellnessTitleLong.length > 60) {
|
||||
return wellnessTitleShort
|
||||
}
|
||||
return wellnessTitleLong
|
||||
case additionalHotelData.hotelSpecialNeeds.nameInUrl:
|
||||
const accessibilityTitleLong = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"Accessibility information for {hotelName} in {destination}",
|
||||
},
|
||||
{ hotelName, destination }
|
||||
)
|
||||
const accessibilityTitleShort = intl.formatMessage(
|
||||
{ defaultMessage: "Accessibility information for {hotelName}" },
|
||||
{ hotelName }
|
||||
)
|
||||
|
||||
if (accessibilityTitleLong.length > 60) {
|
||||
return accessibilityTitleShort
|
||||
}
|
||||
return accessibilityTitleLong
|
||||
case additionalHotelData.meetingRooms.nameInUrl:
|
||||
const meetingsTitleLong = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"Meetings & conferences at {hotelName} in {destination}",
|
||||
},
|
||||
{ hotelName, destination }
|
||||
)
|
||||
const meetingsTitleShort = intl.formatMessage(
|
||||
{ defaultMessage: "Meetings & conferences at {hotelName}" },
|
||||
{ hotelName }
|
||||
)
|
||||
|
||||
if (meetingsTitleLong.length > 60) {
|
||||
return meetingsTitleShort
|
||||
}
|
||||
return meetingsTitleLong
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export async function getHotelPageTitle(data: RawMetadataSchema) {
|
||||
const intl = await getIntl()
|
||||
const { subpageUrl, hotelData, additionalHotelData, hotelRestaurants } = data
|
||||
if (!hotelData) {
|
||||
return null
|
||||
}
|
||||
|
||||
const hotelName = hotelData.name
|
||||
const destination = hotelData.translatedCityName
|
||||
|
||||
if (subpageUrl) {
|
||||
const subpageTitle = await getSubpageTitle(
|
||||
subpageUrl,
|
||||
additionalHotelData,
|
||||
hotelRestaurants,
|
||||
hotelName,
|
||||
destination
|
||||
)
|
||||
|
||||
return subpageTitle
|
||||
}
|
||||
|
||||
return intl.formatMessage(
|
||||
{ defaultMessage: "Stay at {hotelName} | Hotel in {destination}" },
|
||||
{ hotelName, destination }
|
||||
)
|
||||
}
|
||||
79
apps/scandic-web/utils/metadata/title/index.ts
Normal file
79
apps/scandic-web/utils/metadata/title/index.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { PageContentTypeEnum } from "@scandic-hotels/trpc/enums/contentType"
|
||||
|
||||
import {
|
||||
getDestinationFilterSeoMetaTitle,
|
||||
getDestinationPageTitle,
|
||||
} from "./destinationPage"
|
||||
import { getHotelPageTitle } from "./hotelPage"
|
||||
|
||||
import type { RawMetadataSchema } from "@scandic-hotels/trpc/routers/contentstack/metadata/output"
|
||||
|
||||
function getTitleSuffix(contentType: string) {
|
||||
switch (contentType) {
|
||||
case PageContentTypeEnum.contentPage:
|
||||
case PageContentTypeEnum.collectionPage:
|
||||
case PageContentTypeEnum.campaignPage:
|
||||
case PageContentTypeEnum.campaignOverviewPage:
|
||||
case PageContentTypeEnum.destinationOverviewPage:
|
||||
case PageContentTypeEnum.destinationCityPage:
|
||||
case PageContentTypeEnum.destinationCountryPage:
|
||||
return " | Scandic Hotels"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTitle(data: RawMetadataSchema) {
|
||||
const suffix = getTitleSuffix(data.system.content_type_uid)
|
||||
const metadata = data.web?.seo_metadata
|
||||
const isDestinationPage = [
|
||||
PageContentTypeEnum.destinationCityPage,
|
||||
PageContentTypeEnum.destinationCountryPage,
|
||||
].includes(data.system.content_type_uid as PageContentTypeEnum)
|
||||
|
||||
if (isDestinationPage) {
|
||||
const destinationFilterSeoMetaTitle = getDestinationFilterSeoMetaTitle(
|
||||
data,
|
||||
suffix
|
||||
)
|
||||
if (destinationFilterSeoMetaTitle) {
|
||||
return destinationFilterSeoMetaTitle
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata?.title) {
|
||||
return `${metadata.title}${suffix}`
|
||||
}
|
||||
|
||||
let title: string | null = null
|
||||
|
||||
switch (data.system.content_type_uid) {
|
||||
case PageContentTypeEnum.hotelPage:
|
||||
title = await getHotelPageTitle(data)
|
||||
break
|
||||
case PageContentTypeEnum.destinationCityPage:
|
||||
title = await getDestinationPageTitle(data, "city", suffix)
|
||||
break
|
||||
case PageContentTypeEnum.destinationCountryPage:
|
||||
title = await getDestinationPageTitle(data, "country", suffix)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if (title) {
|
||||
return title
|
||||
}
|
||||
|
||||
// Fallback titles from contentstack content
|
||||
if (data.web?.breadcrumbs?.title) {
|
||||
return `${data.web.breadcrumbs.title}${suffix}`
|
||||
}
|
||||
if (data.heading) {
|
||||
return `${data.heading}${suffix}`
|
||||
}
|
||||
if (data.header?.heading) {
|
||||
return `${data.header.heading}${suffix}`
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user