Merged in feat/SW-1517-booking-codes-tracking (pull request #1745)

Feat/SW-1517 booking codes tracking

* feat: SW-1517 Updated tracking to inlcude booking code info

* feat: SW-1517 Tracking booking codes

* feat: SW-1517 booking code multiroom tracking

* feat: SW-1517 booking code tracking select-hotel map view

* feat: SW-1517 Updated to optional param

* feat: SW-1517 Optimized with map

* feat: SW-1517 Typings update

* feat: SW-1517 Replaced reduce with map and join

* feat: SW-1517 Updated typings


Approved-by: Christian Andolf
This commit is contained in:
Hrishikesh Vaipurkar
2025-04-14 07:17:40 +00:00
parent cc7aa6e317
commit e372b91356
14 changed files with 103 additions and 34 deletions

View File

@@ -45,6 +45,17 @@ export function getTracking(
.join("|"),
analyticsRateCode: rooms.map((room) => room.rate).join("|"),
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
// Comma separated booking code values in "code,code,n/a" format for multiroom and "code" or "n/a" for singleroom
// n/a is used whenever code is Not applicable as defined by Tracking team
bookingCode: rooms
.map((room) => room.roomRate.bookingCode ?? "n/a")
.join(", "),
// Similar to booking code, comma separated room based values.
bookingCodeAvailability: booking.bookingCode
? rooms
.map((room) => (room.roomRate.bookingCode ? "true" : "false"))
.join(", ")
: undefined,
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
breakfastOption: rooms
.map(() => (offersBreakfast ? "breakfast buffet" : "no breakfast"))

View File

@@ -103,6 +103,10 @@ export function getTracking(
.join(",")
.toLowerCase(),
bnr: rooms.map((r) => r.confirmationNumber).join(","),
bookingCode: rooms.map((room) => room.bookingCode ?? "n/a").join(", "),
bookingCodeAvailability: booking.bookingCode
? rooms.map((room) => (room.bookingCode ? "true" : "false")).join(", ")
: undefined,
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
breakfastOption: rooms
.map((r) => {

View File

@@ -51,6 +51,7 @@ export function mapRoomState(
return {
adults: booking.adults,
bedDescription: room.bedType.description,
bookingCode: booking.bookingCode,
breakfast,
breakfastIncluded,
cheques: booking.cheques,

View File

@@ -15,6 +15,7 @@ import SelectHotelMap from "."
import type { SelectHotelMapContainerProps } from "@/types/components/hotelReservation/selectHotel/map"
import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
import { RateTypeEnum } from "@/types/enums/rateType"
export async function SelectHotelMapContainer({
searchParams,
@@ -73,6 +74,14 @@ export async function SelectHotelMapContainer({
const arrivalDate = new Date(selectHotelParams.fromDate)
const departureDate = new Date(selectHotelParams.toDate)
const isBookingCodeRateAvailable = bookingCode
? hotels?.some(
(hotel) =>
hotel.availability.productType?.public?.rateType !==
RateTypeEnum.Regular
)
: false
const { hotelsTrackingData, pageTrackingData } = getTracking(
lang,
!!isAlternativeFor,
@@ -86,7 +95,9 @@ export async function SelectHotelMapContainer({
noOfRooms,
hotels?.[0]?.hotel.address.country,
hotels?.[0]?.hotel.address.city,
selectHotelParams.city
selectHotelParams.city,
bookingCode,
isBookingCodeRateAvailable
)
return (
@@ -99,6 +110,7 @@ export async function SelectHotelMapContainer({
filterList={filterList}
cityCoordinates={cityCoordinates}
bookingCode={bookingCode ?? ""}
isBookingCodeRateAvailable={isBookingCodeRateAvailable}
/>
<TrackingSDK pageData={pageTrackingData} hotelInfo={hotelsTrackingData} />
</>

View File

@@ -41,6 +41,7 @@ export default function SelectHotelContent({
hotels,
filterList,
bookingCode,
isBookingCodeRateAvailable,
}: Omit<SelectHotelMapProps, "apiKey">) {
const lang = useLang()
const intl = useIntl()
@@ -140,6 +141,16 @@ export default function SelectHotelContent({
</Button>
)
const isRegularRateAvailable = bookingCode
? hotels.some(
(hotel) =>
hotel.availability.productType?.public?.rateType ===
RateTypeEnum.Regular ||
hotel.availability.productType?.member?.rateType ===
RateTypeEnum.Regular
)
: false
return (
<div className={styles.container}>
<div className={styles.listingContainer} ref={listingContainerRef}>
@@ -160,7 +171,11 @@ export default function SelectHotelContent({
filters={filterList}
setShowSkeleton={setShowSkeleton}
/>
{bookingCode ? <BookingCodeFilter /> : null}
{bookingCode &&
isBookingCodeRateAvailable &&
isRegularRateAvailable ? (
<BookingCodeFilter />
) : null}
</div>
{showSkeleton ? (

View File

@@ -14,6 +14,7 @@ export default function SelectHotelMap({
filterList,
cityCoordinates,
bookingCode,
isBookingCodeRateAvailable,
}: SelectHotelMapProps) {
return (
<APIProvider apiKey={apiKey}>
@@ -24,6 +25,7 @@ export default function SelectHotelMap({
hotels={hotels}
filterList={filterList}
bookingCode={bookingCode}
isBookingCodeRateAvailable={isBookingCodeRateAvailable}
/>
</APIProvider>
)

View File

@@ -22,7 +22,9 @@ export function getTracking(
noOfRooms: number,
country: string | undefined,
hotelCity: string | undefined,
paramCity: string | undefined
paramCity: string | undefined,
bookingCode?: string,
isBookingCodeRateAvailable?: boolean
) {
const pageTrackingData: TrackingSDKPageData = {
channel: TrackingChannelEnum["hotelreservation"],
@@ -44,6 +46,8 @@ export function getTracking(
.join("|"),
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
availableResults: hotelsResult,
bookingCode: bookingCode ? bookingCode : "n/a",
bookingCodeAvailability: isBookingCodeRateAvailable ? "true" : "false",
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
childBedPreference: childrenInRoom
?.map((c) => c?.map((k) => ChildBedMapEnum[k.bed]).join(",") ?? "-")

View File

@@ -119,6 +119,28 @@ export default async function SelectHotel({
const isAllUnavailable = !hotels.length
const suspenseKey = stringify(searchParams)
const isFullPriceHotelAvailable = bookingCode
? hotels?.some(
(hotel) =>
hotel.availability.productType?.public?.rateType ===
RateTypeEnum.Regular ||
hotel.availability.productType?.member?.rateType ===
RateTypeEnum.Regular
)
: false
const isBookingCodeRateAvailable = bookingCode
? hotels?.some(
(hotel) =>
hotel.availability.productType?.public?.rateType !==
RateTypeEnum.Regular ||
hotel.availability.productType?.member?.rateType !==
RateTypeEnum.Regular
)
: false
const { hotelsTrackingData, pageTrackingData } = getTracking(
params.lang,
!!isAlternativeFor,
@@ -126,35 +148,16 @@ export default async function SelectHotel({
departureDate,
adultsInRoom,
childrenInRoom,
hotels.length,
hotels?.length ?? 0,
selectHotelParams.hotelId,
noOfRooms,
hotels?.[0]?.hotel.address.country,
hotels?.[0]?.hotel.address.city,
selectHotelParams.city
selectHotelParams.city,
bookingCode,
isBookingCodeRateAvailable ? "true" : "false"
)
const suspenseKey = stringify(searchParams)
let isFullPriceHotelAvailable
let isBookingCodeRateAvaliable
if (bookingCode) {
isFullPriceHotelAvailable = hotels?.find(
(hotel) =>
hotel.availability.productType?.public?.rateType ===
RateTypeEnum.Regular ||
hotel.availability.productType?.member?.rateType ===
RateTypeEnum.Regular
)
isBookingCodeRateAvaliable = hotels?.find(
(hotel) =>
hotel.availability.productType?.public?.rateType !==
RateTypeEnum.Regular ||
hotel.availability.productType?.member?.rateType !==
RateTypeEnum.Regular
)
}
// Special rates (corporate cheque, voucher and reward nights) will not have regular rate hotels availability
const isSpecialRate = hotels?.some(
(hotel) =>
@@ -189,7 +192,7 @@ export default async function SelectHotel({
</div>
</header>
<main className={styles.main}>
{isBookingCodeRateAvaliable &&
{isBookingCodeRateAvailable &&
isFullPriceHotelAvailable &&
!isSpecialRate ? (
<BookingCodeFilter />

View File

@@ -21,7 +21,9 @@ export function getTracking(
noOfRooms: number,
country: string | undefined,
hotelCity: string | undefined,
paramCity: string | undefined
paramCity: string | undefined,
bookingCode?: string,
isBookingCodeRateAvailable?: string
) {
const pageTrackingData: TrackingSDKPageData = {
channel: TrackingChannelEnum["hotelreservation"],
@@ -57,6 +59,10 @@ export function getTracking(
region: hotelCity,
searchTerm: isAlternativeFor ? hotelId : (paramCity as string),
searchType: "destination",
bookingCode: bookingCode ?? "n/a",
bookingCodeAvailability: bookingCode
? isBookingCodeRateAvailable
: undefined,
}
return {

View File

@@ -28,8 +28,14 @@ export default async function SelectRatePage({
if (!searchDetails?.hotel) {
return notFound()
}
const { adultsInRoom, childrenInRoom, hotel, noOfRooms, selectHotelParams } =
searchDetails
const {
adultsInRoom,
childrenInRoom,
hotel,
noOfRooms,
selectHotelParams,
bookingCode,
} = searchDetails
const hotelData = await getHotel({
hotelId: hotel.id,
@@ -63,7 +69,8 @@ export default async function SelectRatePage({
noOfRooms,
hotelData.hotel.address.country,
hotelData.hotel.address.city,
selectHotelParams.city
selectHotelParams.city,
bookingCode
)
const booking = convertSearchParamsToObj<SelectRateSearchParams>(searchParams)

View File

@@ -20,7 +20,8 @@ export function getTracking(
noOfRooms: number,
country: string | undefined,
hotelCity: string | undefined,
paramCity: string | undefined
paramCity: string | undefined,
bookingCode?: string
) {
const pageTrackingData: TrackingSDKPageData = {
channel: TrackingChannelEnum.hotelreservation,
@@ -52,6 +53,7 @@ export function getTracking(
region: hotelCity,
searchTerm: paramCity ?? hotelName,
searchType: "hotel",
bookingCode: bookingCode ?? "n/a",
}
return {

View File

@@ -22,6 +22,7 @@ export interface SelectHotelMapProps {
filterList: CategorizedFilters
cityCoordinates: Coordinates
bookingCode: string | undefined
isBookingCodeRateAvailable?: boolean
}
type ImageSizes = z.infer<typeof imageSchema>["imageSizes"]

View File

@@ -63,8 +63,8 @@ export type TrackingSDKHotelInfo = {
bnr?: string // Booking number
breakfastOption?: string // "no breakfast" or "breakfast buffet"
//bonuscheque?: boolean
//bookingCode?: string
//bookingCodeAvailability?: boolean
bookingCode?: string
bookingCodeAvailability?: string
bookingTypeofDay?: "weekend" | "weekday"
childBedPreference?: string
country?: string // Country of the hotel

View File

@@ -12,6 +12,7 @@ export interface ChildBedPreference {
export interface Room {
adults: number
bedDescription: string
bookingCode: string | null
breakfast?: PackageSchema
breakfastIncluded: boolean
cheques: number