Merged in feat/SW-1444-destination-page-add-destination-list-component (pull request #1240)

feat/SW-1444 destination page add destination list component

* feat(SW-1444): add list component

* feat(SW-1444): add subtitle to accordion

* feat(SW-1444): refactor component structure

* feat(SW-1444): add desktop breakpoint

* feat(SW-1444): fix typo

* feat(SW-1444): add props

* feat(SW-1444): add query

* feat(SW-1444): updated query

* feat(SW-1444): display data

* feat(SW-1444): fix merge hickup

* feat(SW-1444): change var name

* feat(SW-1444): remove unsued translations

* feat(SW-1444): use country as title

* feat(SW-1444): sort hotels in query

* feat(SW-1444): make responsive

* feat(SW-1444): fetch country url

* feat(SW-1444): update logging

* feat(SW-1444): remove spread


Approved-by: Erik Tiekstra
This commit is contained in:
Fredrik Thorsson
2025-02-04 14:17:12 +00:00
parent 4ed4b3585b
commit b85a3a57ec
27 changed files with 489 additions and 21 deletions
@@ -1,13 +1,25 @@
import { env } from "@/env/server"
import {
GetDestinationOverviewPage,
GetDestinationOverviewPageRefs,
} from "@/lib/graphql/Query/DestinationOverviewPage/DestinationOverviewPage.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import {
contentstackExtendedProcedureUID,
router,
serviceProcedure,
} from "@/server/trpc"
import { toApiLang } from "@/server/utils"
import { generateTag } from "@/utils/generateTag"
import {
getCitiesByCountry,
getCountries,
getHotelIdsByCityId,
} from "../../hotels/utils"
import { getCityListDataByCityIdentifier } from "../destinationCountryPage/utils"
import {
destinationOverviewPageRefsSchema,
destinationOverviewPageSchema,
@@ -20,11 +32,14 @@ import {
getDestinationOverviewPageRefsSuccessCounter,
getDestinationOverviewPageSuccessCounter,
} from "./telemetry"
import { getCountryPageUrl } from "./utils"
import type { DestinationsData } from "@/types/components/destinationOverviewPage/destinationsList/destinationsData"
import {
TrackingChannelEnum,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import type { RequestOptionsWithOutBody } from "@/types/fetch"
import type {
GetDestinationOverviewPageData,
GetDestinationOverviewPageRefsSchema,
@@ -187,4 +202,90 @@ export const destinationOverviewPageQueryRouter = router({
tracking,
}
}),
destinations: router({
get: serviceProcedure.query(async function ({ ctx }) {
const apiLang = toApiLang(ctx.lang)
const params = new URLSearchParams({
language: apiLang,
})
const options: RequestOptionsWithOutBody = {
// needs to clear default option as only
// cache or next.revalidate is permitted
cache: undefined,
headers: {
Authorization: `Bearer ${ctx.serviceToken}`,
},
next: {
revalidate: env.CACHE_TIME_HOTELS,
},
}
const countries = await getCountries(options, params, ctx.lang)
if (!countries) {
return null
}
const countryNames = countries.data.map((country) => country.name)
const citiesByCountry = await getCitiesByCountry(
countryNames,
options,
params,
ctx.lang,
true
)
const destinations: DestinationsData = await Promise.all(
Object.entries(citiesByCountry).map(async ([country, cities]) => {
const citiesWithHotelCount = await Promise.all(
cities.map(async (city) => {
const hotelIdsParams = new URLSearchParams({
language: apiLang,
city: city.id,
onlyBasicInfo: "true",
})
const hotels = await getHotelIdsByCityId(
city.id,
options,
hotelIdsParams
)
let cityUrl
if (city.cityIdentifier) {
cityUrl = await getCityListDataByCityIdentifier(
ctx.lang,
city.cityIdentifier
)
}
return {
id: city.id,
name: city.name,
hotelIds: hotels,
hotelCount: hotels?.length ?? 0,
url: cityUrl?.url,
}
})
)
const countryUrl = await getCountryPageUrl(ctx.lang, country)
return {
country,
countryUrl: countryUrl?.url,
numberOfHotels: citiesWithHotelCount.reduce(
(acc, city) => acc + city.hotelCount,
0
),
cities: citiesWithHotelCount,
}
})
)
return destinations.sort((a, b) => a.country.localeCompare(b.country))
}),
}),
})