feat(SW-718) Fixed filtering with multirooms
This commit is contained in:
@@ -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,
|
||||
])
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user