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("|"), .join("|"),
analyticsRateCode: rooms.map((room) => room.rate).join("|"), analyticsRateCode: rooms.map((room) => room.rate).join("|"),
arrivalDate: format(arrivalDate, "yyyy-MM-dd"), 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", bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
breakfastOption: rooms breakfastOption: rooms
.map(() => (offersBreakfast ? "breakfast buffet" : "no breakfast")) .map(() => (offersBreakfast ? "breakfast buffet" : "no breakfast"))

View File

@@ -103,6 +103,10 @@ export function getTracking(
.join(",") .join(",")
.toLowerCase(), .toLowerCase(),
bnr: rooms.map((r) => r.confirmationNumber).join(","), 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", bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
breakfastOption: rooms breakfastOption: rooms
.map((r) => { .map((r) => {

View File

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

View File

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

View File

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

View File

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

View File

@@ -22,7 +22,9 @@ export function getTracking(
noOfRooms: number, noOfRooms: number,
country: string | undefined, country: string | undefined,
hotelCity: string | undefined, hotelCity: string | undefined,
paramCity: string | undefined paramCity: string | undefined,
bookingCode?: string,
isBookingCodeRateAvailable?: boolean
) { ) {
const pageTrackingData: TrackingSDKPageData = { const pageTrackingData: TrackingSDKPageData = {
channel: TrackingChannelEnum["hotelreservation"], channel: TrackingChannelEnum["hotelreservation"],
@@ -44,6 +46,8 @@ export function getTracking(
.join("|"), .join("|"),
arrivalDate: format(arrivalDate, "yyyy-MM-dd"), arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
availableResults: hotelsResult, availableResults: hotelsResult,
bookingCode: bookingCode ? bookingCode : "n/a",
bookingCodeAvailability: isBookingCodeRateAvailable ? "true" : "false",
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday", bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
childBedPreference: childrenInRoom childBedPreference: childrenInRoom
?.map((c) => c?.map((k) => ChildBedMapEnum[k.bed]).join(",") ?? "-") ?.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 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( const { hotelsTrackingData, pageTrackingData } = getTracking(
params.lang, params.lang,
!!isAlternativeFor, !!isAlternativeFor,
@@ -126,35 +148,16 @@ export default async function SelectHotel({
departureDate, departureDate,
adultsInRoom, adultsInRoom,
childrenInRoom, childrenInRoom,
hotels.length, hotels?.length ?? 0,
selectHotelParams.hotelId, selectHotelParams.hotelId,
noOfRooms, noOfRooms,
hotels?.[0]?.hotel.address.country, hotels?.[0]?.hotel.address.country,
hotels?.[0]?.hotel.address.city, 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 // Special rates (corporate cheque, voucher and reward nights) will not have regular rate hotels availability
const isSpecialRate = hotels?.some( const isSpecialRate = hotels?.some(
(hotel) => (hotel) =>
@@ -189,7 +192,7 @@ export default async function SelectHotel({
</div> </div>
</header> </header>
<main className={styles.main}> <main className={styles.main}>
{isBookingCodeRateAvaliable && {isBookingCodeRateAvailable &&
isFullPriceHotelAvailable && isFullPriceHotelAvailable &&
!isSpecialRate ? ( !isSpecialRate ? (
<BookingCodeFilter /> <BookingCodeFilter />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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