feat(SW-1446): add Jump to functionality to Destination Overview Page

This commit is contained in:
Michael Zetterberg
2025-03-19 06:56:38 +01:00
parent 85a90baa12
commit 9e84da45bc
44 changed files with 3069 additions and 1297 deletions

View File

@@ -164,6 +164,10 @@ export const getLocationsInput = z.object({
lang: z.nativeEnum(Lang),
})
export const getLocationsUrlsInput = z.object({
lang: z.nativeEnum(Lang),
})
export const roomFeaturesInputSchema = z.object({
hotelId: z.string(),
startDate: z.string(),

View File

@@ -3,6 +3,8 @@ import { Lang } from "@/constants/languages"
import { env } from "@/env/server"
import * as api from "@/lib/api"
import { dt } from "@/lib/dt"
import { GetLocationsUrls } from "@/lib/graphql/Query/Locations/Locations.graphql"
import { request } from "@/lib/graphql/request"
import { badRequestError, unauthorizedError } from "@/server/errors/trpc"
import {
contentStackBaseWithServiceProcedure,
@@ -16,10 +18,15 @@ import { toApiLang } from "@/server/utils"
import { generateChildrenString } from "@/components/HotelReservation/utils"
import { getCacheClient } from "@/services/dataCache"
import { cache } from "@/utils/cache"
import { removeMultipleSlashes } from "@/utils/url"
import { getHotelPageUrls } from "../contentstack/hotelPage/utils"
import { getVerifiedUser } from "../user/query"
import { additionalDataSchema } from "./schemas/hotel/include/additionalData"
import {
type GetLocationsUrlsData,
locationsUrlsSchema,
} from "./schemas/location/urls"
import { meetingRoomsSchema } from "./schemas/meetingRoom"
import {
ancillaryPackageInputSchema,
@@ -32,6 +39,7 @@ import {
getHotelsByCSFilterInput,
getHotelsByHotelIdsAvailabilityInputSchema,
getLocationsInput,
getLocationsUrlsInput,
getMeetingRoomsInputSchema,
hotelInputSchema,
hotelsAvailabilityInputSchema,
@@ -55,6 +63,11 @@ import {
roomFeaturesSchema,
roomsAvailabilitySchema,
} from "./output"
import {
locationsUrlsCounter,
locationsUrlsFailCounter,
locationsUrlsSuccessCounter,
} from "./telemetry"
import tempRatesData from "./tempRatesData.json"
import {
getCitiesByCountry,
@@ -1505,6 +1518,79 @@ export const hotelQueryRouter = router({
"max"
)
}),
urls: publicProcedure
.input(getLocationsUrlsInput)
.query(async ({ input }) => {
const procedureName = "hotels.locations.urls"
const { lang } = input
locationsUrlsCounter.add(1, { lang })
console.info(
`${procedureName}: start`,
JSON.stringify({ query: { lang } })
)
const response = await request<GetLocationsUrlsData>(
GetLocationsUrls,
{ locale: lang },
{
key: `${lang}:${procedureName}`,
ttl: "max",
}
)
if (!response.data) {
locationsUrlsFailCounter.add(1, {
lang,
error_type: "no data",
response: JSON.stringify(response),
})
console.error(`${procedureName}: no data`, {
variables: { lang },
error_type: "no data",
response,
})
return null
}
const locationsUrls = locationsUrlsSchema.safeParse(response.data)
if (!locationsUrls.success) {
locationsUrlsFailCounter.add(1, {
lang,
error_type: "validation_error",
error: JSON.stringify(locationsUrls.error),
})
console.error(`${procedureName}: validation error`, {
variables: { lang },
error_type: "validation_error",
error: locationsUrls.error,
})
return null
}
locationsUrlsSuccessCounter.add(1, { lang })
console.info(`${procedureName}: success`, {
variables: { lang },
})
const { data } = locationsUrls
data.hotels = data.hotels.map((hotel) => {
hotel.url = removeMultipleSlashes(`/${lang}/${hotel.url}`)
return hotel
})
data.cities = data.cities.map((city) => {
city.url = removeMultipleSlashes(`/${lang}/${city.url}`)
return city
})
return locationsUrls.data
}),
}),
map: router({
city: serviceProcedure

View File

@@ -0,0 +1,68 @@
import { z } from "zod"
import { isDefined } from "@/server/utils"
export const locationsUrlsSchema = z.object({
hotels: z
.object({
items: z.array(
z.object({
id: z.string(),
url: z.string(),
})
),
})
.transform((data) => {
return data.items
}),
cities: z
.object({
items: z
.array(
z
.object({
id: z
.object({
da: z.string().nullish(),
de: z.string().nullish(),
en: z.string().nullish(),
fi: z.string().nullish(),
no: z.string().nullish(),
pl: z.string().nullish(),
sv: z.string().nullish(),
})
.transform(
(data) =>
data.da ||
data.de ||
data.en ||
data.fi ||
data.no ||
data.pl ||
data.sv
),
url: z.string().nullish(),
})
.partial()
.transform((data) => {
if (!data.id || !data.url) {
return null
}
return {
id: data.id,
url: data.url,
}
})
)
.transform((data) => {
return data.filter(isDefined)
}),
})
.transform((data) => {
return data.items
}),
})
export type GetLocationsUrlsData = z.input<typeof locationsUrlsSchema>
export type LocationsUrls = z.output<typeof locationsUrlsSchema>

View File

@@ -102,3 +102,13 @@ export const additionalDataSuccessCounter = meter.createCounter(
export const additionalDataFailCounter = meter.createCounter(
"trpc.hotels.additionalData-fail"
)
export const locationsUrlsCounter = meter.createCounter(
"trpc.hotels.locations.urls"
)
export const locationsUrlsSuccessCounter = meter.createCounter(
"trpc.hotels.locations.urls-success"
)
export const locationsUrlsFailCounter = meter.createCounter(
"trpc.hotels.locations.urls-fail"
)