import { createCounter } from "@scandic-hotels/common/telemetry" import { GetHotelPageCount } from "../../../graphql/Query/HotelPage/HotelPageCount.graphql" import { GetHotelPageUrls } from "../../../graphql/Query/HotelPage/HotelPageUrl.graphql" import { request } from "../../../graphql/request" import { batchedHotelPageUrlsSchema, hotelPageCountSchema } from "./output" import type { Lang } from "@scandic-hotels/common/constants/language" import type { Campaigns } from "../../../types/campaignPage" import type { GetHotelPageCountData, GetHotelPageUrlsData, } from "../../../types/hotelPage" export async function getHotelPageCount(lang: Lang) { const getHotelPageCountCounter = createCounter( "trpc.contentstack", "hotelPageCount.get" ) const metricsGetHotelPageCount = getHotelPageCountCounter.init({ lang }) metricsGetHotelPageCount.start() const response = await request( GetHotelPageCount, { locale: lang, }, { key: `${lang}:hotel_page_count`, ttl: "max", } ) if (!response.data) { metricsGetHotelPageCount.noDataError() return 0 } const validatedResponse = hotelPageCountSchema.safeParse(response.data) if (!validatedResponse.success) { metricsGetHotelPageCount.validationError(validatedResponse.error) return 0 } metricsGetHotelPageCount.success() return validatedResponse.data } export async function getHotelPageUrls(lang: Lang) { const getHotelPageUrlsCounter = createCounter( "trpc.contentstack", "hotelPageUrls.get" ) const metricsGetHotelPageUrls = getHotelPageUrlsCounter.init({ lang }) metricsGetHotelPageUrls.start() const count = await getHotelPageCount(lang) if (count === 0) { return [] } // Calculating the amount of requests needed to fetch all hotel pages. // Contentstack has a limit of 100 items per request. // So we need to make multiple requests to fetch urls to all hotel pages. // The `batchRequest` function is not working here, because the arrayMerge is // used for other purposes. const amountOfRequests = Math.ceil(count / 100) const requests = Array.from({ length: amountOfRequests }).map((_, i) => ({ document: GetHotelPageUrls, variables: { locale: lang, skip: i * 100 }, cacheKey: `${lang}:hotel_page_urls_batch_${i}`, })) const batchedResponse = await Promise.all( requests.map((req) => request(req.document, req.variables, { key: req.cacheKey, ttl: "max", }) ) ) const validatedResponse = batchedHotelPageUrlsSchema.safeParse(batchedResponse) if (!validatedResponse.success) { metricsGetHotelPageUrls.validationError(validatedResponse.error) return [] } metricsGetHotelPageUrls.success() return validatedResponse.data } export function getSortedCampaigns( prioritizedCampaignUids: string[], campaigns: Campaigns ) { // First we'll sort on the list of prioritizedCampaignUids provided by the // hotel page. If the campaign is not in the prioritized list, it will be // added to the end of the sorted list using the default order from Contentstack. const prioritizedSet = new Set(prioritizedCampaignUids) const prioritized = prioritizedCampaignUids.flatMap((id) => { const found = campaigns.find((c) => c.id === id) return found ? [found] : [] }) const others = campaigns.filter((c) => !prioritizedSet.has(c.id)) const sortedCampaigns = [...prioritized, ...others] // Finally, we'll sort the campaigns by their sort_order, which gets higher priority // than the order by prioritizedCampaignUids. If sort_order is not provided, // we'll keep the original order. The higher the sort_order value, the higher the priority. return sortedCampaigns.sort((a, b) => { const aSortOrder = a.sort_order const bSortOrder = b.sort_order const aHasSortOrder = typeof aSortOrder === "number" const bHasSortOrder = typeof bSortOrder === "number" if (aHasSortOrder && bHasSortOrder) { // Descending order: higher sort_order comes first return bSortOrder - aSortOrder } if (aHasSortOrder && !bHasSortOrder) { return -1 } if (!aHasSortOrder && bHasSortOrder) { return 1 } return 0 }) }