* feat(BOOK-463): Fetching hotel filters from CMS and using these inside the destination pages * fix(BOOK-698): fetch hotel filters from CMS on select hotel page Approved-by: Bianca Widstam
105 lines
2.8 KiB
TypeScript
105 lines
2.8 KiB
TypeScript
import {
|
|
type HotelListingHotelData,
|
|
type HotelSortItem,
|
|
HotelSortOption,
|
|
} from "@scandic-hotels/trpc/types/hotel"
|
|
|
|
import type {
|
|
HotelFilter,
|
|
HotelFilters,
|
|
} from "@scandic-hotels/trpc/routers/hotels/filters/output"
|
|
|
|
const HOTEL_SORTING_STRATEGIES: Partial<
|
|
Record<
|
|
HotelSortOption,
|
|
(a: HotelListingHotelData, b: HotelListingHotelData) => number
|
|
>
|
|
> = {
|
|
[HotelSortOption.Name]: function (a, b) {
|
|
return a.hotel.name.localeCompare(b.hotel.name)
|
|
},
|
|
[HotelSortOption.TripAdvisorRating]: function (a, b) {
|
|
return (b.hotel.tripadvisor ?? 0) - (a.hotel.tripadvisor ?? 0)
|
|
},
|
|
}
|
|
|
|
export function getFilteredHotels(
|
|
hotels: HotelListingHotelData[],
|
|
filters: HotelFilter[]
|
|
) {
|
|
if (filters.length) {
|
|
return hotels.filter(({ hotel }) =>
|
|
filters.every((filter) => {
|
|
const matchesFacility = hotel.detailedFacilities.some(
|
|
(facility) => facility.id === Number(filter.id)
|
|
)
|
|
const matchesCountry = hotel.countryCode === filter.id
|
|
return matchesFacility || matchesCountry
|
|
})
|
|
)
|
|
}
|
|
return hotels
|
|
}
|
|
|
|
export function getSortedHotels(
|
|
hotels: HotelListingHotelData[],
|
|
sortOption: HotelSortOption
|
|
) {
|
|
const sortFn = HOTEL_SORTING_STRATEGIES[sortOption]
|
|
return sortFn ? [...hotels].sort(sortFn) : hotels
|
|
}
|
|
|
|
export function isValidSortOption(
|
|
value: string,
|
|
sortItems: HotelSortItem[]
|
|
): value is HotelSortOption {
|
|
return sortItems.map((item) => item.value).includes(value as HotelSortOption)
|
|
}
|
|
|
|
export function getFiltersWithHotelCount(
|
|
hotelFilters: HotelFilters,
|
|
hotels: HotelListingHotelData[]
|
|
): HotelFilters {
|
|
const flattenedFilters = Object.values(hotelFilters).flat()
|
|
const filterHotelCounts: Record<string, number> = {}
|
|
|
|
hotels.forEach(({ hotel }) => {
|
|
hotel.detailedFacilities.forEach((facility) => {
|
|
filterHotelCounts[facility.id] = (filterHotelCounts[facility.id] || 0) + 1
|
|
})
|
|
|
|
if (hotel.countryCode) {
|
|
filterHotelCounts[hotel.countryCode] =
|
|
(filterHotelCounts[hotel.countryCode] || 0) + 1
|
|
}
|
|
})
|
|
|
|
return flattenedFilters.reduce(
|
|
(acc, filter) => {
|
|
if (filter.filterType === "facility") {
|
|
acc.facilityFilters.push({
|
|
...filter,
|
|
hotelCount: filterHotelCounts[filter.id] ?? 0,
|
|
})
|
|
} else if (filter.filterType === "surroundings") {
|
|
acc.surroundingsFilters.push({
|
|
...filter,
|
|
hotelCount: filterHotelCounts[filter.id] ?? 0,
|
|
})
|
|
} else if (filter.filterType === "country") {
|
|
acc.countryFilters.push({
|
|
...filter,
|
|
filterType: "country",
|
|
hotelCount: filterHotelCounts[filter.id] ?? 0,
|
|
})
|
|
}
|
|
return acc
|
|
},
|
|
{
|
|
facilityFilters: [],
|
|
surroundingsFilters: [],
|
|
countryFilters: [],
|
|
} as HotelFilters
|
|
)
|
|
}
|