Merged in feat/SW-1454-hotel-listing-city-page (pull request #1250)

feat(SW-1454): added hotel listing

* feat(SW-1454): added hotel listing


Approved-by: Fredrik Thorsson
This commit is contained in:
Erik Tiekstra
2025-02-05 13:10:28 +00:00
parent f3e6318d49
commit e3b1bfc414
27 changed files with 522 additions and 103 deletions

View File

@@ -1,14 +1,17 @@
import deepmerge from "deepmerge"
import { unstable_cache } from "next/cache"
import { Lang } from "@/constants/languages"
import { env } from "@/env/server"
import * as api from "@/lib/api"
import { toApiLang } from "@/server/utils"
import { metrics } from "./metrics"
import {
citiesByCountrySchema,
citiesSchema,
countriesSchema,
getHotelIdsByCityIdSchema,
getHotelIdsSchema,
locationsSchema,
} from "./output"
@@ -17,10 +20,9 @@ import { PointOfInterestGroupEnum } from "@/types/enums/pointOfInterest"
import type { RequestOptionsWithOutBody } from "@/types/fetch"
import type {
CitiesGroupedByCountry,
Countries,
CityLocation,
HotelLocation,
} from "@/types/trpc/routers/hotel/locations"
import type { Lang } from "@/constants/languages"
import type { Endpoint } from "@/lib/api/endpoints"
export function getPoiGroupByCategoryName(category: string | undefined) {
@@ -305,11 +307,11 @@ export async function getHotelIdsByCityId(
})
)
return null
return []
}
const apiJson = await apiResponse.json()
const validatedHotelIds = getHotelIdsByCityIdSchema.safeParse(apiJson)
const validatedHotelIds = getHotelIdsSchema.safeParse(apiJson)
if (!validatedHotelIds.success) {
metrics.hotelIds.fail.add(1, {
params: params.toString(),
@@ -323,19 +325,22 @@ export async function getHotelIdsByCityId(
error: validatedHotelIds.error,
})
)
return null
return []
}
metrics.hotelIds.success.add(1, { cityId })
console.info(
"api.hotel.hotel-ids success",
JSON.stringify({ params: params.toString() })
JSON.stringify({
params: params.toString(),
response: validatedHotelIds.data,
})
)
return validatedHotelIds.data
},
[`hotelsByCityId`, params.toString()],
{ revalidate: TWENTYFOUR_HOURS }
{ revalidate: env.CACHE_TIME_HOTELS }
)(params)
}
@@ -376,11 +381,11 @@ export async function getHotelIdsByCountry(
})
)
return null
return []
}
const apiJson = await apiResponse.json()
const validatedHotelIds = getHotelIdsByCityIdSchema.safeParse(apiJson)
const validatedHotelIds = getHotelIdsSchema.safeParse(apiJson)
if (!validatedHotelIds.success) {
metrics.hotelIds.fail.add(1, {
country,
@@ -394,7 +399,7 @@ export async function getHotelIdsByCountry(
error: validatedHotelIds.error,
})
)
return null
return []
}
metrics.hotelIds.success.add(1, { country })
@@ -406,6 +411,69 @@ export async function getHotelIdsByCountry(
return validatedHotelIds.data
},
[`hotelsByCountry`, params.toString()],
{ revalidate: TWENTYFOUR_HOURS }
{ revalidate: env.CACHE_TIME_HOTELS }
)(params)
}
export async function getHotelIdsByCityIdentifier(
cityIdentifier: string,
serviceToken: string
) {
const apiLang = toApiLang(Lang.en)
const cityId = await getCityIdByCityIdentifier(cityIdentifier, serviceToken)
if (!cityId) {
return []
}
const hotelIdsParams = new URLSearchParams({
language: apiLang,
city: cityId,
onlyBasicInfo: "true",
})
const options: RequestOptionsWithOutBody = {
// needs to clear default option as only
// cache or next.revalidate is permitted
cache: undefined,
headers: {
Authorization: `Bearer ${serviceToken}`,
},
next: {
revalidate: env.CACHE_TIME_HOTELS,
},
}
const hotelIds = await getHotelIdsByCityId(cityId, options, hotelIdsParams)
return hotelIds
}
export async function getCityIdByCityIdentifier(
cityIdentifier: string,
serviceToken: string
) {
const lang = Lang.en
const apiLang = toApiLang(lang)
const options: RequestOptionsWithOutBody = {
// needs to clear default option as only
// cache or next.revalidate is permitted
cache: undefined,
headers: {
Authorization: `Bearer ${serviceToken}`,
},
next: {
revalidate: env.CACHE_TIME_HOTELS,
},
}
const params = new URLSearchParams({
language: apiLang,
})
const locations = await getLocations(lang, options, params, null)
if (!locations || "error" in locations) {
return null
}
const cityId = locations
.filter((loc): loc is CityLocation => loc.type === "cities")
.find((loc) => loc.cityIdentifier === cityIdentifier)?.id
return cityId ?? null
}