import type { CategorizedFilters, Filter, SortItem, } from "@/types/components/destinationFilterAndSort" import { SortOption } from "@/types/enums/destinationFilterAndSort" import type { HotelDataWithUrl } from "@/types/hotel" import type { DestinationCityListItem } from "@/types/trpc/routers/contentstack/destinationCityPage" const HOTEL_SORTING_STRATEGIES: Partial< Record number> > = { [SortOption.Name]: function (a, b) { return a.hotel.name.localeCompare(b.hotel.name) }, [SortOption.TripAdvisorRating]: function (a, b) { return ( (b.hotel.ratings?.tripAdvisor.rating ?? 0) - (a.hotel.ratings?.tripAdvisor.rating ?? 0) ) }, [SortOption.Distance]: function (a, b) { return a.hotel.location.distanceToCentre - b.hotel.location.distanceToCentre }, } const CITY_SORTING_STRATEGIES: Partial< Record< SortOption, (a: DestinationCityListItem, b: DestinationCityListItem) => number > > = { [SortOption.Name]: function (a, b) { return a.cityName.localeCompare(b.cityName) }, [SortOption.Recommended]: function (a, b) { if (a.sort_order === null && b.sort_order === null) { return a.cityName.localeCompare(b.cityName) } if (a.sort_order === null) { return 1 } if (b.sort_order === null) { return -1 } return b.sort_order - a.sort_order }, } export function getFilteredHotels( hotels: HotelDataWithUrl[], filters: string[] ) { if (filters.length) { return hotels.filter(({ hotel }) => filters.every((filter) => hotel.detailedFacilities.some((facility) => facility.slug === filter) ) ) } return hotels } export function getFilteredCities( filteredHotels: HotelDataWithUrl[], cities: DestinationCityListItem[] ) { const filteredCityIdentifiers = filteredHotels.map( (hotel) => hotel.cities[0].cityIdentifier ) return cities.filter((city) => filteredCityIdentifiers.includes(city.destination_settings.city) ) } export function getSortedCities( cities: DestinationCityListItem[], sortOption: SortOption ) { const sortFn = CITY_SORTING_STRATEGIES[sortOption] return sortFn ? cities.sort(sortFn) : cities } export function getSortedHotels( hotels: HotelDataWithUrl[], sortOption: SortOption ) { const sortFn = HOTEL_SORTING_STRATEGIES[sortOption] return sortFn ? hotels.sort(sortFn) : hotels } export function isValidSortOption( value: string, sortItems: SortItem[] ): value is SortOption { return sortItems.map((item) => item.value).includes(value as SortOption) } const HOTEL_SURROUNDINGS_FILTER_TYPE_NAMES = [ "Hotel surroundings", "Hotel omgivelser", "Hotelumgebung", "Hotellia lähellä", "Hotellomgivelser", "Omgivningar", ] const HOTEL_FACILITIES_FILTER_TYPE_NAMES = [ "Hotel facilities", "Hotellfaciliteter", "Hotelfaciliteter", "Hotel faciliteter", "Hotel-Infos", "Hotellin palvelut", ] export function getFiltersFromHotels( hotels: HotelDataWithUrl[] ): CategorizedFilters { if (hotels.length === 0) { return { facilityFilters: [], surroundingsFilters: [] } } const filters = hotels.flatMap(({ hotel }) => hotel.detailedFacilities) const sortedFilters = filters.sort((a, b) => b.sortOrder - a.sortOrder) const uniqueFilterNames = [ ...new Set(sortedFilters.map((filter) => filter.name)), ] const filterList = uniqueFilterNames .map((filterName) => { const filter = filters.find((filter) => filter.name === filterName) return filter ? { name: filter.name, slug: filter.slug, filterType: filter.filter, } : null }) .filter((filter): filter is Filter => !!filter) return { facilityFilters: filterList.filter((filter) => HOTEL_FACILITIES_FILTER_TYPE_NAMES.includes(filter.filterType) ), surroundingsFilters: filterList.filter((filter) => HOTEL_SURROUNDINGS_FILTER_TYPE_NAMES.includes(filter.filterType) ), } } export function getBasePathNameWithoutFilters( pathname: string, filterSlugs: string[] ) { const pathSegments = pathname.split("/") const filteredSegments = pathSegments.filter( (segment) => !filterSlugs.includes(segment) ) return filteredSegments.join("/") }