feat(SW-718): fix comments
This commit is contained in:
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
|
import { useRateSelectionStore } from "@/stores/rate-selection"
|
||||||
|
|
||||||
import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
|
import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
|
||||||
import SignupPromoMobile from "@/components/HotelReservation/SignupPromo/Mobile"
|
import SignupPromoMobile from "@/components/HotelReservation/SignupPromo/Mobile"
|
||||||
@@ -16,9 +17,9 @@ import styles from "./rateSummary.module.css"
|
|||||||
|
|
||||||
import type { RateSummaryProps } from "@/types/components/hotelReservation/selectRate/rateSummary"
|
import type { RateSummaryProps } from "@/types/components/hotelReservation/selectRate/rateSummary"
|
||||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||||
|
import type { Rate } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
|
|
||||||
export default function RateSummary({
|
export default function RateSummary({
|
||||||
rateSummary,
|
|
||||||
isUserLoggedIn,
|
isUserLoggedIn,
|
||||||
packages,
|
packages,
|
||||||
roomsAvailability,
|
roomsAvailability,
|
||||||
@@ -26,12 +27,19 @@ export default function RateSummary({
|
|||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const [isVisible, setIsVisible] = useState(false)
|
const [isVisible, setIsVisible] = useState(false)
|
||||||
|
|
||||||
|
const { rateSummary } = useRateSelectionStore()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => setIsVisible(true), 0)
|
const timer = setTimeout(() => setIsVisible(true), 0)
|
||||||
return () => clearTimeout(timer)
|
return () => clearTimeout(timer)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
if (rateSummary.length === 0) return null
|
if (rateSummary.length === 0) return null
|
||||||
|
|
||||||
|
const selectedRateSummary = rateSummary.filter(
|
||||||
|
(summary): summary is Rate => summary !== null
|
||||||
|
)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
member,
|
member,
|
||||||
public: publicRate,
|
public: publicRate,
|
||||||
@@ -39,7 +47,7 @@ export default function RateSummary({
|
|||||||
roomType,
|
roomType,
|
||||||
priceName,
|
priceName,
|
||||||
priceTerm,
|
priceTerm,
|
||||||
} = rateSummary[0] // TODO: Support multiple rooms
|
} = selectedRateSummary[0] // TODO: Support multiple rooms
|
||||||
|
|
||||||
const isPetRoomSelected = features.some(
|
const isPetRoomSelected = features.some(
|
||||||
(feature) => feature.code === RoomPackageCodeEnum.PET_ROOM
|
(feature) => feature.code === RoomPackageCodeEnum.PET_ROOM
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ export async function RoomsContainer({
|
|||||||
const [roomsAvailability, roomsAvailabilityError] =
|
const [roomsAvailability, roomsAvailabilityError] =
|
||||||
await roomsAvailabilityPromise
|
await roomsAvailabilityPromise
|
||||||
|
|
||||||
|
console.log("roomsAvailability_", roomsAvailability)
|
||||||
|
|
||||||
if (packagesError) {
|
if (packagesError) {
|
||||||
// TODO: Log packages error
|
// TODO: Log packages error
|
||||||
console.error("[RoomsContainer] unable to fetch packages")
|
console.error("[RoomsContainer] unable to fetch packages")
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { useIntl } from "react-intl"
|
|||||||
import { useRateSelectionStore } from "@/stores/rate-selection"
|
import { useRateSelectionStore } from "@/stores/rate-selection"
|
||||||
|
|
||||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
import { useRateSummary } from "@/hooks/selectRate/useRateSummary"
|
|
||||||
import { useRoomFiltering } from "@/hooks/selectRate/useRoomFiltering"
|
import { useRoomFiltering } from "@/hooks/selectRate/useRoomFiltering"
|
||||||
import { trackLowestRoomPrice } from "@/utils/tracking"
|
import { trackLowestRoomPrice } from "@/utils/tracking"
|
||||||
import { convertObjToSearchParams, convertSearchParamsToObj } from "@/utils/url"
|
import { convertObjToSearchParams, convertSearchParamsToObj } from "@/utils/url"
|
||||||
@@ -24,10 +23,7 @@ import {
|
|||||||
RoomPackageCodeEnum,
|
RoomPackageCodeEnum,
|
||||||
} from "@/types/components/hotelReservation/selectRate/roomFilter"
|
} from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||||
import type { SelectRateProps } from "@/types/components/hotelReservation/selectRate/roomSelection"
|
import type { SelectRateProps } from "@/types/components/hotelReservation/selectRate/roomSelection"
|
||||||
import type {
|
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
Rate,
|
|
||||||
SelectRateSearchParams,
|
|
||||||
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
|
||||||
import type { RoomConfiguration } from "@/server/routers/hotels/output"
|
import type { RoomConfiguration } from "@/server/routers/hotels/output"
|
||||||
|
|
||||||
export default function Rooms({
|
export default function Rooms({
|
||||||
@@ -45,8 +41,13 @@ export default function Rooms({
|
|||||||
const arrivalDate = searchParams.get("fromDate")
|
const arrivalDate = searchParams.get("fromDate")
|
||||||
const departureDate = searchParams.get("toDate")
|
const departureDate = searchParams.get("toDate")
|
||||||
|
|
||||||
const { modifyRate, selectedRates, setSelectedRates } =
|
const {
|
||||||
useRateSelectionStore()
|
modifyRate,
|
||||||
|
selectedRates,
|
||||||
|
rateSummary,
|
||||||
|
calculateRateSummary,
|
||||||
|
initializeRates,
|
||||||
|
} = useRateSelectionStore()
|
||||||
|
|
||||||
const bookingWidgetSearchData = useMemo(
|
const bookingWidgetSearchData = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -61,10 +62,8 @@ export default function Rooms({
|
|||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedRates(
|
initializeRates(bookingWidgetSearchData.rooms.length)
|
||||||
new Array(bookingWidgetSearchData.rooms.length).fill(undefined)
|
}, [initializeRates, bookingWidgetSearchData.rooms.length])
|
||||||
)
|
|
||||||
}, [setSelectedRates, bookingWidgetSearchData.rooms.length])
|
|
||||||
|
|
||||||
const visibleRooms: RoomConfiguration[] = useMemo(() => {
|
const visibleRooms: RoomConfiguration[] = useMemo(() => {
|
||||||
const deduped = filterDuplicateRoomTypesByLowestPrice(
|
const deduped = filterDuplicateRoomTypesByLowestPrice(
|
||||||
@@ -117,14 +116,20 @@ export default function Rooms({
|
|||||||
const { selectedPackagesByRoom, getRooms, handleFilter, getFilteredRooms } =
|
const { selectedPackagesByRoom, getRooms, handleFilter, getFilteredRooms } =
|
||||||
useRoomFiltering({ roomsAvailability })
|
useRoomFiltering({ roomsAvailability })
|
||||||
|
|
||||||
const rateSummary = useRateSummary({
|
useEffect(() => {
|
||||||
searchedRoomsAndGuests: bookingWidgetSearchData.rooms,
|
calculateRateSummary({
|
||||||
selectedRates,
|
|
||||||
getFilteredRooms,
|
getFilteredRooms,
|
||||||
selectedPackagesByRoom,
|
|
||||||
availablePackages,
|
availablePackages,
|
||||||
roomCategories,
|
roomCategories,
|
||||||
|
selectedPackagesByRoom,
|
||||||
})
|
})
|
||||||
|
}, [
|
||||||
|
getFilteredRooms,
|
||||||
|
availablePackages,
|
||||||
|
roomCategories,
|
||||||
|
selectedPackagesByRoom,
|
||||||
|
calculateRateSummary,
|
||||||
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!rateSummary?.some((rate) => rate === null)) return
|
if (!rateSummary?.some((rate) => rate === null)) return
|
||||||
@@ -180,13 +185,6 @@ export default function Rooms({
|
|||||||
router.push(`select-bed?${queryParams}`)
|
router.push(`select-bed?${queryParams}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleModify = useCallback(
|
|
||||||
(index: number) => () => {
|
|
||||||
modifyRate(index)
|
|
||||||
},
|
|
||||||
[modifyRate]
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleFilterForRoom = useCallback(
|
const handleFilterForRoom = useCallback(
|
||||||
(index: number) =>
|
(index: number) =>
|
||||||
(filter: Record<RoomPackageCodeEnum, boolean | undefined>) => {
|
(filter: Record<RoomPackageCodeEnum, boolean | undefined>) => {
|
||||||
@@ -251,9 +249,7 @@ export default function Rooms({
|
|||||||
<SelectedRoomPanel
|
<SelectedRoomPanel
|
||||||
roomIndex={index}
|
roomIndex={index}
|
||||||
room={room}
|
room={room}
|
||||||
selectedRate={rateSummary[index]}
|
|
||||||
roomCategories={roomCategories}
|
roomCategories={roomCategories}
|
||||||
handleModify={handleModify(index)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.roomSelectionPanel}>
|
<div className={styles.roomSelectionPanel}>
|
||||||
@@ -291,9 +287,6 @@ export default function Rooms({
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<RateSummary
|
<RateSummary
|
||||||
rateSummary={rateSummary.filter(
|
|
||||||
(summary): summary is Rate => summary !== null
|
|
||||||
)}
|
|
||||||
isUserLoggedIn={isUserLoggedIn}
|
isUserLoggedIn={isUserLoggedIn}
|
||||||
packages={availablePackages}
|
packages={availablePackages}
|
||||||
roomsAvailability={roomsAvailability}
|
roomsAvailability={roomsAvailability}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import { useCallback } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { useRateSelectionStore } from "@/stores/rate-selection"
|
||||||
|
|
||||||
import { EditIcon } from "@/components/Icons"
|
import { EditIcon } from "@/components/Icons"
|
||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
@@ -9,34 +12,33 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
|||||||
|
|
||||||
import styles from "./selectedRoomPanel.module.css"
|
import styles from "./selectedRoomPanel.module.css"
|
||||||
|
|
||||||
import type {
|
import type { Room } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
Rate,
|
|
||||||
Room,
|
|
||||||
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
|
||||||
import type { RoomData } from "@/types/hotel"
|
import type { RoomData } from "@/types/hotel"
|
||||||
|
|
||||||
interface SelectedRoomPanelProps {
|
interface SelectedRoomPanelProps {
|
||||||
roomIndex: number
|
roomIndex: number
|
||||||
room: Room
|
room: Room
|
||||||
selectedRate: Rate | null
|
|
||||||
roomCategories: RoomData[]
|
roomCategories: RoomData[]
|
||||||
handleModify: () => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SelectedRoomPanel({
|
export default function SelectedRoomPanel({
|
||||||
roomIndex,
|
roomIndex,
|
||||||
room,
|
room,
|
||||||
selectedRate,
|
|
||||||
roomCategories,
|
roomCategories,
|
||||||
handleModify,
|
|
||||||
}: SelectedRoomPanelProps) {
|
}: SelectedRoomPanelProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
const { rateSummary, modifyRate } = useRateSelectionStore()
|
||||||
|
const selectedRate = rateSummary[roomIndex]
|
||||||
const images = roomCategories.find((roomCategory) =>
|
const images = roomCategories.find((roomCategory) =>
|
||||||
roomCategory.roomTypes.some(
|
roomCategory.roomTypes.some(
|
||||||
(roomType) => roomType.code === selectedRate?.roomTypeCode
|
(roomType) => roomType.code === selectedRate?.roomTypeCode
|
||||||
)
|
)
|
||||||
)?.images
|
)?.images
|
||||||
|
|
||||||
|
const handleModify = useCallback(() => {
|
||||||
|
modifyRate(roomIndex)
|
||||||
|
}, [modifyRate, roomIndex])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.selectedRoomPanel}>
|
<div className={styles.selectedRoomPanel}>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import type {
|
|||||||
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
import type { RoomConfiguration } from "@/server/routers/hotels/output"
|
import type { RoomConfiguration } from "@/server/routers/hotels/output"
|
||||||
|
|
||||||
interface UseRateSummaryProps {
|
interface UseRateSummary {
|
||||||
searchedRoomsAndGuests: Array<{ adults: number; children?: any[] }>
|
searchedRoomsAndGuests: Array<{ adults: number; children?: any[] }>
|
||||||
selectedRates: (RateCode | undefined)[]
|
selectedRates: (RateCode | undefined)[]
|
||||||
getFilteredRooms: (roomIndex: number) => RoomConfiguration[]
|
getFilteredRooms: (roomIndex: number) => RoomConfiguration[]
|
||||||
@@ -26,7 +26,7 @@ export function useRateSummary({
|
|||||||
selectedPackagesByRoom,
|
selectedPackagesByRoom,
|
||||||
availablePackages,
|
availablePackages,
|
||||||
roomCategories,
|
roomCategories,
|
||||||
}: UseRateSummaryProps) {
|
}: UseRateSummary) {
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const summaries: (Rate | null)[] = []
|
const summaries: (Rate | null)[] = []
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,40 @@
|
|||||||
import { create } from "zustand"
|
import { create } from "zustand"
|
||||||
|
|
||||||
import type { RateCode } from "@/types/components/hotelReservation/selectRate/selectRate"
|
import type {
|
||||||
|
RoomPackageCodeEnum,
|
||||||
|
RoomPackageData} from "@/types/components/hotelReservation/selectRate/roomFilter";
|
||||||
|
import type { RoomParam } from "@/types/components/hotelReservation/selectRate/section"
|
||||||
|
import type {
|
||||||
|
Rate,
|
||||||
|
RateCode,
|
||||||
|
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
|
import type { RoomConfiguration } from "@/server/routers/hotels/output"
|
||||||
|
|
||||||
|
interface RateSummaryParams {
|
||||||
|
getFilteredRooms: (roomIndex: number) => RoomConfiguration[]
|
||||||
|
availablePackages: RoomPackageData
|
||||||
|
roomCategories: Array<{ name: string; roomTypes: Array<{ code: string }> }>
|
||||||
|
selectedPackagesByRoom: Record<number, RoomPackageCodeEnum[]>
|
||||||
|
}
|
||||||
interface RateSelectionState {
|
interface RateSelectionState {
|
||||||
selectedRates: (RateCode | undefined)[]
|
selectedRates: (RateCode | undefined)[]
|
||||||
setSelectedRates: (rates: (RateCode | undefined)[]) => void
|
roomsAndGuests: RoomParam[]
|
||||||
|
rateSummary: (Rate | null)[]
|
||||||
modifyRate: (index: number) => void
|
modifyRate: (index: number) => void
|
||||||
selectRate: (index: number, rate: RateCode | undefined) => void
|
selectRate: (index: number, rate: RateCode | undefined) => void
|
||||||
|
setRoomsAndGuests: (rooms: RoomParam[]) => void
|
||||||
|
initializeRates: (count: number) => void
|
||||||
|
calculateRateSummary: ({
|
||||||
|
getFilteredRooms,
|
||||||
|
availablePackages,
|
||||||
|
roomCategories,
|
||||||
|
}: RateSummaryParams) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useRateSelectionStore = create<RateSelectionState>((set) => ({
|
export const useRateSelectionStore = create<RateSelectionState>((set, get) => ({
|
||||||
selectedRates: [],
|
selectedRates: [],
|
||||||
setSelectedRates: (rates) => set({ selectedRates: rates }),
|
roomsAndGuests: [],
|
||||||
|
rateSummary: [],
|
||||||
modifyRate: (index) =>
|
modifyRate: (index) =>
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const newRates = [...state.selectedRates]
|
const newRates = [...state.selectedRates]
|
||||||
@@ -24,4 +47,64 @@ export const useRateSelectionStore = create<RateSelectionState>((set) => ({
|
|||||||
newRates[index] = rate
|
newRates[index] = rate
|
||||||
return { selectedRates: newRates }
|
return { selectedRates: newRates }
|
||||||
}),
|
}),
|
||||||
|
initializeRates: (count) =>
|
||||||
|
set({ selectedRates: new Array(count).fill(undefined) }),
|
||||||
|
setRoomsAndGuests: (rooms) => set({ roomsAndGuests: rooms }),
|
||||||
|
calculateRateSummary: ({
|
||||||
|
getFilteredRooms,
|
||||||
|
availablePackages,
|
||||||
|
roomCategories,
|
||||||
|
selectedPackagesByRoom,
|
||||||
|
}) => {
|
||||||
|
const state = get()
|
||||||
|
const summaries = state.roomsAndGuests.map((_, roomIndex) => {
|
||||||
|
const selectedRate = state.selectedRates[roomIndex]
|
||||||
|
const filteredRooms = getFilteredRooms(roomIndex)
|
||||||
|
const selectedPackages = selectedPackagesByRoom[roomIndex] || []
|
||||||
|
|
||||||
|
const room = filteredRooms.find(
|
||||||
|
(room) => room.roomTypeCode === selectedRate?.roomTypeCode
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!room) return null
|
||||||
|
|
||||||
|
const product = room.products.find(
|
||||||
|
(product) =>
|
||||||
|
product.productType.public.rateCode === selectedRate?.publicRateCode
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!product) return null
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
set({ rateSummary: summaries })
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import type { RoomPackageData } from "./roomFilter"
|
|||||||
import type { Rate } from "./selectRate"
|
import type { Rate } from "./selectRate"
|
||||||
|
|
||||||
export interface RateSummaryProps {
|
export interface RateSummaryProps {
|
||||||
rateSummary: Rate[]
|
|
||||||
isUserLoggedIn: boolean
|
isUserLoggedIn: boolean
|
||||||
packages: RoomPackageData | undefined
|
packages: RoomPackageData | undefined
|
||||||
roomsAvailability: RoomsAvailability
|
roomsAvailability: RoomsAvailability
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { CreditCard, SafeUser } from "@/types/user"
|
import type { CreditCard, SafeUser } from "@/types/user"
|
||||||
import type { PaymentMethodEnum } from "@/constants/booking"
|
import type { PaymentMethodEnum } from "@/constants/booking"
|
||||||
|
import type { Child } from "./selectRate"
|
||||||
|
|
||||||
export interface SectionProps {
|
export interface SectionProps {
|
||||||
nextPath: string
|
nextPath: string
|
||||||
@@ -43,7 +44,7 @@ export interface PaymentClientProps
|
|||||||
|
|
||||||
export interface RoomParam {
|
export interface RoomParam {
|
||||||
adults: number
|
adults: number
|
||||||
children?: { age: number; bed: number }[]
|
children?: Child[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SectionPageProps {
|
export interface SectionPageProps {
|
||||||
|
|||||||
Reference in New Issue
Block a user