diff --git a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/RoomCard/index.tsx b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/RoomCard/index.tsx
index e0d66ff63..37377d079 100644
--- a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/RoomCard/index.tsx
+++ b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/RoomCard/index.tsx
@@ -146,56 +146,40 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
const payLater = intl.formatMessage({ id: "Pay later" })
const payNow = intl.formatMessage({ id: "Pay now" })
- function getRate(rateCode: string, rateDefinition?: RateDefinition) {
- const rateObj = {
- terms: rateDefinition?.generalTerms,
- rateTitle:
- rateDefinition?.rateType !== RateTypeEnum.Regular
- ? rateDefinition?.title
- : undefined,
- }
+ // Possible undefined rate definition carried from roomsAvailability possibility of null
+ function getRate(rateCode: string) {
switch (rateCode) {
case "change":
return {
isFlex: false,
notAvailable: false,
title: freeBooking,
- ...rateObj,
}
case "flex":
return {
isFlex: true,
notAvailable: false,
title: freeCancelation,
- ...rateObj,
}
case "save":
return {
isFlex: false,
notAvailable: false,
title: nonRefundable,
- ...rateObj,
}
default:
throw new Error(
- `Unknown key for rate, should be "change", "flex", "save" or "special", but got ${rateCode}`
+ `Unknown key for rate, should be "change", "flex", "save", but got ${rateCode}`
)
}
}
function getRateInfo(product: Product) {
- const rateDefinition = rateDefinitions?.filter(
- (rateDefinition) =>
- rateDefinition.rateCode === product.productType.public.rateCode
- )[0]
if (
!product.productType.public.rateCode &&
!product.productType.member?.rateCode
) {
- const possibleRate = getRate(
- product.productType.public.rate,
- rateDefinition
- )
+ const possibleRate = getRate(product.productType.public.rate)
if (possibleRate) {
return {
...possibleRate,
@@ -206,8 +190,6 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
isFlex: false,
notAvailable: true,
title: "",
- terms: undefined,
- rateTitle: undefined,
}
}
@@ -225,15 +207,23 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
)
}
+ // At least one rate is required to proceed here
if (!publicRate && !memberRate) {
throw new Error(
"We should never make it here without any single available rateCode"
)
}
- const specialRate = publicRate || memberRate
- if (product.productType.public.rateType !== "Regular" && specialRate) {
- return getRate(specialRate, rateDefinition)
+
+ // Booking code scenario which has various rate types in which only
+ // public rate code is allowed/obtained from the API
+ const isBookingCodeRate =
+ product.productType.public.rateType !== RateTypeEnum.Regular
+ if (isBookingCodeRate) {
+ //@ts-ignore (publicRate || memberRate) types as `string | undefined` instead of just `string`
+ return getRate(publicRate || memberRate)
}
+
+ // Regular rates (Save, Change, Flex) requires both public and member rates availability
if (!publicRate || !memberRate) {
throw new Error(
"We should never make it here without both public and member rateCodes"
@@ -241,10 +231,29 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
}
const key = isUserLoggedIn && isMainRoom ? memberRate : publicRate
- return getRate(key, rateDefinition)
+ return getRate(key)
}
- const isSpecialRate =
+ function getPartialRateDefinition(
+ product: Product,
+ rateDefinitions: RateDefinition[]
+ ) {
+ return rateDefinitions
+ .filter((rateDefinition) =>
+ isUserLoggedIn && product.productType.member
+ ? rateDefinition.rateCode === product.productType.member.rateCode
+ : rateDefinition.rateCode === product.productType.public.rateCode
+ )
+ .flatMap((rateDefinition) => ({
+ terms: rateDefinition.generalTerms,
+ rateTitle:
+ rateDefinition.rateType !== RateTypeEnum.Regular
+ ? rateDefinition.title
+ : undefined,
+ }))[0]
+ }
+
+ const isBookingCodeRate =
bookingCode &&
roomConfiguration.products.every((item) => {
return item.productType.public.rateType !== RateTypeEnum.Regular
@@ -335,7 +344,7 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
{breakfastMessage}
{bookingCode ? (
-
+
{bookingCode}
@@ -343,19 +352,20 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
{roomConfiguration.products.map((product) => {
const rate = getRateInfo(product)
+ const rateDefinition = getPartialRateDefinition(
+ product,
+ rateDefinitions
+ )
const isSelectedRateCode =
selectedRate?.product.productType.public.rateCode ===
product.productType.public.rateCode ||
(selectedRate?.product.productType.member?.rateCode ===
product.productType.member?.rateCode &&
+ // to handle undefined === undefined scenarios in booking code rates
product.productType.member?.rateCode !== undefined)
return (
)
})}
diff --git a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/index.tsx b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/index.tsx
index 55a4dd0c0..882450e63 100644
--- a/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/index.tsx
+++ b/apps/scandic-web/components/HotelReservation/SelectRate/RoomsContainer/Rooms/RoomSelectionPanel/index.tsx
@@ -19,6 +19,7 @@ import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHote
import { AlertTypeEnum } from "@/types/enums/alert"
import { BookingCodeFilterEnum } from "@/types/enums/bookingCodeFilter"
import { RateTypeEnum } from "@/types/enums/rateType"
+import type { RoomConfiguration } from "@/types/trpc/routers/hotel/roomAvailability"
export default function RoomSelectionPanel() {
const { rooms } = useRoomContext()
@@ -33,67 +34,67 @@ export default function RoomSelectionPanel() {
(state) => state.activeCodeFilter
)
- let filteredRooms = rooms,
- isRegularRatesAvailableWithCode: boolean = false,
- noAvailabilityWithBookingCode: boolean = false
- if (bookingCode) {
- isRegularRatesAvailableWithCode = bookingCode
- ? rooms?.some((room) => {
- return (
- room.status === AvailabilityEnum.Available &&
- room.products.some(
- (product) =>
- product.productType.public.rateType === RateTypeEnum.Regular
- )
- )
- })
- : false
+ // With Booking code rates we will always obtain public rate and never a member rate,
+ // so we should ignore it from the logic below.
+ const isRegularRatesAvailableWithCode =
+ bookingCode &&
+ rooms.some(
+ (room) =>
+ room.status === AvailabilityEnum.Available &&
+ room.products.some(
+ (product) =>
+ product.productType.public.rateType === RateTypeEnum.Regular
+ )
+ )
- noAvailabilityWithBookingCode = bookingCode
- ? !rooms?.some((room) => {
- return (
- room.status === AvailabilityEnum.Available &&
- room.products.some(
- (product) =>
- product.productType.public.rateType !== RateTypeEnum.Regular
- )
- )
- })
- : false
+ // Booking codes rate comes with various rate types but Regular is reserved
+ // for non-booking code rates (Save, Change & Flex)
+ const isBookingCodeRatesAvailable =
+ bookingCode &&
+ rooms.some(
+ (room) =>
+ room.status === AvailabilityEnum.Available &&
+ room.products.some(
+ (product) =>
+ product.productType.public.rateType !== RateTypeEnum.Regular
+ )
+ )
- filteredRooms =
- noAvailabilityWithBookingCode ||
- !isRegularRatesAvailableWithCode ||
- activeCodeFilter === BookingCodeFilterEnum.All
- ? rooms
- : rooms.filter((room) => {
- return (
- room.status === AvailabilityEnum.Available &&
- room.products.every(
- (product) =>
- (activeCodeFilter === BookingCodeFilterEnum.Discounted &&
- product.productType.public.rateType !==
- RateTypeEnum.Regular) ||
- (activeCodeFilter === BookingCodeFilterEnum.Regular &&
- product.productType.public.rateType ===
- RateTypeEnum.Regular)
- )
- )
- })
- }
+ // Show all rooms if either booking code rates or regular rates are not available
+ // or filter selection is All rooms
+ const showAllRooms =
+ !isBookingCodeRatesAvailable ||
+ !isRegularRatesAvailableWithCode ||
+ activeCodeFilter === BookingCodeFilterEnum.All
+ const bookingCodeDiscountedRooms = rooms.filter(
+ (room) =>
+ room.status === AvailabilityEnum.Available &&
+ room.products.every(
+ (product) =>
+ product.productType.public.rateType !== RateTypeEnum.Regular
+ )
+ )
+ const regularRateRooms = rooms.filter(
+ (room) =>
+ room.status === AvailabilityEnum.Available &&
+ room.products.every(
+ (product) =>
+ product.productType.public.rateType === RateTypeEnum.Regular
+ )
+ )
+ // Show booking code filter when both of the booking code rates or regular rates are available
+ const showBookingCodeFilter =
+ isRegularRatesAvailableWithCode && isBookingCodeRatesAvailable
return (
<>
- {noAvailableRooms ||
- (bookingCode &&
- isRegularRatesAvailableWithCode &&
- noAvailabilityWithBookingCode) ? (
+ {noAvailableRooms || (bookingCode && !isBookingCodeRatesAvailable) ? (
) : null}
- {bookingCode &&
- isRegularRatesAvailableWithCode &&
- !noAvailabilityWithBookingCode ? (
-
- ) : null}
+ {showBookingCodeFilter ? : null}
- {filteredRooms.map((roomConfiguration) => (
-
- ))}
+ {/* Show either Booking code filtered rooms or all the rooms */}
+ {showAllRooms
+ ? rooms.map((roomConfiguration) => RoomCardWrap(roomConfiguration))
+ : activeCodeFilter === BookingCodeFilterEnum.Discounted
+ ? bookingCodeDiscountedRooms.map((roomConfiguration) =>
+ RoomCardWrap(roomConfiguration)
+ )
+ : regularRateRooms.map((roomConfiguration) =>
+ RoomCardWrap(roomConfiguration)
+ )}
>
)
}
+
+function RoomCardWrap(roomConfiguration: RoomConfiguration) {
+ return (
+
+ )
+}
diff --git a/apps/scandic-web/i18n/dictionaries/en.json b/apps/scandic-web/i18n/dictionaries/en.json
index 88ae9ae83..66b23086a 100644
--- a/apps/scandic-web/i18n/dictionaries/en.json
+++ b/apps/scandic-web/i18n/dictionaries/en.json
@@ -524,7 +524,6 @@
"Reference": "Reference",
"Reference #{bookingNr}": "Reference #{bookingNr}",
"Reference number": "Reference number",
- "Regular price": "Regular price",
"Relax": "Relax",
"Remember code": "Remember code",
"Remove card from member profile": "Remove card from member profile",
diff --git a/apps/scandic-web/server/routers/hotels/schemas/roomAvailability/configuration.ts b/apps/scandic-web/server/routers/hotels/schemas/roomAvailability/configuration.ts
index 48b21766b..56acc0e14 100644
--- a/apps/scandic-web/server/routers/hotels/schemas/roomAvailability/configuration.ts
+++ b/apps/scandic-web/server/routers/hotels/schemas/roomAvailability/configuration.ts
@@ -44,7 +44,7 @@ export const roomConfigurationSchema = z
return product
}
- // Return rate even if single when special rates
+ // Return rate even if single when booking code rate which can be any one of other rate types
if (product.productType.public.rateType !== RateTypeEnum.Regular) {
return product
}
@@ -73,7 +73,8 @@ export const roomConfigurationSchema = z
/**
* When all products miss at least one rateCode (member or public), we change the status to NotAvailable
* since we cannot as of now (31 january) guarantee the flow with missing rateCodes.
- * Exception Special rate (Booking code rates)
+ * This rule applies to regular rates (Save, Change and Flex)
+ * Exception Booking code rate
*
* TODO: (Maybe) notify somewhere that this happened
*/