feat(SW-201): Added hotel metadata
This commit is contained in:
@@ -509,6 +509,7 @@
|
|||||||
"to": "to",
|
"to": "to",
|
||||||
"uppercase letter": "uppercase letter",
|
"uppercase letter": "uppercase letter",
|
||||||
"{amount} out of {total}": "{amount} out of {total}",
|
"{amount} out of {total}": "{amount} out of {total}",
|
||||||
"{amount} {currency}": "{amount} {currency}",
|
"{card} ending with {cardno}": "{card} ending with {cardno}",
|
||||||
"{card} ending with {cardno}": "{card} ending with {cardno}"
|
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||||
|
"Stay at HOTEL_NAME | Hotel in DESTINATION": "Stay at {hotelName} | Hotel in {destination}"
|
||||||
}
|
}
|
||||||
|
|||||||
19
lib/graphql/Query/HotelPage/Metadata.graphql
Normal file
19
lib/graphql/Query/HotelPage/Metadata.graphql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#import "../../Fragments/Metadata.graphql"
|
||||||
|
#import "../../Fragments/System.graphql"
|
||||||
|
|
||||||
|
query GetHotelPageMetadata($locale: String!, $uid: String!) {
|
||||||
|
hotel_page(locale: $locale, uid: $uid) {
|
||||||
|
hotel_page_id
|
||||||
|
web {
|
||||||
|
breadcrumbs {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
seo_metadata {
|
||||||
|
...Metadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
|
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
|
||||||
import { getDescription, getImages, getTitle } from "./utils"
|
import { getDescription, getImage, getTitle } from "./utils"
|
||||||
|
|
||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
|
|
||||||
@@ -71,16 +71,26 @@ export const rawMetadataSchema = z.object({
|
|||||||
.nullable(),
|
.nullable(),
|
||||||
hero_image: tempImageVaultAssetSchema.nullable(),
|
hero_image: tempImageVaultAssetSchema.nullable(),
|
||||||
blocks: metaDataBlocksSchema,
|
blocks: metaDataBlocksSchema,
|
||||||
|
hotel_page_id: z.string().optional().nullable(),
|
||||||
|
hotelData: z
|
||||||
|
.object({
|
||||||
|
name: z.string(),
|
||||||
|
city: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
image: z.object({ url: z.string(), alt: z.string() }).nullable(),
|
||||||
|
})
|
||||||
|
.optional()
|
||||||
|
.nullable(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const metadataSchema = rawMetadataSchema.transform((data) => {
|
export const metadataSchema = rawMetadataSchema.transform(async (data) => {
|
||||||
const noIndex = !!data.web?.seo_metadata?.noindex
|
const noIndex = !!data.web?.seo_metadata?.noindex
|
||||||
|
|
||||||
const metadata: Metadata = {
|
const metadata: Metadata = {
|
||||||
title: getTitle(data),
|
title: await getTitle(data),
|
||||||
description: getDescription(data),
|
description: await getDescription(data),
|
||||||
openGraph: {
|
openGraph: {
|
||||||
images: getImages(data),
|
images: getImage(data),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ import { cache } from "react"
|
|||||||
import { GetAccountPageMetadata } from "@/lib/graphql/Query/AccountPage/Metadata.graphql"
|
import { GetAccountPageMetadata } from "@/lib/graphql/Query/AccountPage/Metadata.graphql"
|
||||||
import { GetCollectionPageMetadata } from "@/lib/graphql/Query/CollectionPage/Metadata.graphql"
|
import { GetCollectionPageMetadata } from "@/lib/graphql/Query/CollectionPage/Metadata.graphql"
|
||||||
import { GetContentPageMetadata } from "@/lib/graphql/Query/ContentPage/Metadata.graphql"
|
import { GetContentPageMetadata } from "@/lib/graphql/Query/ContentPage/Metadata.graphql"
|
||||||
|
import { GetHotelPageMetadata } from "@/lib/graphql/Query/HotelPage/Metadata.graphql"
|
||||||
import { GetLoyaltyPageMetadata } from "@/lib/graphql/Query/LoyaltyPage/Metadata.graphql"
|
import { GetLoyaltyPageMetadata } from "@/lib/graphql/Query/LoyaltyPage/Metadata.graphql"
|
||||||
import { request } from "@/lib/graphql/request"
|
import { request } from "@/lib/graphql/request"
|
||||||
import { notFound } from "@/server/errors/trpc"
|
import { notFound } from "@/server/errors/trpc"
|
||||||
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
|
import { contentStackUidWithServiceProcedure, router } from "@/server/trpc"
|
||||||
|
|
||||||
import { generateTag } from "@/utils/generateTag"
|
import { generateTag } from "@/utils/generateTag"
|
||||||
|
|
||||||
|
import { getHotelData } from "../../hotels/query"
|
||||||
import { metadataSchema } from "./output"
|
import { metadataSchema } from "./output"
|
||||||
import { affix } from "./utils"
|
import { affix } from "./utils"
|
||||||
|
|
||||||
@@ -86,10 +88,10 @@ const fetchMetadata = cache(async function fetchMemoizedMetadata<T>(
|
|||||||
return response.data
|
return response.data
|
||||||
})
|
})
|
||||||
|
|
||||||
function getTransformedMetadata(data: unknown) {
|
async function getTransformedMetadata(data: unknown) {
|
||||||
transformMetadataCounter.add(1)
|
transformMetadataCounter.add(1)
|
||||||
console.info("contentstack.metadata transform start")
|
console.info("contentstack.metadata transform start")
|
||||||
const validatedMetadata = metadataSchema.safeParse(data)
|
const validatedMetadata = await metadataSchema.safeParseAsync(data)
|
||||||
|
|
||||||
if (!validatedMetadata.success) {
|
if (!validatedMetadata.success) {
|
||||||
transformMetadataFailCounter.add(1, {
|
transformMetadataFailCounter.add(1, {
|
||||||
@@ -112,7 +114,7 @@ function getTransformedMetadata(data: unknown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const metadataQueryRouter = router({
|
export const metadataQueryRouter = router({
|
||||||
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
|
get: contentStackUidWithServiceProcedure.query(async ({ ctx }) => {
|
||||||
const variables = {
|
const variables = {
|
||||||
lang: ctx.lang,
|
lang: ctx.lang,
|
||||||
uid: ctx.uid,
|
uid: ctx.uid,
|
||||||
@@ -139,6 +141,38 @@ export const metadataQueryRouter = router({
|
|||||||
loyalty_page: RawMetadataSchema
|
loyalty_page: RawMetadataSchema
|
||||||
}>(GetLoyaltyPageMetadata, variables)
|
}>(GetLoyaltyPageMetadata, variables)
|
||||||
return getTransformedMetadata(loyaltyPageResponse.loyalty_page)
|
return getTransformedMetadata(loyaltyPageResponse.loyalty_page)
|
||||||
|
case PageTypeEnum.hotelPage:
|
||||||
|
const hotelPageResponse = await fetchMetadata<{
|
||||||
|
hotel_page: RawMetadataSchema
|
||||||
|
}>(GetHotelPageMetadata, variables)
|
||||||
|
const hotelPageData = hotelPageResponse.hotel_page
|
||||||
|
const hotelData = hotelPageData.hotel_page_id
|
||||||
|
? await getHotelData(
|
||||||
|
{ hotelId: hotelPageData.hotel_page_id, language: ctx.lang },
|
||||||
|
ctx.serviceToken
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
|
||||||
|
const rawHotelData = hotelPageData
|
||||||
|
|
||||||
|
if (hotelData?.data.attributes) {
|
||||||
|
const attributes = hotelData.data.attributes
|
||||||
|
const images = attributes.gallery?.smallerImages
|
||||||
|
|
||||||
|
rawHotelData.hotelData = {
|
||||||
|
name: attributes.name,
|
||||||
|
city: attributes.cityName,
|
||||||
|
description: attributes.hotelContent.texts.descriptions.short,
|
||||||
|
image: images?.length
|
||||||
|
? {
|
||||||
|
url: images[0].imageSizes.small,
|
||||||
|
alt: images[0].metaData.altText,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getTransformedMetadata(rawHotelData)
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { getIntl } from "@/i18n"
|
||||||
|
|
||||||
import { RTETypeEnum } from "@/types/rte/enums"
|
import { RTETypeEnum } from "@/types/rte/enums"
|
||||||
import type { RawMetadataSchema } from "@/types/trpc/routers/contentstack/metadata"
|
import type { RawMetadataSchema } from "@/types/trpc/routers/contentstack/metadata"
|
||||||
|
|
||||||
@@ -58,11 +60,18 @@ function truncateTextAfterLastPeriod(
|
|||||||
return `${maxLengthText}...`
|
return `${maxLengthText}...`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTitle(data: RawMetadataSchema) {
|
export async function getTitle(data: RawMetadataSchema) {
|
||||||
|
const intl = await getIntl()
|
||||||
const metadata = data.web?.seo_metadata
|
const metadata = data.web?.seo_metadata
|
||||||
if (metadata?.title) {
|
if (metadata?.title) {
|
||||||
return metadata.title
|
return metadata.title
|
||||||
}
|
}
|
||||||
|
if (data.hotelData) {
|
||||||
|
return intl.formatMessage(
|
||||||
|
{ id: "Stay at HOTEL_NAME | Hotel in DESTINATION" },
|
||||||
|
{ hotelName: data.hotelData.name, destination: data.hotelData.city }
|
||||||
|
)
|
||||||
|
}
|
||||||
if (data.web?.breadcrumbs?.title) {
|
if (data.web?.breadcrumbs?.title) {
|
||||||
return data.web.breadcrumbs.title
|
return data.web.breadcrumbs.title
|
||||||
}
|
}
|
||||||
@@ -75,11 +84,15 @@ export function getTitle(data: RawMetadataSchema) {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDescription(data: RawMetadataSchema) {
|
export async function getDescription(data: RawMetadataSchema) {
|
||||||
|
const intl = await getIntl()
|
||||||
const metadata = data.web?.seo_metadata
|
const metadata = data.web?.seo_metadata
|
||||||
if (metadata?.description) {
|
if (metadata?.description) {
|
||||||
return metadata.description
|
return metadata.description
|
||||||
}
|
}
|
||||||
|
if (data.hotelData) {
|
||||||
|
return data.hotelData.description
|
||||||
|
}
|
||||||
if (data.preamble) {
|
if (data.preamble) {
|
||||||
return truncateTextAfterLastPeriod(data.preamble)
|
return truncateTextAfterLastPeriod(data.preamble)
|
||||||
}
|
}
|
||||||
@@ -108,22 +121,23 @@ export function getImages(data: RawMetadataSchema) {
|
|||||||
|
|
||||||
// Currently we don't have the possibility to get smaller images from ImageVault (2024-11-15)
|
// Currently we don't have the possibility to get smaller images from ImageVault (2024-11-15)
|
||||||
if (metadataImage) {
|
if (metadataImage) {
|
||||||
return [
|
return {
|
||||||
{
|
url: metadataImage.url,
|
||||||
url: metadataImage.url,
|
alt: metadataImage.meta.alt || undefined,
|
||||||
width: metadataImage.dimensions.width,
|
width: metadataImage.dimensions.width,
|
||||||
height: metadataImage.dimensions.height,
|
height: metadataImage.dimensions.height,
|
||||||
},
|
}
|
||||||
]
|
}
|
||||||
|
if (data.hotelData?.image) {
|
||||||
|
return data.hotelData.image
|
||||||
}
|
}
|
||||||
if (heroImage) {
|
if (heroImage) {
|
||||||
return [
|
return {
|
||||||
{
|
url: heroImage.url,
|
||||||
url: heroImage.url,
|
alt: heroImage.meta.alt || undefined,
|
||||||
width: heroImage.dimensions.width,
|
width: heroImage.dimensions.width,
|
||||||
height: heroImage.dimensions.height,
|
height: heroImage.dimensions.height,
|
||||||
},
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
return []
|
return undefined
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user