feat(BOOK-463): Fetching hotel filters from CMS and using these inside the destination pages and select hotel page
* 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
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import {
|
||||
type HotelFilter,
|
||||
type HotelListingHotelData,
|
||||
type HotelSortItem,
|
||||
HotelSortOption,
|
||||
} from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
import type {
|
||||
HotelFilter,
|
||||
HotelFilters,
|
||||
} from "@scandic-hotels/trpc/routers/hotels/filters/output"
|
||||
import type { DestinationCityListItem } from "@scandic-hotels/trpc/types/destinationCityPage"
|
||||
import type { DestinationFilter } from "@scandic-hotels/trpc/types/destinationsData"
|
||||
|
||||
@@ -32,7 +35,9 @@ export function getFilteredHotels(
|
||||
if (filters.length) {
|
||||
return hotels.filter(({ hotel }) =>
|
||||
filters.every((filter) =>
|
||||
hotel.detailedFacilities.some((facility) => facility.id === filter.id)
|
||||
hotel.detailedFacilities.some(
|
||||
(facility) => facility.id === Number(filter.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -96,3 +101,81 @@ export function getActiveDestinationFilter(
|
||||
}
|
||||
return allSeoFilters.find((f) => f.filter.id === filterFromUrl.id) || null
|
||||
}
|
||||
|
||||
export function getFiltersWithHotelAndCityCount(
|
||||
hotelFilters: HotelFilters,
|
||||
hotels: HotelListingHotelData[],
|
||||
cities: DestinationCityListItem[]
|
||||
): HotelFilters {
|
||||
const flattenedFilters = Object.values(hotelFilters).flat()
|
||||
const filterHotelCounts: Record<string, number> = {}
|
||||
const filterCityIdentifiers: Record<string, Set<string>> = {}
|
||||
|
||||
hotels.forEach(({ hotel }) => {
|
||||
hotel.detailedFacilities.forEach((facility) => {
|
||||
filterHotelCounts[facility.id] = (filterHotelCounts[facility.id] || 0) + 1
|
||||
|
||||
if (!filterCityIdentifiers[facility.id]) {
|
||||
filterCityIdentifiers[facility.id] = new Set()
|
||||
}
|
||||
if (hotel.cityIdentifier) {
|
||||
filterCityIdentifiers[facility.id].add(hotel.cityIdentifier)
|
||||
}
|
||||
})
|
||||
|
||||
if (hotel.countryCode) {
|
||||
filterHotelCounts[hotel.countryCode] =
|
||||
(filterHotelCounts[hotel.countryCode] || 0) + 1
|
||||
|
||||
if (!filterCityIdentifiers[hotel.countryCode]) {
|
||||
filterCityIdentifiers[hotel.countryCode] = new Set()
|
||||
}
|
||||
if (hotel.cityIdentifier) {
|
||||
filterCityIdentifiers[hotel.countryCode].add(hotel.cityIdentifier)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Count cities that match the cityIdentifiers for each filter
|
||||
const filterCityCounts: Record<string, number> = {}
|
||||
Object.entries(filterCityIdentifiers).forEach(
|
||||
([filterId, cityIdentifiers]) => {
|
||||
filterCityCounts[filterId] = cities.filter(
|
||||
(city) =>
|
||||
city.destination_settings.city &&
|
||||
cityIdentifiers.has(city.destination_settings.city)
|
||||
).length
|
||||
}
|
||||
)
|
||||
|
||||
return flattenedFilters.reduce(
|
||||
(acc, filter) => {
|
||||
if (filter.filterType === "facility") {
|
||||
acc.facilityFilters.push({
|
||||
...filter,
|
||||
hotelCount: filterHotelCounts[filter.id] ?? 0,
|
||||
cityCount: filterCityCounts[filter.id] ?? 0,
|
||||
})
|
||||
} else if (filter.filterType === "surroundings") {
|
||||
acc.surroundingsFilters.push({
|
||||
...filter,
|
||||
hotelCount: filterHotelCounts[filter.id] ?? 0,
|
||||
cityCount: filterCityCounts[filter.id] ?? 0,
|
||||
})
|
||||
} else if (filter.filterType === "country") {
|
||||
acc.countryFilters.push({
|
||||
...filter,
|
||||
filterType: "country",
|
||||
hotelCount: filterHotelCounts[filter.id] ?? 0,
|
||||
cityCount: filterCityCounts[filter.id] ?? 0,
|
||||
})
|
||||
}
|
||||
return acc
|
||||
},
|
||||
{
|
||||
facilityFilters: [],
|
||||
surroundingsFilters: [],
|
||||
countryFilters: [],
|
||||
} as HotelFilters
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import { produce } from "immer"
|
||||
import { useContext } from "react"
|
||||
import { create, useStore } from "zustand"
|
||||
|
||||
import { mergeHotelFiltersAndSeoFilters } from "@scandic-hotels/trpc/utils/getFiltersFromHotels"
|
||||
import { getSortedCities } from "@scandic-hotels/trpc/utils/getSortedCities"
|
||||
import { mergeHotelFiltersAndSeoFilters } from "@scandic-hotels/trpc/utils/mergeHotelFiltersAndSeoFilters"
|
||||
|
||||
import { DestinationDataContext } from "@/contexts/DestinationData"
|
||||
import {
|
||||
@@ -16,12 +16,13 @@ import {
|
||||
getBasePathNameWithoutFilters,
|
||||
getFilteredCities,
|
||||
getFilteredHotels,
|
||||
getFiltersWithHotelAndCityCount,
|
||||
getSortedHotels,
|
||||
isValidSortOption,
|
||||
} from "./helper"
|
||||
|
||||
import type { HotelFilter } from "@scandic-hotels/trpc/routers/hotels/filters/output"
|
||||
import type { DestinationFilter } from "@scandic-hotels/trpc/types/destinationsData"
|
||||
import type { HotelFilter } from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
import type {
|
||||
DestinationDataState,
|
||||
@@ -39,9 +40,10 @@ export function createDestinationDataStore({
|
||||
}: InitialState) {
|
||||
const defaultSort =
|
||||
sortItems.find((s) => s.isDefault)?.value ?? sortItems[0].value
|
||||
|
||||
const allFilters = mergeHotelFiltersAndSeoFilters(hotelFilters, seoFilters)
|
||||
const allSeoFilters = Object.values(seoFilters).flat()
|
||||
const allFlattenedFilters = Object.values(allFilters).flat<HotelFilter[]>()
|
||||
const allFlattenedFilters = Object.values(allFilters).flat()
|
||||
const allFilterSlugs = allFlattenedFilters.map((filter) => filter.slug)
|
||||
const activeFilters: HotelFilter[] = []
|
||||
let activeSeoFilter: DestinationFilter | null = null
|
||||
@@ -75,6 +77,12 @@ export function createDestinationDataStore({
|
||||
const filteredCities = getFilteredCities(filteredHotels, allCities)
|
||||
const activeCities = getSortedCities(filteredCities, activeSort)
|
||||
|
||||
const filtersWithCount = getFiltersWithHotelAndCityCount(
|
||||
allFilters,
|
||||
filteredHotels,
|
||||
filteredCities
|
||||
)
|
||||
|
||||
return create<DestinationDataState>((set) => ({
|
||||
actions: {
|
||||
updateActiveFiltersAndSort(filterSlugs, sort, filterSlugFromUrl) {
|
||||
@@ -175,9 +183,16 @@ export function createDestinationDataStore({
|
||||
? getFilteredCities(pendingHotels, state.allCities)
|
||||
: []
|
||||
|
||||
const pendingFiltersWithCount = getFiltersWithHotelAndCityCount(
|
||||
state.allFilters,
|
||||
pendingHotels,
|
||||
pendingCities
|
||||
)
|
||||
|
||||
state.pendingFilters = filters
|
||||
state.pendingHotelCount = pendingHotels.length
|
||||
state.pendingCityCount = pendingCities.length
|
||||
state.filtersWithCount = pendingFiltersWithCount
|
||||
})
|
||||
)
|
||||
},
|
||||
@@ -187,6 +202,11 @@ export function createDestinationDataStore({
|
||||
state.pendingFilters = []
|
||||
state.pendingHotelCount = state.allHotels.length
|
||||
state.pendingCityCount = state.allCities.length
|
||||
state.filtersWithCount = getFiltersWithHotelAndCityCount(
|
||||
state.allFilters,
|
||||
state.allHotels,
|
||||
state.allCities
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
@@ -197,6 +217,19 @@ export function createDestinationDataStore({
|
||||
state.pendingSort = state.activeSort
|
||||
state.pendingHotelCount = state.activeHotels.length
|
||||
state.pendingCityCount = state.activeCities.length
|
||||
const filteredHotels = getFilteredHotels(
|
||||
state.allHotels,
|
||||
state.activeFilters
|
||||
)
|
||||
const filteredCities = getFilteredCities(
|
||||
filteredHotels,
|
||||
state.allCities
|
||||
)
|
||||
state.filtersWithCount = getFiltersWithHotelAndCityCount(
|
||||
state.allFilters,
|
||||
filteredHotels,
|
||||
filteredCities
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
@@ -213,6 +246,7 @@ export function createDestinationDataStore({
|
||||
activeFilters,
|
||||
pendingFilters: activeFilters,
|
||||
allFilters,
|
||||
filtersWithCount,
|
||||
activeSeoFilter,
|
||||
filterFromUrl,
|
||||
basePathnameWithoutFilters,
|
||||
|
||||
Reference in New Issue
Block a user