feat(SW-718) Fixed filtering with multirooms

This commit is contained in:
Pontus Dreij
2025-01-21 14:40:39 +01:00
parent edcf146ce1
commit 328cbbe0e1
16 changed files with 326 additions and 151 deletions
+96
View File
@@ -0,0 +1,96 @@
import { useMemo } from "react"
import {
RoomPackageCodeEnum,
type RoomPackageData,
} from "@/types/components/hotelReservation/selectRate/roomFilter"
import type {
Rate,
RateCode,
} from "@/types/components/hotelReservation/selectRate/selectRate"
import type { RoomConfiguration } from "@/server/routers/hotels/output"
interface UseRateSummaryProps {
searchedRoomsAndGuests: Array<{ adults: number; children?: any[] }>
selectedRates: (RateCode | undefined)[]
getFilteredRooms: (roomIndex: number) => RoomConfiguration[]
selectedPackagesByRoom: Record<number, RoomPackageCodeEnum[]>
availablePackages: RoomPackageData
roomCategories: Array<{ name: string; roomTypes: Array<{ code: string }> }>
}
export function useRateSummary({
searchedRoomsAndGuests,
selectedRates,
getFilteredRooms,
selectedPackagesByRoom,
availablePackages,
roomCategories,
}: UseRateSummaryProps) {
return useMemo(() => {
const summaries: (Rate | null)[] = []
searchedRoomsAndGuests.forEach((_, roomIndex) => {
const selectedRate = selectedRates[roomIndex]
const filteredRooms = getFilteredRooms(roomIndex)
const selectedPackages = selectedPackagesByRoom[roomIndex] || []
const room = filteredRooms.find(
(room) => room.roomTypeCode === selectedRate?.roomTypeCode
)
if (!room) {
summaries[roomIndex] = null
return
}
const product = room.products.find(
(product) =>
product.productType.public.rateCode === selectedRate?.publicRateCode
)
if (!product) {
summaries[roomIndex] = null
return
}
const petRoomPackage =
(selectedPackages.includes(RoomPackageCodeEnum.PET_ROOM) &&
availablePackages.find(
(pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM
)) ||
undefined
const features = filteredRooms.find((room) =>
room.features.some(
(feature) => feature.code === RoomPackageCodeEnum.PET_ROOM
)
)?.features
const roomType = roomCategories.find((roomCategory) =>
roomCategory.roomTypes.some(
(roomType) => roomType.code === room.roomTypeCode
)
)
summaries[roomIndex] = {
features: petRoomPackage && features ? features : [],
priceName: selectedRate?.name,
priceTerm: selectedRate?.paymentTerm,
public: product.productType.public,
member: product.productType.member,
roomType: roomType?.name || room.roomType,
roomTypeCode: room.roomTypeCode,
}
})
return summaries
}, [
searchedRoomsAndGuests,
selectedRates,
getFilteredRooms,
selectedPackagesByRoom,
availablePackages,
roomCategories,
])
}
+92
View File
@@ -0,0 +1,92 @@
import { useCallback, useMemo, useState } from "react"
import { filterDuplicateRoomTypesByLowestPrice } from "@/components/HotelReservation/SelectRate/Rooms/utils"
import type {
RoomPackageCodeEnum,
RoomPackageCodes,
} from "@/types/components/hotelReservation/selectRate/roomFilter"
import type {
RoomConfiguration,
RoomsAvailability,
} from "@/server/routers/hotels/output"
interface UseRoomFilteringProps {
roomsAvailability: RoomsAvailability
}
export function useRoomFiltering({ roomsAvailability }: UseRoomFilteringProps) {
const [selectedPackagesByRoom, setSelectedPackagesByRoom] = useState<
Record<number, RoomPackageCodes[]>
>({})
const visibleRooms = useMemo(() => {
const deduped = filterDuplicateRoomTypesByLowestPrice(
roomsAvailability.roomConfigurations
)
const separated = deduped.reduce<{
available: RoomConfiguration[]
notAvailable: RoomConfiguration[]
}>(
(acc, curr) => {
if (curr.status === "NotAvailable")
return { ...acc, notAvailable: [...acc.notAvailable, curr] }
return { ...acc, available: [...acc.available, curr] }
},
{ available: [], notAvailable: [] }
)
return [...separated.available, ...separated.notAvailable]
}, [roomsAvailability.roomConfigurations])
const handleFilter = useCallback(
(
filter: Record<RoomPackageCodeEnum, boolean | undefined>,
roomIndex: number
) => {
const filteredPackages = Object.keys(filter).filter(
(key) => filter[key as RoomPackageCodeEnum]
) as RoomPackageCodeEnum[]
setSelectedPackagesByRoom((prev) => ({
...prev,
[roomIndex]: filteredPackages,
}))
},
[]
)
const getFilteredRooms = useCallback(
(roomIndex: number) => {
const selectedPackages = selectedPackagesByRoom[roomIndex] || []
return visibleRooms.filter((room) =>
selectedPackages.every((filteredPackage) =>
room.features.some((feature) => feature.code === filteredPackage)
)
)
},
[visibleRooms, selectedPackagesByRoom]
)
const getRooms = useCallback(
(roomIndex: number) => {
const selectedPackages = selectedPackagesByRoom[roomIndex] || []
const filteredRooms = getFilteredRooms(roomIndex)
return {
...roomsAvailability,
roomConfigurations:
selectedPackages.length === 0 ? visibleRooms : filteredRooms,
}
},
[roomsAvailability, visibleRooms, selectedPackagesByRoom, getFilteredRooms]
)
return {
selectedPackagesByRoom,
getFilteredRooms,
getRooms,
handleFilter,
}
}