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:
@@ -12,7 +12,10 @@ import FilterCheckbox from "./FilterCheckbox"
|
||||
|
||||
import styles from "./filterContent.module.css"
|
||||
|
||||
import type { CategorizedHotelFilters, HotelFilter } from "../../../../types"
|
||||
import type {
|
||||
CategorizedHotelFilters,
|
||||
SelectHotelFilter,
|
||||
} from "../../../../types"
|
||||
|
||||
interface FilterContentProps {
|
||||
filters: CategorizedHotelFilters
|
||||
@@ -75,7 +78,7 @@ export default function FilterContent({
|
||||
return null
|
||||
}
|
||||
|
||||
function filterOutput(filters: HotelFilter[]) {
|
||||
function filterOutput(filters: SelectHotelFilter[]) {
|
||||
return filters.map((filter) => {
|
||||
const relevantIds = showOnlyBookingCodeRates
|
||||
? filter.bookingCodeFilteredIds
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { AvailabilityEnum } from "@scandic-hotels/trpc/enums/selectHotel"
|
||||
import { getHotelFilters } from "@scandic-hotels/trpc/routers/hotels/filters/utils"
|
||||
import { generateChildrenString } from "@scandic-hotels/trpc/routers/hotels/helpers"
|
||||
|
||||
import { serverClient } from "../../trpc"
|
||||
@@ -18,7 +19,7 @@ import type {
|
||||
Location,
|
||||
} from "@scandic-hotels/trpc/types/locations"
|
||||
|
||||
import type { CategorizedHotelFilters, HotelFilter } from "../../types"
|
||||
import type { CategorizedHotelFilters, SelectHotelFilter } from "../../types"
|
||||
|
||||
type AvailabilityInput = {
|
||||
cityId: string
|
||||
@@ -273,50 +274,38 @@ export async function getHotels({
|
||||
return hotels
|
||||
}
|
||||
|
||||
const hotelSurroundingsFilterNames = [
|
||||
"Hotel surroundings",
|
||||
"Hotel omgivelser",
|
||||
"Hotelumgebung",
|
||||
"Hotellia lähellä",
|
||||
"Hotellomgivelser",
|
||||
"Omgivningar",
|
||||
]
|
||||
|
||||
const hotelFacilitiesFilterNames = [
|
||||
"Hotel facilities",
|
||||
"Hotellfaciliteter",
|
||||
"Hotelfaciliteter",
|
||||
"Hotel faciliteter",
|
||||
"Hotel-Infos",
|
||||
"Hotellin palvelut",
|
||||
]
|
||||
|
||||
export function getFiltersFromHotels(
|
||||
export async function fetchHotelFiltersAndMapToCategorizedFilters(
|
||||
hotels: HotelResponse[],
|
||||
showBookingCodeFilter: boolean
|
||||
): CategorizedHotelFilters {
|
||||
showBookingCodeFilter: boolean,
|
||||
lang: Lang
|
||||
): Promise<CategorizedHotelFilters> {
|
||||
const defaultFilters = { facilityFilters: [], surroundingsFilters: [] }
|
||||
if (!hotels.length) {
|
||||
return defaultFilters
|
||||
}
|
||||
const { countryFilters, ...hotelFilters } = await getHotelFilters(lang)
|
||||
const allFlattenedFilters = Object.values(hotelFilters).flat()
|
||||
const filters = hotels.flatMap(({ hotel, availability }) => {
|
||||
const hotelFilterData = allFlattenedFilters.map((filter) => {
|
||||
const hotelHasFilter = hotel.detailedFacilities.some(
|
||||
(facility) => facility.id.toString() === filter.id
|
||||
)
|
||||
return {
|
||||
...filter,
|
||||
hotelId: hotelHasFilter ? hotel.operaId : null,
|
||||
hotelIds: hotelHasFilter ? [hotel.operaId] : [],
|
||||
bookingCodeFilteredIds:
|
||||
(availability.bookingCode || !showBookingCodeFilter) && hotelHasFilter
|
||||
? [hotel.operaId]
|
||||
: [],
|
||||
}
|
||||
})
|
||||
|
||||
const filters = hotels.flatMap(({ hotel, availability }) =>
|
||||
hotel.detailedFacilities.map(
|
||||
(facility) =>
|
||||
<HotelFilter>{
|
||||
...facility,
|
||||
hotelId: hotel.operaId,
|
||||
hotelIds: [hotel.operaId],
|
||||
bookingCodeFilteredIds:
|
||||
availability.bookingCode || !showBookingCodeFilter
|
||||
? [hotel.operaId]
|
||||
: [],
|
||||
}
|
||||
)
|
||||
)
|
||||
return hotelFilterData
|
||||
})
|
||||
|
||||
const uniqueFilterIds = [...new Set(filters.map((filter) => filter.id))]
|
||||
const filterList: HotelFilter[] = uniqueFilterIds
|
||||
const filterList: SelectHotelFilter[] = uniqueFilterIds
|
||||
.map((filterId) => {
|
||||
const filter = filters.find((f) => f.id === filterId)
|
||||
|
||||
@@ -324,7 +313,9 @@ export function getFiltersFromHotels(
|
||||
if (filter) {
|
||||
const matchingFilters = filters.filter((f) => f.id === filterId)
|
||||
|
||||
filter.hotelIds = matchingFilters.map((f) => f.hotelId)
|
||||
filter.hotelIds = matchingFilters
|
||||
.map((f) => f.hotelId)
|
||||
.filter((id) => id !== null)
|
||||
filter.bookingCodeFilteredIds = [
|
||||
...new Set(
|
||||
matchingFilters.flatMap((f) => f.bookingCodeFilteredIds ?? [])
|
||||
@@ -333,18 +324,17 @@ export function getFiltersFromHotels(
|
||||
}
|
||||
return filter
|
||||
})
|
||||
.filter((filter): filter is HotelFilter => filter !== undefined)
|
||||
.filter((filter): filter is SelectHotelFilter => filter !== undefined)
|
||||
.sort((a, b) => b.sortOrder - a.sortOrder)
|
||||
|
||||
return filterList.reduce<CategorizedHotelFilters>((filters, filter) => {
|
||||
if (filter.filter && hotelSurroundingsFilterNames.includes(filter.filter)) {
|
||||
filters.surroundingsFilters.push(filter)
|
||||
}
|
||||
|
||||
if (filter.filter && hotelFacilitiesFilterNames.includes(filter.filter)) {
|
||||
filters.facilityFilters.push(filter)
|
||||
}
|
||||
|
||||
return filters
|
||||
}, defaultFilters)
|
||||
const facilityFilters = filterList.filter(
|
||||
(filter) => filter.filterType === "facility"
|
||||
)
|
||||
const surroundingsFilters = filterList.filter(
|
||||
(filter) => filter.filterType === "surroundings"
|
||||
)
|
||||
return {
|
||||
facilityFilters,
|
||||
surroundingsFilters,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ import BookingCodeFilter from "../BookingCodeFilter"
|
||||
import HotelCardListing from "../HotelCardListing"
|
||||
import { StaticMap } from "../StaticMap"
|
||||
import HotelFilter from "./Filters/HotelFilter"
|
||||
import { getFiltersFromHotels, type HotelResponse } from "./helpers"
|
||||
import {
|
||||
fetchHotelFiltersAndMapToCategorizedFilters,
|
||||
type HotelResponse,
|
||||
} from "./helpers"
|
||||
import HotelCount from "./HotelCount"
|
||||
import HotelSorter from "./HotelSorter"
|
||||
import { MapWithButtonWrapper } from "./MapWithButtonWrapper"
|
||||
@@ -35,7 +38,7 @@ interface SelectHotelProps {
|
||||
topSlot?: ReactNode
|
||||
}
|
||||
|
||||
export function SelectHotel({
|
||||
export async function SelectHotel({
|
||||
bookingCode,
|
||||
city,
|
||||
hotels,
|
||||
@@ -61,7 +64,11 @@ export function SelectHotel({
|
||||
|
||||
const showBookingCodeFilter = isBookingCodeRateAvailable && !isSpecialRate
|
||||
|
||||
const filterList = getFiltersFromHotels(hotels, showBookingCodeFilter)
|
||||
const filterList = await fetchHotelFiltersAndMapToCategorizedFilters(
|
||||
hotels,
|
||||
showBookingCodeFilter,
|
||||
lang
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { env } from "../../env/server"
|
||||
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
|
||||
import { MapContainer } from "../components/MapContainer"
|
||||
import {
|
||||
getFiltersFromHotels,
|
||||
fetchHotelFiltersAndMapToCategorizedFilters,
|
||||
getHotels,
|
||||
} from "../components/SelectHotel/helpers"
|
||||
import {
|
||||
@@ -108,7 +108,11 @@ export async function AlternativeHotelsMapPage({
|
||||
config,
|
||||
})
|
||||
|
||||
const filterList = getFiltersFromHotels(hotels, isBookingCodeRateAvailable)
|
||||
const filterList = await fetchHotelFiltersAndMapToCategorizedFilters(
|
||||
hotels,
|
||||
isBookingCodeRateAvailable,
|
||||
lang
|
||||
)
|
||||
|
||||
return (
|
||||
<BookingFlowConfig config={config}>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { env } from "../../env/server"
|
||||
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
|
||||
import { MapContainer } from "../components/MapContainer"
|
||||
import {
|
||||
getFiltersFromHotels,
|
||||
fetchHotelFiltersAndMapToCategorizedFilters,
|
||||
getHotels,
|
||||
} from "../components/SelectHotel/helpers"
|
||||
import {
|
||||
@@ -109,7 +109,11 @@ export async function SelectHotelMapPage({
|
||||
config,
|
||||
})
|
||||
|
||||
const filterList = getFiltersFromHotels(hotels, isBookingCodeRateAvailable)
|
||||
const filterList = await fetchHotelFiltersAndMapToCategorizedFilters(
|
||||
hotels,
|
||||
isBookingCodeRateAvailable,
|
||||
lang
|
||||
)
|
||||
|
||||
const suspenseKey = stringify(searchParams)
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
|
||||
import type { HotelFilter } from "@scandic-hotels/trpc/routers/hotels/filters/output"
|
||||
|
||||
export type NextSearchParams = { [key: string]: string | string[] | undefined }
|
||||
|
||||
export type HotelFilter = Hotel["detailedFacilities"][number] & {
|
||||
export type SelectHotelFilter = HotelFilter & {
|
||||
hotelId: string
|
||||
hotelIds: string[]
|
||||
bookingCodeFilteredIds: string[]
|
||||
}
|
||||
|
||||
export type CategorizedHotelFilters = {
|
||||
facilityFilters: HotelFilter[]
|
||||
surroundingsFilters: HotelFilter[]
|
||||
facilityFilters: SelectHotelFilter[]
|
||||
surroundingsFilters: SelectHotelFilter[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user