Merged in fix/SW-1754-overview-page-rate-limit (pull request #1412)
fix(SW-1754): Fix rate limit issue on Destination Overview Page * fix(SW-1754): Fix rate limit issue on Destination Overview Page Approved-by: Matilda Landström
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { ArrowRightIcon } from "@/components/Icons"
|
import { ArrowRightIcon } from "@/components/Icons"
|
||||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import { getIntl } from "@/i18n"
|
import { getIntl } from "@/i18n"
|
||||||
|
|
||||||
import styles from "./destination.module.css"
|
import styles from "./destination.module.css"
|
||||||
@@ -27,13 +28,17 @@ export default async function Destination({
|
|||||||
<ul className={styles.citiesList}>
|
<ul className={styles.citiesList}>
|
||||||
{cities.map((city) => (
|
{cities.map((city) => (
|
||||||
<li key={city.id}>
|
<li key={city.id}>
|
||||||
<Link
|
{city.url ? (
|
||||||
href={city.url ? city.url : ""}
|
<Link
|
||||||
color="baseTextMediumContrast"
|
href={city.url}
|
||||||
textDecoration="underline"
|
color="baseTextMediumContrast"
|
||||||
>
|
textDecoration="underline"
|
||||||
{`${city.name} (${city.hotelCount})`}
|
>
|
||||||
</Link>
|
{`${city.name} (${city.hotelCount})`}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Body>{`${city.name} (${city.hotelCount})`}</Body>
|
||||||
|
)}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -13,6 +13,22 @@
|
|||||||
justify-items: start;
|
justify-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.imageWrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tripAdvisor {
|
||||||
|
position: absolute;
|
||||||
|
top: var(--Spacing-x2);
|
||||||
|
left: var(--Spacing-x2);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--Spacing-x-half);
|
||||||
|
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||||
|
padding: var(--Spacing-x-quarter) var(--Spacing-x1);
|
||||||
|
border-radius: var(--Corner-radius-Small);
|
||||||
|
}
|
||||||
|
|
||||||
.intro {
|
.intro {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: var(--Spacing-x-half);
|
gap: var(--Spacing-x-half);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Link from "next/link"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
||||||
import { ChevronRightSmallIcon } from "@/components/Icons"
|
import { ChevronRightSmallIcon, TripAdvisorIcon } from "@/components/Icons"
|
||||||
import HotelLogo from "@/components/Icons/Logos"
|
import HotelLogo from "@/components/Icons/Logos"
|
||||||
import ImageGallery from "@/components/ImageGallery"
|
import ImageGallery from "@/components/ImageGallery"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
@@ -34,13 +34,23 @@ export default function HotelListingItem({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={styles.container}>
|
<article className={styles.container}>
|
||||||
<ImageGallery
|
<div className={styles.imageWrapper}>
|
||||||
images={galleryImages}
|
<ImageGallery
|
||||||
title={intl.formatMessage(
|
images={galleryImages}
|
||||||
{ id: "{title} - Image gallery" },
|
title={intl.formatMessage(
|
||||||
{ title: hotel.name }
|
{ id: "{title} - Image gallery" },
|
||||||
|
{ title: hotel.name }
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{hotel.ratings?.tripAdvisor.rating && (
|
||||||
|
<div className={styles.tripAdvisor}>
|
||||||
|
<TripAdvisorIcon color="burgundy" />
|
||||||
|
<Caption color="burgundy">
|
||||||
|
{hotel.ratings.tripAdvisor.rating}
|
||||||
|
</Caption>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
</div>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<div className={styles.intro}>
|
<div className={styles.intro}>
|
||||||
<HotelLogo hotelId={hotel.operaId} hotelType={hotel.hotelType} />
|
<HotelLogo hotelId={hotel.operaId} hotelType={hotel.hotelType} />
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ query GetDestinationCityListData($locale: String!, $cityIdentifier: String!) {
|
|||||||
all_destination_city_page(
|
all_destination_city_page(
|
||||||
where: {
|
where: {
|
||||||
OR: [
|
OR: [
|
||||||
{ destination_settings: { city_sweden: $cityIdentifier } }
|
|
||||||
{ destination_settings: { city_denmark: $cityIdentifier } }
|
{ destination_settings: { city_denmark: $cityIdentifier } }
|
||||||
|
{ destination_settings: { city_finland: $cityIdentifier } }
|
||||||
|
{ destination_settings: { city_germany: $cityIdentifier } }
|
||||||
|
{ destination_settings: { city_norway: $cityIdentifier } }
|
||||||
|
{ destination_settings: { city_poland: $cityIdentifier } }
|
||||||
|
{ destination_settings: { city_sweden: $cityIdentifier } }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
locale: $locale
|
locale: $locale
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#import "../../Fragments/System.graphql"
|
||||||
|
|
||||||
|
query GetCityPageUrls($locale: String!) {
|
||||||
|
all_destination_city_page(locale: $locale) {
|
||||||
|
items {
|
||||||
|
url
|
||||||
|
destination_settings {
|
||||||
|
city_denmark
|
||||||
|
city_finland
|
||||||
|
city_germany
|
||||||
|
city_norway
|
||||||
|
city_poland
|
||||||
|
city_sweden
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#import "../../Fragments/System.graphql"
|
||||||
|
|
||||||
|
query GetCountryPageUrls($locale: String!) {
|
||||||
|
all_destination_country_page(locale: $locale) {
|
||||||
|
items {
|
||||||
|
url
|
||||||
|
destination_settings {
|
||||||
|
country
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,20 +33,6 @@ query GetDestinationOverviewPageRefs($locale: String!, $uid: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query GetCountryPageUrl($locale: String!, $country: String!) {
|
|
||||||
all_destination_country_page(
|
|
||||||
where: { destination_settings: { country: $country } }
|
|
||||||
locale: $locale
|
|
||||||
) {
|
|
||||||
items {
|
|
||||||
url
|
|
||||||
system {
|
|
||||||
...System
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
query GetDaDeEnUrlsDestinationOverviewPage($uid: String!) {
|
query GetDaDeEnUrlsDestinationOverviewPage($uid: String!) {
|
||||||
de: destination_overview_page(locale: "de", uid: $uid) {
|
de: destination_overview_page(locale: "de", uid: $uid) {
|
||||||
url
|
url
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#import "../../Fragments/System.graphql"
|
#import "../../Fragments/System.graphql"
|
||||||
|
|
||||||
query GetHotelPageUrl($locale: String!, $hotelId: String!) {
|
query GetHotelPageUrls($locale: String!) {
|
||||||
all_hotel_page(locale: $locale, where: { hotel_page_id: $hotelId }) {
|
all_hotel_page(locale: $locale) {
|
||||||
items {
|
items {
|
||||||
url
|
url
|
||||||
|
hotel_page_id
|
||||||
system {
|
system {
|
||||||
...System
|
...System
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,6 +185,56 @@ export const destinationCityPageSchema = z
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const cityPageUrlsSchema = z
|
||||||
|
.object({
|
||||||
|
all_destination_city_page: z.object({
|
||||||
|
items: z.array(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
url: z.string(),
|
||||||
|
destination_settings: z
|
||||||
|
.object({
|
||||||
|
city_denmark: z.string().optional().nullable(),
|
||||||
|
city_finland: z.string().optional().nullable(),
|
||||||
|
city_germany: z.string().optional().nullable(),
|
||||||
|
city_poland: z.string().optional().nullable(),
|
||||||
|
city_norway: z.string().optional().nullable(),
|
||||||
|
city_sweden: z.string().optional().nullable(),
|
||||||
|
})
|
||||||
|
.transform(
|
||||||
|
({
|
||||||
|
city_denmark,
|
||||||
|
city_finland,
|
||||||
|
city_germany,
|
||||||
|
city_norway,
|
||||||
|
city_poland,
|
||||||
|
city_sweden,
|
||||||
|
}) => {
|
||||||
|
const cities = [
|
||||||
|
city_denmark,
|
||||||
|
city_finland,
|
||||||
|
city_germany,
|
||||||
|
city_poland,
|
||||||
|
city_norway,
|
||||||
|
city_sweden,
|
||||||
|
].filter((city): city is string => Boolean(city))
|
||||||
|
|
||||||
|
return { city: cities[0] }
|
||||||
|
}
|
||||||
|
),
|
||||||
|
system: systemSchema,
|
||||||
|
})
|
||||||
|
.transform((data) => {
|
||||||
|
return {
|
||||||
|
city: data.destination_settings.city,
|
||||||
|
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.transform(({ all_destination_city_page }) => all_destination_city_page.items)
|
||||||
|
|
||||||
/** REFS */
|
/** REFS */
|
||||||
const destinationCityPageContentRefs = z
|
const destinationCityPageContentRefs = z
|
||||||
.object({
|
.object({
|
||||||
|
|||||||
@@ -21,3 +21,13 @@ export const getDestinationCityPageSuccessCounter = meter.createCounter(
|
|||||||
export const getDestinationCityPageFailCounter = meter.createCounter(
|
export const getDestinationCityPageFailCounter = meter.createCounter(
|
||||||
"trpc.contentstack.destinationCityPage.get-fail"
|
"trpc.contentstack.destinationCityPage.get-fail"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const getCityPageUrlsCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.cityPageUrls.get"
|
||||||
|
)
|
||||||
|
export const getCityPageUrlsSuccessCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.cityPageUrls.get-success"
|
||||||
|
)
|
||||||
|
export const getCityPageUrlsFailCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.cityPageUrls.get-fail"
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,8 +1,21 @@
|
|||||||
|
import { GetCityPageUrls } from "@/lib/graphql/Query/DestinationCityPage/DestinationCityPageUrl.graphql"
|
||||||
|
import { request } from "@/lib/graphql/request"
|
||||||
|
|
||||||
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
|
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
|
||||||
|
|
||||||
|
import { cityPageUrlsSchema } from "./output"
|
||||||
|
import {
|
||||||
|
getCityPageUrlsCounter,
|
||||||
|
getCityPageUrlsFailCounter,
|
||||||
|
getCityPageUrlsSuccessCounter,
|
||||||
|
} from "./telemetry"
|
||||||
|
|
||||||
import { DestinationCityPageEnum } from "@/types/enums/destinationCityPage"
|
import { DestinationCityPageEnum } from "@/types/enums/destinationCityPage"
|
||||||
import type { System } from "@/types/requests/system"
|
import type { System } from "@/types/requests/system"
|
||||||
import type { DestinationCityPageRefs } from "@/types/trpc/routers/contentstack/destinationCityPage"
|
import type {
|
||||||
|
DestinationCityPageRefs,
|
||||||
|
GetCityPageUrlsData,
|
||||||
|
} from "@/types/trpc/routers/contentstack/destinationCityPage"
|
||||||
import type { Lang } from "@/constants/languages"
|
import type { Lang } from "@/constants/languages"
|
||||||
|
|
||||||
export function generatePageTags(
|
export function generatePageTags(
|
||||||
@@ -51,3 +64,62 @@ export function getConnections({
|
|||||||
|
|
||||||
return connections
|
return connections
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getCityPageUrls(lang: Lang) {
|
||||||
|
getCityPageUrlsCounter.add(1, { lang })
|
||||||
|
console.info(
|
||||||
|
"contentstack.cityPageUrls start",
|
||||||
|
JSON.stringify({ query: { lang } })
|
||||||
|
)
|
||||||
|
const tag = `${lang}:city_page_urls`
|
||||||
|
const response = await request<GetCityPageUrlsData>(
|
||||||
|
GetCityPageUrls,
|
||||||
|
{
|
||||||
|
locale: lang,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cache: "force-cache",
|
||||||
|
next: {
|
||||||
|
tags: [tag],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!response.data) {
|
||||||
|
getCityPageUrlsFailCounter.add(1, {
|
||||||
|
lang,
|
||||||
|
error_type: "not_found",
|
||||||
|
error: `Destination city pages not found for lang: ${lang}`,
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"contentstack.cityPageUrls not found error",
|
||||||
|
JSON.stringify({ query: { lang } })
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const validatedResponse = cityPageUrlsSchema.safeParse(response.data)
|
||||||
|
|
||||||
|
if (!validatedResponse.success) {
|
||||||
|
getCityPageUrlsFailCounter.add(1, {
|
||||||
|
lang,
|
||||||
|
error_type: "validation_error",
|
||||||
|
error: JSON.stringify(validatedResponse.error),
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"contentstack.cityPageUrls validation error",
|
||||||
|
JSON.stringify({
|
||||||
|
query: { lang },
|
||||||
|
error: validatedResponse.error,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
getCityPageUrlsSuccessCounter.add(1, { lang })
|
||||||
|
console.info(
|
||||||
|
"contentstack.cityPageUrls success",
|
||||||
|
JSON.stringify({ query: { lang } })
|
||||||
|
)
|
||||||
|
|
||||||
|
return validatedResponse.data
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { discriminatedUnionArray } from "@/lib/discriminatedUnion"
|
import { discriminatedUnionArray } from "@/lib/discriminatedUnion"
|
||||||
|
|
||||||
|
import { removeMultipleSlashes } from "@/utils/url"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
accordionRefsSchema,
|
accordionRefsSchema,
|
||||||
accordionSchema,
|
accordionSchema,
|
||||||
@@ -120,6 +122,31 @@ export const destinationCountryPageSchema = z
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const countryPageUrlsSchema = z
|
||||||
|
.object({
|
||||||
|
all_destination_country_page: z.object({
|
||||||
|
items: z.array(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
url: z.string(),
|
||||||
|
destination_settings: z.object({
|
||||||
|
country: z.string(),
|
||||||
|
}),
|
||||||
|
system: systemSchema,
|
||||||
|
})
|
||||||
|
.transform((data) => {
|
||||||
|
return {
|
||||||
|
country: data.destination_settings.country,
|
||||||
|
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.transform(
|
||||||
|
({ all_destination_country_page }) => all_destination_country_page.items
|
||||||
|
)
|
||||||
|
|
||||||
/** REFS */
|
/** REFS */
|
||||||
const destinationCountryPageContentRefs = z
|
const destinationCountryPageContentRefs = z
|
||||||
.object({
|
.object({
|
||||||
|
|||||||
@@ -31,3 +31,15 @@ export const getCityListDataSuccessCounter = meter.createCounter(
|
|||||||
export const getCityListDataFailCounter = meter.createCounter(
|
export const getCityListDataFailCounter = meter.createCounter(
|
||||||
"trpc.contentstack.cityListData.get-fail"
|
"trpc.contentstack.cityListData.get-fail"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const getCountryPageUrlsCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.getCountryPageUrls"
|
||||||
|
)
|
||||||
|
|
||||||
|
export const getCountryPageUrlsSuccessCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.getCountryPageUrls-success"
|
||||||
|
)
|
||||||
|
|
||||||
|
export const getCountryPageUrlsFailCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.getCountryPageUrls-fail"
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
import { GetDestinationCityListData } from "@/lib/graphql/Query/DestinationCityPage/DestinationCityListData.graphql"
|
import { GetDestinationCityListData } from "@/lib/graphql/Query/DestinationCityPage/DestinationCityListData.graphql"
|
||||||
|
import { GetCountryPageUrls } from "@/lib/graphql/Query/DestinationCountryPage/DestinationCountryPageUrl.graphql"
|
||||||
import { request } from "@/lib/graphql/request"
|
import { request } from "@/lib/graphql/request"
|
||||||
import { toApiLang } from "@/server/utils"
|
import { toApiLang } from "@/server/utils"
|
||||||
|
|
||||||
@@ -7,10 +8,14 @@ import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
|
|||||||
|
|
||||||
import { getCitiesByCountry } from "../../hotels/utils"
|
import { getCitiesByCountry } from "../../hotels/utils"
|
||||||
import { destinationCityListDataSchema } from "../destinationCityPage/output"
|
import { destinationCityListDataSchema } from "../destinationCityPage/output"
|
||||||
|
import { countryPageUrlsSchema } from "./output"
|
||||||
import {
|
import {
|
||||||
getCityListDataCounter,
|
getCityListDataCounter,
|
||||||
getCityListDataFailCounter,
|
getCityListDataFailCounter,
|
||||||
getCityListDataSuccessCounter,
|
getCityListDataSuccessCounter,
|
||||||
|
getCountryPageUrlsCounter,
|
||||||
|
getCountryPageUrlsFailCounter,
|
||||||
|
getCountryPageUrlsSuccessCounter,
|
||||||
} from "./telemetry"
|
} from "./telemetry"
|
||||||
|
|
||||||
import { ApiCountry, type Country } from "@/types/enums/country"
|
import { ApiCountry, type Country } from "@/types/enums/country"
|
||||||
@@ -18,7 +23,10 @@ import { DestinationCountryPageEnum } from "@/types/enums/destinationCountryPage
|
|||||||
import type { RequestOptionsWithOutBody } from "@/types/fetch"
|
import type { RequestOptionsWithOutBody } from "@/types/fetch"
|
||||||
import type { System } from "@/types/requests/system"
|
import type { System } from "@/types/requests/system"
|
||||||
import type { GetDestinationCityListDataResponse } from "@/types/trpc/routers/contentstack/destinationCityPage"
|
import type { GetDestinationCityListDataResponse } from "@/types/trpc/routers/contentstack/destinationCityPage"
|
||||||
import type { DestinationCountryPageRefs } from "@/types/trpc/routers/contentstack/destinationCountryPage"
|
import type {
|
||||||
|
DestinationCountryPageRefs,
|
||||||
|
GetCountryPageUrlsData,
|
||||||
|
} from "@/types/trpc/routers/contentstack/destinationCountryPage"
|
||||||
import type { Lang } from "@/constants/languages"
|
import type { Lang } from "@/constants/languages"
|
||||||
|
|
||||||
export function generatePageTags(
|
export function generatePageTags(
|
||||||
@@ -178,3 +186,66 @@ export async function getCityPages(
|
|||||||
.flat()
|
.flat()
|
||||||
.filter((city): city is NonNullable<typeof city> => !!city)
|
.filter((city): city is NonNullable<typeof city> => !!city)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getCountryPageUrls(lang: Lang) {
|
||||||
|
getCountryPageUrlsCounter.add(1, { lang })
|
||||||
|
console.info(
|
||||||
|
"contentstack.countryPageUrls start",
|
||||||
|
JSON.stringify({ query: { lang } })
|
||||||
|
)
|
||||||
|
|
||||||
|
const tag = `${lang}:country_page_urls`
|
||||||
|
const response = await request<GetCountryPageUrlsData>(
|
||||||
|
GetCountryPageUrls,
|
||||||
|
{
|
||||||
|
locale: lang,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cache: "force-cache",
|
||||||
|
next: {
|
||||||
|
tags: [tag],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!response.data) {
|
||||||
|
getCountryPageUrlsFailCounter.add(1, {
|
||||||
|
lang,
|
||||||
|
error_type: "not_found",
|
||||||
|
error: `Country pages not found for lang: ${lang}`,
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"contentstack.countryPageUrls not found error",
|
||||||
|
JSON.stringify({ query: { lang } })
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const validatedCountryPageUrls = countryPageUrlsSchema.safeParse(
|
||||||
|
response.data
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!validatedCountryPageUrls.success) {
|
||||||
|
getCountryPageUrlsFailCounter.add(1, {
|
||||||
|
lang,
|
||||||
|
error_type: "validation_error",
|
||||||
|
error: JSON.stringify(validatedCountryPageUrls.error),
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"contentstack.countryPageUrls validation error",
|
||||||
|
JSON.stringify({
|
||||||
|
query: { lang },
|
||||||
|
error: validatedCountryPageUrls.error,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
getCountryPageUrlsSuccessCounter.add(1, { lang })
|
||||||
|
console.info(
|
||||||
|
"contentstack.countryPageUrls success",
|
||||||
|
JSON.stringify({ query: { lang } })
|
||||||
|
)
|
||||||
|
|
||||||
|
return validatedCountryPageUrls.data
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { discriminatedUnionArray } from "@/lib/discriminatedUnion"
|
import { discriminatedUnionArray } from "@/lib/discriminatedUnion"
|
||||||
|
|
||||||
import { removeMultipleSlashes } from "@/utils/url"
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
cardGalleryRefsSchema,
|
cardGalleryRefsSchema,
|
||||||
cardGallerySchema,
|
cardGallerySchema,
|
||||||
@@ -40,27 +38,6 @@ export const destinationOverviewPageSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const countryPageUrlSchema = z
|
|
||||||
.object({
|
|
||||||
all_destination_country_page: z.object({
|
|
||||||
items: z.array(
|
|
||||||
z
|
|
||||||
.object({
|
|
||||||
url: z.string(),
|
|
||||||
system: systemSchema,
|
|
||||||
})
|
|
||||||
.transform((data) => {
|
|
||||||
return {
|
|
||||||
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.transform(
|
|
||||||
({ all_destination_country_page }) => all_destination_country_page.items[0]
|
|
||||||
)
|
|
||||||
|
|
||||||
/** REFS */
|
/** REFS */
|
||||||
const destinationOverviewPageCardGalleryRef = z
|
const destinationOverviewPageCardGalleryRef = z
|
||||||
.object({
|
.object({
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ import {
|
|||||||
getCountries,
|
getCountries,
|
||||||
getHotelIdsByCityId,
|
getHotelIdsByCityId,
|
||||||
} from "../../hotels/utils"
|
} from "../../hotels/utils"
|
||||||
import { getCityListDataByCityIdentifier } from "../destinationCountryPage/utils"
|
import { getCityPageUrls } from "../destinationCityPage/utils"
|
||||||
|
import { getCountryPageUrls } from "../destinationCountryPage/utils"
|
||||||
import {
|
import {
|
||||||
destinationOverviewPageRefsSchema,
|
destinationOverviewPageRefsSchema,
|
||||||
destinationOverviewPageSchema,
|
destinationOverviewPageSchema,
|
||||||
@@ -32,7 +33,6 @@ import {
|
|||||||
getDestinationOverviewPageRefsSuccessCounter,
|
getDestinationOverviewPageRefsSuccessCounter,
|
||||||
getDestinationOverviewPageSuccessCounter,
|
getDestinationOverviewPageSuccessCounter,
|
||||||
} from "./telemetry"
|
} from "./telemetry"
|
||||||
import { getCountryPageUrl } from "./utils"
|
|
||||||
|
|
||||||
import type { DestinationsData } from "@/types/components/destinationOverviewPage/destinationsList/destinationsData"
|
import type { DestinationsData } from "@/types/components/destinationOverviewPage/destinationsList/destinationsData"
|
||||||
import {
|
import {
|
||||||
@@ -220,8 +220,8 @@ export const destinationOverviewPageQueryRouter = router({
|
|||||||
revalidate: env.CACHE_TIME_HOTELS,
|
revalidate: env.CACHE_TIME_HOTELS,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const countries = await getCountries(options, params, ctx.lang)
|
const countries = await getCountries(options, params, ctx.lang)
|
||||||
|
const countryPages = await getCountryPageUrls(ctx.lang)
|
||||||
|
|
||||||
if (!countries) {
|
if (!countries) {
|
||||||
return null
|
return null
|
||||||
@@ -237,6 +237,8 @@ export const destinationOverviewPageQueryRouter = router({
|
|||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const cityPages = await getCityPageUrls(ctx.lang)
|
||||||
|
|
||||||
const destinations: DestinationsData = await Promise.all(
|
const destinations: DestinationsData = await Promise.all(
|
||||||
Object.entries(citiesByCountry).map(async ([country, cities]) => {
|
Object.entries(citiesByCountry).map(async ([country, cities]) => {
|
||||||
const citiesWithHotelCount = await Promise.all(
|
const citiesWithHotelCount = await Promise.all(
|
||||||
@@ -252,29 +254,27 @@ export const destinationOverviewPageQueryRouter = router({
|
|||||||
hotelIdsParams
|
hotelIdsParams
|
||||||
)
|
)
|
||||||
|
|
||||||
let cityUrl
|
const cityPage = cityPages.find(
|
||||||
if (city.cityIdentifier) {
|
(cityPage) => cityPage.city === city.cityIdentifier
|
||||||
cityUrl = await getCityListDataByCityIdentifier(
|
)
|
||||||
ctx.lang,
|
|
||||||
city.cityIdentifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: city.id,
|
id: city.id,
|
||||||
name: city.name,
|
name: city.name,
|
||||||
hotelIds: hotels,
|
hotelIds: hotels,
|
||||||
hotelCount: hotels?.length ?? 0,
|
hotelCount: hotels?.length ?? 0,
|
||||||
url: cityUrl?.url,
|
url: cityPage?.url,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
const countryUrl = await getCountryPageUrl(ctx.lang, country)
|
const countryPage = countryPages.find(
|
||||||
|
(countryPage) => countryPage.country === country
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
country,
|
country,
|
||||||
countryUrl: countryUrl?.url,
|
countryUrl: countryPage?.url,
|
||||||
numberOfHotels: citiesWithHotelCount.reduce(
|
numberOfHotels: citiesWithHotelCount.reduce(
|
||||||
(acc, city) => acc + city.hotelCount,
|
(acc, city) => acc + city.hotelCount,
|
||||||
0
|
0
|
||||||
|
|||||||
@@ -21,15 +21,3 @@ export const getDestinationOverviewPageSuccessCounter = meter.createCounter(
|
|||||||
export const getDestinationOverviewPageFailCounter = meter.createCounter(
|
export const getDestinationOverviewPageFailCounter = meter.createCounter(
|
||||||
"trpc.contentstack.destinationOverviewPage.get-fail"
|
"trpc.contentstack.destinationOverviewPage.get-fail"
|
||||||
)
|
)
|
||||||
|
|
||||||
export const getCountryPageUrlCounter = meter.createCounter(
|
|
||||||
"trpc.contentstack.getCountryPageUrl"
|
|
||||||
)
|
|
||||||
|
|
||||||
export const getCountryPageUrlSuccessCounter = meter.createCounter(
|
|
||||||
"trpc.contentstack.getCountryPageUrl-success"
|
|
||||||
)
|
|
||||||
|
|
||||||
export const getCountryPageUrlFailCounter = meter.createCounter(
|
|
||||||
"trpc.contentstack.getCountryPageUrl-fail"
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
import { GetCountryPageUrl } from "@/lib/graphql/Query/DestinationOverviewPage/DestinationOverviewPage.graphql"
|
|
||||||
import { request } from "@/lib/graphql/request"
|
|
||||||
|
|
||||||
import { countryPageUrlSchema } from "./output"
|
|
||||||
import {
|
|
||||||
getCountryPageUrlCounter,
|
|
||||||
getCountryPageUrlFailCounter,
|
|
||||||
getCountryPageUrlSuccessCounter,
|
|
||||||
} from "./telemetry"
|
|
||||||
|
|
||||||
import type { GetCountryPageUrlData } from "@/types/trpc/routers/contentstack/destinationOverviewPage"
|
|
||||||
import type { Lang } from "@/constants/languages"
|
|
||||||
|
|
||||||
export async function getCountryPageUrl(lang: Lang, country: string) {
|
|
||||||
getCountryPageUrlCounter.add(1, { lang, country })
|
|
||||||
console.info(
|
|
||||||
"contentstack.countryPageUrl start",
|
|
||||||
JSON.stringify({ query: { lang, country } })
|
|
||||||
)
|
|
||||||
|
|
||||||
const tag = `${lang}:country_page_url:${country}`
|
|
||||||
const response = await request<GetCountryPageUrlData>(
|
|
||||||
GetCountryPageUrl,
|
|
||||||
{
|
|
||||||
locale: lang,
|
|
||||||
country,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cache: "force-cache",
|
|
||||||
next: {
|
|
||||||
tags: [tag],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!response.data) {
|
|
||||||
getCountryPageUrlFailCounter.add(1, {
|
|
||||||
lang,
|
|
||||||
country,
|
|
||||||
error_type: "not_found",
|
|
||||||
error: `Country page not found for country: ${country}`,
|
|
||||||
})
|
|
||||||
console.error(
|
|
||||||
"contentstack.countryPageUrl not found error",
|
|
||||||
JSON.stringify({ query: { lang, country } })
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const validatedCountryPageUrl = countryPageUrlSchema.safeParse(response.data)
|
|
||||||
|
|
||||||
if (!validatedCountryPageUrl.success) {
|
|
||||||
getCountryPageUrlFailCounter.add(1, {
|
|
||||||
lang,
|
|
||||||
country,
|
|
||||||
error_type: "validation_error",
|
|
||||||
error: JSON.stringify(validatedCountryPageUrl.error),
|
|
||||||
})
|
|
||||||
console.error(
|
|
||||||
"contentstack.countryPageUrl validation error",
|
|
||||||
JSON.stringify({
|
|
||||||
query: { lang, country },
|
|
||||||
error: validatedCountryPageUrl.error,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
getCountryPageUrlSuccessCounter.add(1, { lang, country })
|
|
||||||
console.info(
|
|
||||||
"contentstack.countryPageUrl success",
|
|
||||||
JSON.stringify({ query: { lang, country } })
|
|
||||||
)
|
|
||||||
|
|
||||||
return validatedCountryPageUrl.data
|
|
||||||
}
|
|
||||||
@@ -116,25 +116,23 @@ export const hotelPageRefsSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const hotelPageUrlSchema = z
|
export const hotelPageUrlsSchema = z
|
||||||
.object({
|
.object({
|
||||||
all_hotel_page: z.object({
|
all_hotel_page: z.object({
|
||||||
items: z
|
items: z.array(
|
||||||
.array(
|
z
|
||||||
z.object({
|
.object({
|
||||||
url: z.string(),
|
url: z.string(),
|
||||||
|
hotel_page_id: z.string(),
|
||||||
system: systemSchema,
|
system: systemSchema,
|
||||||
})
|
})
|
||||||
)
|
.transform((data) => {
|
||||||
.max(1),
|
return {
|
||||||
|
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||||
|
hotelId: data.hotel_page_id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.transform((data) => {
|
.transform(({ all_hotel_page }) => all_hotel_page.items)
|
||||||
const page = data.all_hotel_page.items[0]
|
|
||||||
if (!page) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const lang = page.system.locale
|
|
||||||
return removeMultipleSlashes(`/${lang}/${page.url}`)
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ export const getHotelPageFailCounter = meter.createCounter(
|
|||||||
"trpc.contentstack.hotelPage.get-fail"
|
"trpc.contentstack.hotelPage.get-fail"
|
||||||
)
|
)
|
||||||
|
|
||||||
export const getHotelPageUrlCounter = meter.createCounter(
|
export const getHotelPageUrlsCounter = meter.createCounter(
|
||||||
"trpc.contentstack.hotelPageUrl.get"
|
"trpc.contentstack.hotelPageUrls.get"
|
||||||
)
|
)
|
||||||
export const getHotelPageUrlSuccessCounter = meter.createCounter(
|
export const getHotelPageUrlsSuccessCounter = meter.createCounter(
|
||||||
"trpc.contentstack.hotelPageUrl.get-success"
|
"trpc.contentstack.hotelPageUrls.get-success"
|
||||||
)
|
)
|
||||||
export const getHotelPageUrlFailCounter = meter.createCounter(
|
export const getHotelPageUrlsFailCounter = meter.createCounter(
|
||||||
"trpc.contentstack.hotelPageUrl.get-fail"
|
"trpc.contentstack.hotelPageUrls.get-fail"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,29 +1,25 @@
|
|||||||
import { GetHotelPageRefs } from "@/lib/graphql/Query/HotelPage/HotelPage.graphql"
|
import { GetHotelPageRefs } from "@/lib/graphql/Query/HotelPage/HotelPage.graphql"
|
||||||
import { GetHotelPageUrl } from "@/lib/graphql/Query/HotelPage/HotelPageUrl.graphql"
|
import { GetHotelPageUrls } from "@/lib/graphql/Query/HotelPage/HotelPageUrl.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 {
|
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
|
||||||
generateHotelUrlTag,
|
|
||||||
generateTag,
|
|
||||||
generateTagsFromSystem,
|
|
||||||
} from "@/utils/generateTag"
|
|
||||||
|
|
||||||
import { hotelPageRefsSchema, hotelPageUrlSchema } from "./output"
|
import { hotelPageRefsSchema, hotelPageUrlsSchema } from "./output"
|
||||||
import {
|
import {
|
||||||
getHotelPageRefsCounter,
|
getHotelPageRefsCounter,
|
||||||
getHotelPageRefsFailCounter,
|
getHotelPageRefsFailCounter,
|
||||||
getHotelPageRefsSuccessCounter,
|
getHotelPageRefsSuccessCounter,
|
||||||
getHotelPageUrlCounter,
|
getHotelPageUrlsCounter,
|
||||||
getHotelPageUrlFailCounter,
|
getHotelPageUrlsFailCounter,
|
||||||
getHotelPageUrlSuccessCounter,
|
getHotelPageUrlsSuccessCounter,
|
||||||
} from "./telemetry"
|
} from "./telemetry"
|
||||||
|
|
||||||
import { HotelPageEnum } from "@/types/enums/hotelPage"
|
import { HotelPageEnum } from "@/types/enums/hotelPage"
|
||||||
import type { System } from "@/types/requests/system"
|
import type { System } from "@/types/requests/system"
|
||||||
import type {
|
import type {
|
||||||
GetHotelPageRefsSchema,
|
GetHotelPageRefsSchema,
|
||||||
GetHotelPageUrlData,
|
GetHotelPageUrlsData,
|
||||||
HotelPageRefs,
|
HotelPageRefs,
|
||||||
} from "@/types/trpc/routers/contentstack/hotelPage"
|
} from "@/types/trpc/routers/contentstack/hotelPage"
|
||||||
import type { Lang } from "@/constants/languages"
|
import type { Lang } from "@/constants/languages"
|
||||||
@@ -136,63 +132,61 @@ export function getConnections({ hotel_page }: HotelPageRefs) {
|
|||||||
return connections
|
return connections
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getHotelPageUrl(lang: Lang, hotelId: string) {
|
export async function getHotelPageUrls(lang: Lang) {
|
||||||
getHotelPageUrlCounter.add(1, { lang, hotelId })
|
getHotelPageUrlsCounter.add(1, { lang })
|
||||||
console.info(
|
console.info(
|
||||||
"contentstack.hotelPageUrl start",
|
"contentstack.hotelPageUrls start",
|
||||||
JSON.stringify({ query: { lang, hotelId } })
|
JSON.stringify({ query: { lang } })
|
||||||
)
|
)
|
||||||
const response = await request<GetHotelPageUrlData>(
|
const tags = [`${lang}:hotel_page_urls`]
|
||||||
GetHotelPageUrl,
|
const response = await request<GetHotelPageUrlsData>(
|
||||||
|
GetHotelPageUrls,
|
||||||
{
|
{
|
||||||
locale: lang,
|
locale: lang,
|
||||||
hotelId,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cache: "force-cache",
|
cache: "force-cache",
|
||||||
next: {
|
next: {
|
||||||
tags: [generateHotelUrlTag(lang, hotelId)],
|
tags,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!response.data) {
|
if (!response.data) {
|
||||||
getHotelPageUrlFailCounter.add(1, {
|
getHotelPageUrlsFailCounter.add(1, {
|
||||||
lang,
|
lang,
|
||||||
hotelId,
|
|
||||||
error_type: "not_found",
|
error_type: "not_found",
|
||||||
error: `Hotel page not found for hotelId: ${hotelId}`,
|
error: `Hotel pages not found for lang: ${lang}`,
|
||||||
})
|
})
|
||||||
console.error(
|
console.error(
|
||||||
"contentstack.hotelPageUrl not found error",
|
"contentstack.hotelPageUrls not found error",
|
||||||
JSON.stringify({ query: { lang, hotelId } })
|
JSON.stringify({ query: { lang } })
|
||||||
)
|
)
|
||||||
return null
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatedHotelPageUrl = hotelPageUrlSchema.safeParse(response.data)
|
const validatedHotelPageUrls = hotelPageUrlsSchema.safeParse(response.data)
|
||||||
|
|
||||||
if (!validatedHotelPageUrl.success) {
|
if (!validatedHotelPageUrls.success) {
|
||||||
getHotelPageUrlFailCounter.add(1, {
|
getHotelPageUrlsFailCounter.add(1, {
|
||||||
lang,
|
lang,
|
||||||
hotelId,
|
|
||||||
error_type: "validation_error",
|
error_type: "validation_error",
|
||||||
error: JSON.stringify(validatedHotelPageUrl.error),
|
error: JSON.stringify(validatedHotelPageUrls.error),
|
||||||
})
|
})
|
||||||
console.error(
|
console.error(
|
||||||
"contentstack.hotelPageUrl validation error",
|
"contentstack.hotelPageUrls validation error",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: { lang, hotelId },
|
query: { lang },
|
||||||
error: validatedHotelPageUrl.error,
|
error: validatedHotelPageUrls.error,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
return null
|
return []
|
||||||
}
|
}
|
||||||
getHotelPageUrlSuccessCounter.add(1, { lang, hotelId })
|
getHotelPageUrlsSuccessCounter.add(1, { lang })
|
||||||
console.info(
|
console.info(
|
||||||
"contentstack.hotelPageUrl success",
|
"contentstack.hotelPageUrl success",
|
||||||
JSON.stringify({ query: { lang, hotelId } })
|
JSON.stringify({ query: { lang } })
|
||||||
)
|
)
|
||||||
|
|
||||||
return validatedHotelPageUrl.data
|
return validatedHotelPageUrls.data
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { toApiLang } from "@/server/utils"
|
|||||||
import { generateChildrenString } from "@/components/HotelReservation/utils"
|
import { generateChildrenString } from "@/components/HotelReservation/utils"
|
||||||
import { cache } from "@/utils/cache"
|
import { cache } from "@/utils/cache"
|
||||||
|
|
||||||
import { getHotelPageUrl } from "../contentstack/hotelPage/utils"
|
import { getHotelPageUrls } from "../contentstack/hotelPage/utils"
|
||||||
import { getVerifiedUser, parsedUser } from "../user/query"
|
import { getVerifiedUser, parsedUser } from "../user/query"
|
||||||
import { additionalDataSchema } from "./schemas/hotel/include/additionalData"
|
import { additionalDataSchema } from "./schemas/hotel/include/additionalData"
|
||||||
import { meetingRoomsSchema } from "./schemas/meetingRoom"
|
import { meetingRoomsSchema } from "./schemas/meetingRoom"
|
||||||
@@ -1100,21 +1100,21 @@ export const hotelQueryRouter = router({
|
|||||||
)
|
)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
const hotelPages = await getHotelPageUrls(language)
|
||||||
const hotels = await Promise.all(
|
const hotels = await Promise.all(
|
||||||
hotelsToFetch.map(async (hotelId) => {
|
hotelsToFetch.map(async (hotelId) => {
|
||||||
const [hotelData, url] = await Promise.all([
|
const hotelData = await getHotel(
|
||||||
getHotel(
|
{ hotelId, isCardOnlyPayment: false, language },
|
||||||
{ hotelId, isCardOnlyPayment: false, language },
|
ctx.serviceToken
|
||||||
ctx.serviceToken
|
)
|
||||||
),
|
const hotelPage = hotelPages.find(
|
||||||
getHotelPageUrl(language, hotelId),
|
(page) => page.hotelId === hotelId
|
||||||
])
|
)
|
||||||
|
|
||||||
return hotelData
|
return hotelData
|
||||||
? {
|
? {
|
||||||
...hotelData,
|
...hotelData,
|
||||||
url,
|
url: hotelPage?.url ?? null,
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { env } from "@/env/server"
|
|||||||
import * as api from "@/lib/api"
|
import * as api from "@/lib/api"
|
||||||
import { toApiLang } from "@/server/utils"
|
import { toApiLang } from "@/server/utils"
|
||||||
|
|
||||||
import { getHotelPageUrl } from "../contentstack/hotelPage/utils"
|
import { getHotelPageUrls } from "../contentstack/hotelPage/utils"
|
||||||
import { metrics } from "./metrics"
|
import { metrics } from "./metrics"
|
||||||
import {
|
import {
|
||||||
citiesByCountrySchema,
|
citiesByCountrySchema,
|
||||||
@@ -484,17 +484,15 @@ export async function getHotelsByHotelIds(
|
|||||||
lang: Lang,
|
lang: Lang,
|
||||||
serviceToken: string
|
serviceToken: string
|
||||||
) {
|
) {
|
||||||
|
const hotelPages = await getHotelPageUrls(lang)
|
||||||
const hotels = await Promise.all(
|
const hotels = await Promise.all(
|
||||||
hotelIds.map(async (hotelId) => {
|
hotelIds.map(async (hotelId) => {
|
||||||
const [hotelData, url] = await Promise.all([
|
const hotelData = await getHotel(
|
||||||
getHotel(
|
{ hotelId, language: lang, isCardOnlyPayment: false },
|
||||||
{ hotelId, language: lang, isCardOnlyPayment: false },
|
serviceToken
|
||||||
serviceToken
|
)
|
||||||
),
|
const hotelPage = hotelPages.find((page) => page.hotelId === hotelId)
|
||||||
getHotelPageUrl(lang, hotelId),
|
return hotelData ? { ...hotelData, url: hotelPage?.url ?? null } : null
|
||||||
])
|
|
||||||
|
|
||||||
return hotelData ? { ...hotelData, url } : null
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { z } from "zod"
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
blocksSchema,
|
blocksSchema,
|
||||||
|
cityPageUrlsSchema,
|
||||||
destinationCityListDataSchema,
|
destinationCityListDataSchema,
|
||||||
destinationCityPageRefsSchema,
|
destinationCityPageRefsSchema,
|
||||||
destinationCityPageSchema,
|
destinationCityPageSchema,
|
||||||
@@ -18,6 +19,10 @@ export interface GetDestinationCityListDataResponse
|
|||||||
|
|
||||||
export interface DestinationCityListData
|
export interface DestinationCityListData
|
||||||
extends z.output<typeof destinationCityListDataSchema> {}
|
extends z.output<typeof destinationCityListDataSchema> {}
|
||||||
|
export interface GetCityPageUrlsData
|
||||||
|
extends z.input<typeof cityPageUrlsSchema> {}
|
||||||
|
|
||||||
|
export interface CityPageUrlsData extends z.output<typeof cityPageUrlsSchema> {}
|
||||||
|
|
||||||
export interface DestinationCityListItem extends DestinationCityListData {
|
export interface DestinationCityListItem extends DestinationCityListData {
|
||||||
cityName: string
|
cityName: string
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { z } from "zod"
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
blocksSchema,
|
blocksSchema,
|
||||||
|
countryPageUrlsSchema,
|
||||||
destinationCountryPageRefsSchema,
|
destinationCountryPageRefsSchema,
|
||||||
destinationCountryPageSchema,
|
destinationCountryPageSchema,
|
||||||
} from "@/server/routers/contentstack/destinationCountryPage/output"
|
} from "@/server/routers/contentstack/destinationCountryPage/output"
|
||||||
@@ -19,3 +20,6 @@ export interface GetDestinationCountryPageRefsSchema
|
|||||||
|
|
||||||
export interface DestinationCountryPageRefs
|
export interface DestinationCountryPageRefs
|
||||||
extends z.output<typeof destinationCountryPageRefsSchema> {}
|
extends z.output<typeof destinationCountryPageRefsSchema> {}
|
||||||
|
|
||||||
|
export interface GetCountryPageUrlsData
|
||||||
|
extends z.input<typeof countryPageUrlsSchema> {}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import type { z } from "zod"
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
blocksSchema,
|
blocksSchema,
|
||||||
countryPageUrlSchema,
|
|
||||||
destinationOverviewPageRefsSchema,
|
destinationOverviewPageRefsSchema,
|
||||||
destinationOverviewPageSchema,
|
destinationOverviewPageSchema,
|
||||||
} from "@/server/routers/contentstack/destinationOverviewPage/output"
|
} from "@/server/routers/contentstack/destinationOverviewPage/output"
|
||||||
@@ -18,7 +17,4 @@ export interface GetDestinationOverviewPageRefsSchema
|
|||||||
export interface DestinationOverviewPageRefs
|
export interface DestinationOverviewPageRefs
|
||||||
extends z.output<typeof destinationOverviewPageRefsSchema> {}
|
extends z.output<typeof destinationOverviewPageRefsSchema> {}
|
||||||
|
|
||||||
export interface GetCountryPageUrlData
|
|
||||||
extends z.input<typeof countryPageUrlSchema> {}
|
|
||||||
|
|
||||||
export type Block = z.output<typeof blocksSchema>
|
export type Block = z.output<typeof blocksSchema>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type {
|
|||||||
contentBlock,
|
contentBlock,
|
||||||
hotelPageRefsSchema,
|
hotelPageRefsSchema,
|
||||||
hotelPageSchema,
|
hotelPageSchema,
|
||||||
hotelPageUrlSchema,
|
hotelPageUrlsSchema,
|
||||||
} from "@/server/routers/contentstack/hotelPage/output"
|
} from "@/server/routers/contentstack/hotelPage/output"
|
||||||
import type { activitiesCardSchema } from "@/server/routers/contentstack/schemas/blocks/activitiesCard"
|
import type { activitiesCardSchema } from "@/server/routers/contentstack/schemas/blocks/activitiesCard"
|
||||||
import type { spaPageSchema } from "@/server/routers/contentstack/schemas/blocks/spaPage"
|
import type { spaPageSchema } from "@/server/routers/contentstack/schemas/blocks/spaPage"
|
||||||
@@ -22,7 +22,6 @@ export interface GetHotelPageRefsSchema
|
|||||||
extends z.input<typeof hotelPageRefsSchema> {}
|
extends z.input<typeof hotelPageRefsSchema> {}
|
||||||
|
|
||||||
export interface HotelPageRefs extends z.output<typeof hotelPageRefsSchema> {}
|
export interface HotelPageRefs extends z.output<typeof hotelPageRefsSchema> {}
|
||||||
|
export interface GetHotelPageUrlsData
|
||||||
export interface GetHotelPageUrlData
|
extends z.input<typeof hotelPageUrlsSchema> {}
|
||||||
extends z.input<typeof hotelPageUrlSchema> {}
|
export type HotelPageUrls = z.output<typeof hotelPageUrlsSchema>
|
||||||
export type HotelPageUrl = z.output<typeof hotelPageUrlSchema>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user