Files
web/packages/trpc/lib/routers/hotels/services/getHotelsByHotelIds.ts
Matilda Landström 5986828580 Merged in feat/LOY-430-reward-nights (pull request #3295)
Feat/LOY-430 reward nights

* chore(LOY-430): add reward nights request and dynamic content

* chore(LOY-430): fix Reward Night component

* Refactor: use existing endpoint and add rewardNight data to that response instead


Approved-by: Linus Flood
2025-12-08 07:44:58 +00:00

114 lines
3.9 KiB
TypeScript

import { getCacheClient } from "@scandic-hotels/common/dataCache"
import { chunk } from "@scandic-hotels/common/utils/chunk"
import { getHotelPageUrls } from "../../contentstack/hotelPage/utils"
import { getHotel } from "./getHotel"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { HotelListingHotelData } from "../../../types/hotel"
export async function getHotelsByHotelIds({
hotelIds,
lang,
serviceToken,
contentType = "hotel",
}: {
hotelIds: string[]
lang: Lang
serviceToken: string
contentType?: "hotel" | "restaurant" | "meeting"
}) {
const cacheClient = await getCacheClient()
const cacheKey = `${lang}:getHotelsByHotelIds:hotels:${contentType}:${[...hotelIds].sort().join(",")}`
return await cacheClient.cacheOrGet(
cacheKey,
async () => {
const hotelPages = await getHotelPageUrls(lang)
const chunkedHotelIds = chunk(hotelIds, 10)
const hotels: HotelListingHotelData[] = []
for (const hotelIdChunk of chunkedHotelIds) {
const chunkedHotels = await Promise.all(
hotelIdChunk.map(async (hotelId) => {
const hotelResponse = await getHotel(
{ hotelId, language: lang, isCardOnlyPayment: false },
serviceToken
)
if (!hotelResponse) {
throw new Error(`Hotel not found: ${hotelId}`)
}
const hotelPage = hotelPages.find(
(page) => page.hotelId === hotelId
)
const { hotel, cities, additionalData } = hotelResponse
const content = {
description: hotel.hotelContent?.texts.descriptions?.short,
galleryImages: hotel.galleryImages,
url: hotelPage?.url ?? "",
openInNewTab: false,
}
if (contentType === "restaurant") {
const restaurantDescription =
additionalData?.restaurantsOverviewPage
.restaurantsContentDescriptionShort
const restaurantImages =
additionalData.restaurantImages?.heroImages
if (restaurantDescription) {
content.description = restaurantDescription
}
if (restaurantImages && restaurantImages.length > 0) {
content.galleryImages = restaurantImages
}
} else if (contentType === "meeting") {
const meetingDescription =
hotel.hotelContent.texts.meetingDescription?.short
const meetingImages =
additionalData?.conferencesAndMeetings?.heroImages
if (meetingDescription) {
content.description = meetingDescription
}
if (meetingImages && meetingImages.length > 0) {
content.galleryImages = meetingImages
}
}
const data: HotelListingHotelData = {
hotel: {
id: hotel.id,
countryCode: hotel.countryCode,
galleryImages: content.galleryImages,
name: hotel.name,
tripadvisor: hotel.ratings?.tripAdvisor?.rating || null,
detailedFacilities: hotel.detailedFacilities.sort(
(a, b) => b.sortOrder - a.sortOrder
),
location: hotel.location,
hotelType: hotel.hotelType,
type: hotel.type,
address: hotel.address,
cityIdentifier: cities[0]?.cityIdentifier || null,
description: content.description || null,
rewardNight: hotel.rewardNight,
},
url: content.url,
meetingUrl: additionalData.meetingRooms.meetingOnlineLink || null,
}
return data
})
)
hotels.push(...chunkedHotels)
}
return hotels.filter((hotel): hotel is HotelListingHotelData => !!hotel)
},
"1d"
)
}