Feat/SW-1519 remove deprecated hotel data from schema

* feat(SW-1519): Removed displayWebpage from hotel schema

* feat(SW-1519): Removed gallery from hotel schema

* feat(SW-1519): Removed conferencesAndMeetings from hotel schema

* feat(SW-1519): Removed healthAndWellness from hotel schema

* feat(SW-1519): Removed restaurantImages from hotel schema

* feat(SW-1519): Removed restaurantsOverviewPage from hotel schema


Approved-by: Fredrik Thorsson
Approved-by: Matilda Landström
This commit is contained in:
Erik Tiekstra
2025-03-19 06:28:13 +00:00
parent 2fc33966ac
commit b2b197b1ef
15 changed files with 76 additions and 1701 deletions

View File

@@ -73,7 +73,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
return notFound() return notFound()
} }
const jsonSchema = generateHotelSchema(hotelData.hotel) const jsonSchema = generateHotelSchema(hotelData)
const { faq, content, tabValues } = hotelPageData const { faq, content, tabValues } = hotelPageData
const { const {
name, name,

View File

@@ -75,7 +75,7 @@ export function getSubpageData(
: null, : null,
} }
case additionalData.meetingRooms.nameInUrl: case additionalData.meetingRooms.nameInUrl:
const meetingImage = hotel.conferencesAndMeetings?.heroImages[0] const meetingImage = additionalData.conferencesAndMeetings?.heroImages[0]
return { return {
elevatorPitch: hotel.hotelContent.texts.meetingDescription?.medium, elevatorPitch: hotel.hotelContent.texts.meetingDescription?.medium,
mainBody: additionalData.meetingRooms.mainBody, mainBody: additionalData.meetingRooms.mainBody,

View File

@@ -9,7 +9,7 @@ export function getHotelPins(
return [] return []
} }
return hotels.map(({ availability, hotel }) => { return hotels.map(({ availability, hotel, additionalData }) => {
const productType = availability.productType const productType = availability.productType
return { return {
coordinates: { coordinates: {
@@ -19,7 +19,8 @@ export function getHotelPins(
name: hotel.name, name: hotel.name,
publicPrice: productType?.public?.localPrice.pricePerNight ?? null, publicPrice: productType?.public?.localPrice.pricePerNight ?? null,
memberPrice: productType?.member?.localPrice.pricePerNight ?? null, memberPrice: productType?.member?.localPrice.pricePerNight ?? null,
redemptionPrice: productType?.redemption?.localPrice.pointsPerNight ?? null, redemptionPrice:
productType?.redemption?.localPrice.pointsPerNight ?? null,
rateType: rateType:
productType?.public?.rateType ?? productType?.member?.rateType ?? null, productType?.public?.rateType ?? productType?.member?.rateType ?? null,
currency: currency:
@@ -27,7 +28,10 @@ export function getHotelPins(
productType?.member?.localPrice.currency || productType?.member?.localPrice.currency ||
currencyValue || currencyValue ||
"N/A", "N/A",
images: [hotel.hotelContent.images, ...(hotel.gallery?.heroImages ?? [])], images: [
hotel.hotelContent.images,
...(additionalData.gallery?.heroImages ?? []),
],
amenities: hotel.detailedFacilities amenities: hotel.detailedFacilities
.map((facility) => ({ .map((facility) => ({
...facility, ...facility,

View File

@@ -46,7 +46,7 @@ export async function MyStay({ refId }: { refId: string }) {
return notFound() return notFound()
} }
const { booking, hotel, room } = bookingConfirmation const { booking, hotel, additionalData, room } = bookingConfirmation
const user = await getProfileSafely() const user = await getProfileSafely()
const bv = cookies().get("bv")?.value const bv = cookies().get("bv")?.value
const intl = await getIntl() const intl = await getIntl()
@@ -78,7 +78,7 @@ export async function MyStay({ refId }: { refId: string }) {
<Image <Image
className={styles.image} className={styles.image}
src={ src={
hotel.gallery?.heroImages[0]?.imageSizes.large ?? additionalData.gallery?.heroImages[0]?.imageSizes.large ??
hotel.galleryImages[0]?.imageSizes.large ?? hotel.galleryImages[0]?.imageSizes.large ??
"" ""
} }

View File

@@ -12,7 +12,7 @@ import type {
import type { CategorizedFilters } from "@/types/components/hotelReservation/selectHotel/hotelFilters" import type { CategorizedFilters } from "@/types/components/hotelReservation/selectHotel/hotelFilters"
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel" import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams" import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
import type { DetailedFacility, Hotel } from "@/types/hotel" import type { AdditionalData, DetailedFacility, Hotel } from "@/types/hotel"
import type { HotelsAvailabilityItem } from "@/types/trpc/routers/hotel/availability" import type { HotelsAvailabilityItem } from "@/types/trpc/routers/hotel/availability"
import type { import type {
HotelLocation, HotelLocation,
@@ -26,6 +26,7 @@ interface AvailabilityResponse {
export interface HotelResponse { export interface HotelResponse {
availability: HotelsAvailabilityItem availability: HotelsAvailabilityItem
hotel: Hotel hotel: Hotel
additionalData: AdditionalData
} }
type Result = AvailabilityResponse | null type Result = AvailabilityResponse | null
@@ -48,6 +49,7 @@ async function enhanceHotels(hotels: HotelsAvailabilityItem[]) {
return { return {
availability, availability,
hotel: hotelData.hotel, hotel: hotelData.hotel,
additionalData: hotelData.additionalData,
} }
}) })
) )
@@ -121,12 +123,12 @@ function sortAndFilterHotelsByAvailability(
(hotel.productType?.public && (hotel.productType?.public &&
currentAddedHotel?.productType?.public && currentAddedHotel?.productType?.public &&
hotel.productType.public.localPrice.pricePerNight < hotel.productType.public.localPrice.pricePerNight <
currentAddedHotel.productType.public.localPrice currentAddedHotel.productType.public.localPrice
.pricePerNight) || .pricePerNight) ||
(hotel.productType?.member && (hotel.productType?.member &&
currentAddedHotel?.productType?.member && currentAddedHotel?.productType?.member &&
hotel.productType.member.localPrice.pricePerNight < hotel.productType.member.localPrice.pricePerNight <
currentAddedHotel.productType.member.localPrice.pricePerNight) currentAddedHotel.productType.member.localPrice.pricePerNight)
) { ) {
availableHotels.set(hotel.hotelId, hotel) availableHotels.set(hotel.hotelId, hotel)
} }

View File

@@ -6,6 +6,7 @@ import { hotelreservation } from "@/constants/routes/hotelReservation"
import { env } from "@/env/server" import { env } from "@/env/server"
import { attributesSchema as hotelAttributesSchema } from "../../hotels/schemas/hotel" import { attributesSchema as hotelAttributesSchema } from "../../hotels/schemas/hotel"
import { additionalDataAttributesSchema } from "../../hotels/schemas/hotel/include/additionalData"
import { tempImageVaultAssetSchema } from "../schemas/imageVault" import { tempImageVaultAssetSchema } from "../schemas/imageVault"
import { systemSchema } from "../schemas/system" import { systemSchema } from "../schemas/system"
import { getDescription, getImage, getTitle } from "./utils" import { getDescription, getImage, getTitle } from "./utils"
@@ -96,7 +97,11 @@ export const rawMetadataSchema = z.object({
blocks: metaDataBlocksSchema, blocks: metaDataBlocksSchema,
hotel_page_id: z.string().optional().nullable(), hotel_page_id: z.string().optional().nullable(),
hotelData: hotelAttributesSchema hotelData: hotelAttributesSchema
.pick({ name: true, address: true, hotelContent: true, gallery: true }) .pick({ name: true, address: true, hotelContent: true })
.optional()
.nullable(),
additionalHotelData: additionalDataAttributesSchema
.pick({ gallery: true })
.optional() .optional()
.nullable(), .nullable(),
location: z.string().optional().nullable(), location: z.string().optional().nullable(),

View File

@@ -248,7 +248,12 @@ export const metadataQueryRouter = router({
metadata = await getTransformedMetadata({ metadata = await getTransformedMetadata({
...hotelPageData, ...hotelPageData,
hotelData: hotelData?.hotel, ...(hotelData
? {
hotelData: hotelData?.hotel,
additionalHotelData: hotelData?.additionalData,
}
: {}),
}) })
break break
case PageContentTypeEnum.startPage: case PageContentTypeEnum.startPage:

View File

@@ -157,8 +157,8 @@ export function getImage(data: RawMetadataSchema) {
const metadataImage = data.web?.seo_metadata?.seo_image const metadataImage = data.web?.seo_metadata?.seo_image
const heroImage = data.hero_image || data.header?.hero_image const heroImage = data.hero_image || data.header?.hero_image
const hotelImage = const hotelImage =
data.hotelData?.gallery?.heroImages?.[0] || data.additionalHotelData?.gallery?.heroImages?.[0] ||
data.hotelData?.gallery?.smallerImages?.[0] data.additionalHotelData?.gallery?.smallerImages?.[0]
// 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) {

View File

@@ -13,9 +13,6 @@ import { hotelContentSchema } from "./hotel/content"
import { detailedFacilitiesSchema } from "./hotel/detailedFacility" import { detailedFacilitiesSchema } from "./hotel/detailedFacility"
import { hotelFactsSchema } from "./hotel/facts" import { hotelFactsSchema } from "./hotel/facts"
import { healthFacilitiesSchema } from "./hotel/healthFacilities" import { healthFacilitiesSchema } from "./hotel/healthFacilities"
import { displayWebPageSchema } from "./hotel/include/additionalData/displayWebPage"
import { facilitySchema } from "./hotel/include/additionalData/facility"
import { gallerySchema } from "./hotel/include/additionalData/gallery"
import { includeSchema } from "./hotel/include/include" import { includeSchema } from "./hotel/include/include"
import { locationSchema } from "./hotel/location" import { locationSchema } from "./hotel/location"
import { merchantInformationSchema } from "./hotel/merchantInformation" import { merchantInformationSchema } from "./hotel/merchantInformation"
@@ -31,17 +28,13 @@ export const attributesSchema = z.object({
address: addressSchema, address: addressSchema,
cityId: nullableStringValidator, cityId: nullableStringValidator,
cityName: nullableStringValidator, cityName: nullableStringValidator,
conferencesAndMeetings: facilitySchema.nullish(),
contactInformation: contactInformationSchema, contactInformation: contactInformationSchema,
countryCode: nullableStringValidator, countryCode: nullableStringValidator,
detailedFacilities: detailedFacilitiesSchema, detailedFacilities: detailedFacilitiesSchema,
displayWebPage: displayWebPageSchema,
gallery: gallerySchema.nullish(),
galleryImages: z galleryImages: z
.array(imageSchema) .array(imageSchema)
.nullish() .nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : [])), .transform((arr) => (arr ? arr.filter(Boolean) : [])),
healthAndWellness: facilitySchema.nullish(),
healthFacilities: healthFacilitiesSchema, healthFacilities: healthFacilitiesSchema,
hotelContent: hotelContentSchema, hotelContent: hotelContentSchema,
hotelFacts: hotelFactsSchema, hotelFacts: hotelFactsSchema,
@@ -56,7 +49,6 @@ export const attributesSchema = z.object({
parking: nullableArrayObjectValidator(parkingSchema), parking: nullableArrayObjectValidator(parkingSchema),
pointsOfInterest: pointOfInterestsSchema, pointsOfInterest: pointOfInterestsSchema,
ratings: ratingsSchema, ratings: ratingsSchema,
restaurantImages: facilitySchema.nullish(),
rewardNight: rewardNightSchema, rewardNight: rewardNightSchema,
socialMedia: socialMediaSchema, socialMedia: socialMediaSchema,
specialAlerts: specialAlertsSchema, specialAlerts: specialAlertsSchema,

View File

@@ -3,7 +3,6 @@ import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator" import { nullableStringValidator } from "@/utils/zod/stringValidator"
import { imageSchema } from "../image" import { imageSchema } from "../image"
import { restaurantsOverviewPageSchema } from "./include/additionalData/restaurantsOverviewPage"
const descriptionSchema = z const descriptionSchema = z
.object({ .object({
@@ -21,6 +20,5 @@ const textsSchema = z.object({
export const hotelContentSchema = z.object({ export const hotelContentSchema = z.object({
images: imageSchema, images: imageSchema,
restaurantsOverviewPage: restaurantsOverviewPageSchema,
texts: textsSchema, texts: textsSchema,
}) })

View File

@@ -15,29 +15,31 @@ export const extraPageSchema = z.object({
nameInUrl: nullableStringValidator, nameInUrl: nullableStringValidator,
}) })
export const additionalDataAttributesSchema = z.object({
accessibility: facilitySchema.nullish(),
conferencesAndMeetings: facilitySchema.nullish(),
displayWebPage: displayWebPageSchema,
gallery: gallerySchema.nullish(),
healthAndFitness: extraPageSchema,
healthAndWellness: facilitySchema.nullish(),
hotelParking: extraPageSchema,
hotelRoomElevatorPitchText: nullableStringValidator,
hotelSpecialNeeds: extraPageSchema,
id: nullableStringValidator,
meetingRooms: extraPageSchema.merge(
z.object({
meetingOnlineLink: z.string().nullish(),
})
),
name: nullableStringValidator,
parkingImages: facilitySchema.nullish(),
restaurantImages: facilitySchema.nullish(),
restaurantsOverviewPage: restaurantsOverviewPageSchema,
specialNeedGroups: nullableArrayObjectValidator(specialNeedGroupSchema),
})
export const additionalDataSchema = z.object({ export const additionalDataSchema = z.object({
attributes: z.object({ attributes: additionalDataAttributesSchema,
accessibility: facilitySchema.nullish(),
conferencesAndMeetings: facilitySchema.nullish(),
displayWebPage: displayWebPageSchema,
gallery: gallerySchema.nullish(),
healthAndFitness: extraPageSchema,
healthAndWellness: facilitySchema.nullish(),
hotelParking: extraPageSchema,
hotelRoomElevatorPitchText: nullableStringValidator,
hotelSpecialNeeds: extraPageSchema,
id: nullableStringValidator,
meetingRooms: extraPageSchema.merge(
z.object({
meetingOnlineLink: z.string().nullish(),
})
),
name: nullableStringValidator,
parkingImages: facilitySchema.nullish(),
restaurantImages: facilitySchema.nullish(),
restaurantsOverviewPage: restaurantsOverviewPageSchema,
specialNeedGroups: nullableArrayObjectValidator(specialNeedGroupSchema),
}),
type: z.literal("additionalData"), type: z.literal("additionalData"),
}) })

View File

@@ -2,29 +2,21 @@ import { z } from "zod"
import { attributesSchema } from "@/server/routers/hotels/schemas/hotel" import { attributesSchema } from "@/server/routers/hotels/schemas/hotel"
import { displayWebPageSchema } from "./additionalData/displayWebPage"
export const nearbyHotelsSchema = z.object({ export const nearbyHotelsSchema = z.object({
attributes: z.lazy(() => attributes: z.lazy(() =>
z attributesSchema.pick({
.object({ address: true,
displayWebPage: displayWebPageSchema, cityId: true,
}) cityName: true,
.merge( detailedFacilities: true,
attributesSchema.pick({ hotelContent: true,
address: true, isActive: true,
cityId: true, isPublished: true,
cityName: true, location: true,
detailedFacilities: true, name: true,
hotelContent: true, operaId: true,
isActive: true, ratings: true,
isPublished: true, })
location: true,
name: true,
operaId: true,
ratings: true,
})
)
), ),
id: z.string(), id: z.string(),
type: z.literal("hotels"), type: z.literal("hotels"),

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
import type { Hotel } from "@/types/hotel" import type { AdditionalData, Hotel } from "@/types/hotel"
import type { MeetingRooms } from "../meetingRooms" import type { MeetingRooms } from "../meetingRooms"
export type MeetingsAndConferencesSidePeekProps = { export type MeetingsAndConferencesSidePeekProps = {
meetingFacilities: Hotel["conferencesAndMeetings"] meetingFacilities: AdditionalData["conferencesAndMeetings"]
descriptions: Hotel["hotelContent"]["texts"]["meetingDescription"] descriptions: Hotel["hotelContent"]["texts"]["meetingDescription"]
meetingRooms: MeetingRooms meetingRooms: MeetingRooms
meetingPageUrl: string | undefined meetingPageUrl: string | undefined

View File

@@ -7,7 +7,7 @@ import type {
WithContext, WithContext,
} from "schema-dts" } from "schema-dts"
import type { Hotel } from "@/types/hotel" import type { HotelData } from "@/types/hotel"
import type { Breadcrumbs } from "@/types/trpc/routers/contentstack/breadcrumbs" import type { Breadcrumbs } from "@/types/trpc/routers/contentstack/breadcrumbs"
export function generateBreadcrumbsSchema(breadcrumbs: Breadcrumbs) { export function generateBreadcrumbsSchema(breadcrumbs: Breadcrumbs) {
@@ -32,10 +32,13 @@ export function generateBreadcrumbsSchema(breadcrumbs: Breadcrumbs) {
} }
} }
export function generateHotelSchema(hotel: Hotel) { export function generateHotelSchema(hotelData: HotelData) {
const { hotel, additionalData } = hotelData
const ratings = hotel.ratings?.tripAdvisor const ratings = hotel.ratings?.tripAdvisor
const checkinData = hotel.hotelFacts.checkin const checkinData = hotel.hotelFacts.checkin
const image = hotel.gallery?.heroImages[0] || hotel.gallery?.smallerImages[0] const image =
additionalData.gallery?.heroImages[0] ||
additionalData.gallery?.smallerImages[0]
const facilities = hotel.detailedFacilities const facilities = hotel.detailedFacilities
const jsonLd: WithContext<HotelSchema> = { const jsonLd: WithContext<HotelSchema> = {
"@context": "https://schema.org", "@context": "https://schema.org",