feat(SW-2863): Move contentstack router to trpc package * Add exports to packages and lint rule to prevent relative imports * Add env to trpc package * Add eslint to trpc package * Apply lint rules * Use direct imports from trpc package * Add lint-staged config to trpc * Move lang enum to common * Restructure trpc package folder structure * WIP first step * update internal imports in trpc * Fix most errors in scandic-web Just 100 left... * Move Props type out of trpc * Fix CategorizedFilters types * Move more schemas in hotel router * Fix deps * fix getNonContentstackUrls * Fix import error * Fix entry error handling * Fix generateMetadata metrics * Fix alertType enum * Fix duplicated types * lint:fix * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package * Fix broken imports * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package Approved-by: Linus Flood
93 lines
2.6 KiB
TypeScript
93 lines
2.6 KiB
TypeScript
"use client"
|
|
import { useEffect } from "react"
|
|
|
|
import { useRatesStore } from "@/stores/select-rate"
|
|
|
|
import RoomProvider from "@/providers/SelectRate/RoomProvider"
|
|
import { trackLowestRoomPrice } from "@/utils/tracking"
|
|
|
|
import MultiRoomWrapper from "./MultiRoomWrapper"
|
|
import NoAvailabilityAlert from "./NoAvailabilityAlert"
|
|
import RoomsHeader from "./RoomsHeader"
|
|
import RoomsList from "./RoomsList"
|
|
|
|
import styles from "./rooms.module.css"
|
|
|
|
import type { PriceProduct } from "@scandic-hotels/trpc/types/roomAvailability"
|
|
|
|
export default function Rooms() {
|
|
const {
|
|
arrivalDate,
|
|
bookingRooms,
|
|
departureDate,
|
|
hotelId,
|
|
rooms,
|
|
visibleRooms,
|
|
} = useRatesStore((state) => ({
|
|
arrivalDate: state.booking.fromDate,
|
|
bookingRooms: state.booking.rooms,
|
|
departureDate: state.booking.toDate,
|
|
hotelId: state.booking.hotelId,
|
|
rooms: state.rooms,
|
|
visibleRooms: state.roomConfigurations,
|
|
}))
|
|
|
|
useEffect(() => {
|
|
const pricesWithCurrencies = visibleRooms.flatMap((roomConfiguration) =>
|
|
roomConfiguration.flatMap((room) =>
|
|
room.products
|
|
.filter(
|
|
(product): product is PriceProduct =>
|
|
!!(
|
|
("public" in product && product.public) ||
|
|
("member" in product && product.member)
|
|
)
|
|
)
|
|
.map((product) => ({
|
|
currency: (product.public?.localPrice.currency ||
|
|
product.member?.localPrice.currency)!,
|
|
price: (product.public?.localPrice.pricePerNight ||
|
|
product.member?.localPrice.pricePerNight)!,
|
|
}))
|
|
)
|
|
)
|
|
|
|
// Specific n/a when no prices available in reward night and voucher scenarios
|
|
const lowestPrice = pricesWithCurrencies.length
|
|
? pricesWithCurrencies
|
|
.reduce((minPrice, { price }) => Math.min(minPrice, price), Infinity)
|
|
.toString()
|
|
: "n/a"
|
|
|
|
const currency = pricesWithCurrencies.length
|
|
? pricesWithCurrencies[0]?.currency
|
|
: "n/a"
|
|
|
|
trackLowestRoomPrice({
|
|
hotelId,
|
|
arrivalDate,
|
|
departureDate,
|
|
lowestPrice: lowestPrice,
|
|
currency: currency,
|
|
})
|
|
}, [arrivalDate, departureDate, hotelId, visibleRooms])
|
|
|
|
return (
|
|
<div className={styles.content}>
|
|
{bookingRooms.map((room, idx) => (
|
|
<RoomProvider
|
|
key={`${room.rateCode}-${room.roomTypeCode}-${idx}`}
|
|
idx={idx}
|
|
room={rooms[idx]}
|
|
>
|
|
<MultiRoomWrapper isMultiRoom={bookingRooms.length > 1}>
|
|
<RoomsHeader />
|
|
<NoAvailabilityAlert />
|
|
<RoomsList />
|
|
</MultiRoomWrapper>
|
|
</RoomProvider>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|