Merged in feat/SW-2113-allow-feature-combinations (pull request #1719)

Feat/SW-2113 allow feature combinations

* feat(SW-2113): Refactor features data to be fetched on filter room filter change

* feat(SW-2113): added loading state

* fix: now clear room selection when applying filter and room doesnt exists. And added room features to mobile summary

* fix

* fix: add package to price details

* feat(SW-2113): added buttons to room filter

* fix: active room

* fix: remove console log

* fix: added form and close handler to room package filter

* fix: add restriction so you cannot select pet room with allergy room and vice versa

* fix: fixes from review feedback

* fix

* fix: hide modify button if on nextcoming rooms if no selection is made, and adjust filter logic in togglePackage

* fix: forgot to use roomFeatureCodes from input..

* fix: naming


Approved-by: Simon.Emanuelsson
This commit is contained in:
Tobias Johansson
2025-04-07 11:36:34 +00:00
parent 8d34e1c8bb
commit e6ae6ff650
31 changed files with 725 additions and 359 deletions

View File

@@ -106,3 +106,16 @@ export function isRoomPackageCode(
code as RoomPackageCodeEnum
)
}
export function filterRoomsBySelectedPackages(
selectedPackages: RoomPackageCodeEnum[],
rooms: RoomConfiguration[]
) {
if (!selectedPackages.length) {
return rooms
}
return rooms.filter((r) =>
selectedPackages.every((pkg) => r.features.find((f) => f.code === pkg))
)
}

View File

@@ -6,9 +6,9 @@ import { create, useStore } from "zustand"
import { RatesContext } from "@/contexts/Rates"
import {
filterRoomsBySelectedPackages,
findProductInRoom,
findSelectedRate,
isRoomPackageCode,
} from "./helpers"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
@@ -72,11 +72,18 @@ export function createRatesStore({
for (const [idx, room] of booking.rooms.entries()) {
if (room.rateCode && room.roomTypeCode) {
const roomConfiguration = roomConfigurations?.[idx]
const selectedPackages = room.packages ?? []
let rooms: RoomConfiguration[] = filterRoomsBySelectedPackages(
selectedPackages,
roomConfiguration
)
const selectedRoom = findSelectedRate(
room.rateCode,
room.counterRateCode,
room.roomTypeCode,
roomConfiguration
rooms
)
if (!selectedRoom) {
@@ -97,6 +104,8 @@ export function createRatesStore({
roomType: selectedRoom.roomType,
roomTypeCode: selectedRoom.roomTypeCode,
}
} else {
rateSummary[idx] = null
}
}
}
@@ -105,9 +114,10 @@ export function createRatesStore({
if (searchParams.has("modifyRateIndex")) {
activeRoom = Number(searchParams.get("modifyRateIndex"))
} else if (rateSummary.length === booking.rooms.length) {
// Since all rooms has selections, all sections should be
// closed on load
activeRoom = -1
// Finds the first unselected room and sets that to active
// if no unselected rooms it will return -1 and close all rooms
const unselectedRoomIndex = rateSummary.findIndex((rate) => !rate)
activeRoom = unselectedRoomIndex
}
return create<RatesState>()((set) => {
@@ -126,6 +136,13 @@ export function createRatesStore({
roomConfigurations,
rooms: booking.rooms.map((room, idx) => {
const roomConfiguration = roomConfigurations[idx]
const selectedPackages = room.packages ?? []
let rooms: RoomConfiguration[] = filterRoomsBySelectedPackages(
selectedPackages,
roomConfiguration
)
const selectedRate =
findSelectedRate(
room.rateCode,
@@ -143,21 +160,6 @@ export function createRatesStore({
)
}
// Since features are fetched async based on query string, we need to read from query string to apply correct filtering
const packagesParam = searchParams.get(`room[${idx}].packages`)
const selectedPackages = packagesParam
? packagesParam.split(",").filter(isRoomPackageCode)
: []
let rooms: RoomConfiguration[] = roomConfiguration
if (selectedPackages.length) {
rooms = roomConfiguration.filter((r) =>
selectedPackages.some((pkg) =>
r.features.find((f) => f.code === pkg)
)
)
}
return {
actions: {
appendRegularRates(roomConfigurations) {
@@ -204,6 +206,48 @@ export function createRatesStore({
})
)
},
addRoomFeatures(roomFeatures) {
return set(
produce((state: RatesState) => {
const selectedPackages = state.rooms[idx].selectedPackages
const rateSummaryItem = state.rateSummary[idx]
state.roomConfigurations[idx].forEach((room) => {
const features = roomFeatures.find(
(feat) => feat.roomTypeCode === room.roomTypeCode
)?.features
if (features) {
room.features = features
if (rateSummaryItem) {
rateSummaryItem.packages = selectedPackages
rateSummaryItem.features = features
}
}
})
state.rateSummary[idx] = rateSummaryItem
state.rooms[idx].rooms = filterRoomsBySelectedPackages(
selectedPackages,
state.roomConfigurations[idx]
)
const selectedRate = findSelectedRate(
room.rateCode,
room.counterRateCode,
room.roomTypeCode,
state.rooms[idx].rooms
)
if (!selectedRate) {
state.rooms[idx].selectedRate = null
state.rateSummary[idx] = null
}
})
)
},
closeSection() {
return set(
produce((state: RatesState) => {
@@ -229,44 +273,53 @@ export function createRatesStore({
})
)
},
togglePackage(code) {
togglePackages(selectedPackages) {
return set(
produce((state: RatesState) => {
const isSelected =
state.rooms[idx].selectedPackages.includes(code)
const selectedPackages = isSelected
? state.rooms[idx].selectedPackages.filter(
(pkg) => pkg !== code
)
: [...state.rooms[idx].selectedPackages, code]
state.rooms[idx].selectedPackages = selectedPackages
const rateSummaryItem = state.rateSummary[idx]
const roomConfiguration = state.roomConfigurations[idx]
if (roomConfiguration) {
const searchParams = new URLSearchParams(state.searchParams)
if (selectedPackages.length) {
state.rooms[idx].rooms = roomConfiguration.filter(
(room) =>
selectedPackages.every((pkg) =>
room.features.find((feat) => feat.code === pkg)
)
)
searchParams.set(
`room[${idx}].packages`,
selectedPackages.join(",")
)
if (state.rateSummary[idx]) {
state.rateSummary[idx].packages = selectedPackages
if (rateSummaryItem) {
rateSummaryItem.packages = selectedPackages
}
} else {
state.rooms[idx].rooms = roomConfiguration
if (state.rateSummary[idx]) {
state.rateSummary[idx].packages = []
if (rateSummaryItem) {
rateSummaryItem.packages = []
}
searchParams.delete(`room[${idx}].packages`)
}
// If we already have the features data 'addRoomFeatures' wont run
// so we need to do additional filtering here if thats the case
const filteredRooms = filterRoomsBySelectedPackages(
selectedPackages,
state.roomConfigurations[idx]
)
if (filteredRooms.length) {
const selectedRate = findSelectedRate(
room.rateCode,
room.counterRateCode,
room.roomTypeCode,
state.rooms[idx].rooms
)
if (!selectedRate) {
state.rooms[idx].selectedRate = null
state.rateSummary[idx] = null
}
}
state.searchParams = new ReadonlyURLSearchParams(
searchParams
)