Files
web/apps/scandic-web/utils/tracking/myStay.ts
Anton Gunnarsson e4a66499e5 Merged in feat/sw-3322-move-base-tracking-to-common (pull request #2713)
feat(SW-3322): Move base tracking to common package

* Move base tracking to common package

* Update lock file


Approved-by: Joakim Jäderberg
2025-08-27 12:29:46 +00:00

327 lines
8.7 KiB
TypeScript

import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { trackEvent } from "@scandic-hotels/common/tracking/base"
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
import type { PackageSchema } from "@scandic-hotels/trpc/types/bookingConfirmation"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
import type { SelectedAncillary } from "@/types/components/myPages/myStay/ancillaries"
import type { Room } from "@/types/stores/my-stay"
import type { BreakfastData } from "@/stores/my-stay/add-ancillary-flow"
export function trackCancelStay(
hotelId: string,
duration: number,
bnr: string,
roomPrice?: number
) {
trackEvent({
event: "BookingCancellations",
hotelInfo: {
hotelId: hotelId,
duration,
roomPrice,
bnr: bnr,
},
})
}
export function trackMyStayPageLink(ctaName: string) {
trackEvent({
event: "confirmationPageLinks",
cta: {
name: ctaName,
},
})
}
type LateArrivalGuarantee = "mandatory" | "yes" | "no" | "na"
export function trackGlaSaveCardAttempt(
hotelId: string,
savedCreditCard: CreditCard | undefined,
lateArrivalGuarantee: LateArrivalGuarantee
) {
trackEvent({
event: "glaCardSaveAttempt",
hotelInfo: {
hotelId,
lateArrivalGuarantee,
guaranteedProduct: "room",
},
paymentInfo: {
status: "glacardsaveattempt",
isSavedCreditCard: !!savedCreditCard,
type: savedCreditCard?.cardType,
},
})
}
export function buildAncillariesTracking(
packages: {
code: string
quantity: number
comment?: string
}[],
selectedAncillary: SelectedAncillary | null | undefined,
deliveryTime: string | string[] | null | undefined
) {
return packages.map((pkg) => {
const payedWithCard = pkg.code === selectedAncillary?.id
const payedWithPoints = pkg.code === selectedAncillary?.loyaltyCode
const ancillaryDeliveryTime = selectedAncillary?.requiresDeliveryTime
? deliveryTime
: undefined
return {
productId: pkg.code,
productUnits: pkg.quantity,
productDeliveryTime: ancillaryDeliveryTime,
productName: selectedAncillary?.title,
productCategory: selectedAncillary?.categoryName,
...(payedWithCard && {
productPrice: (selectedAncillary?.price.total ?? 0) * pkg.quantity,
currency: selectedAncillary?.price.currency,
}),
...(payedWithPoints && {
productPoints: (selectedAncillary?.points ?? 0) * pkg.quantity,
}),
}
})
}
export function trackGlaAncillaryAttempt(
savedCreditCard: CreditCard | undefined,
packages: {
code: string
quantity: number
comment: string | undefined
}[],
selectedAncillary: SelectedAncillary | null,
deliveryTime: string | undefined,
breakfastData: BreakfastData | null
) {
trackEvent({
event: "GuaranteeAttemptAncillary",
paymentInfo: {
status: "glacardsaveattempt",
type: savedCreditCard?.cardType,
},
ancillaries: breakfastData
? buildBreakfastTracking(breakfastData, selectedAncillary?.hotelId)
: buildAncillariesTracking(packages, selectedAncillary, deliveryTime),
hotelInfo: {
hotelId: selectedAncillary?.hotelId,
lateArrivalGuarantee: "yes",
guaranteedProduct: "room + ancillary",
},
})
}
export function trackAncillarySuccess(
confirmationNumber: string,
packages: {
code: string
quantity: number
comment?: string
}[],
deliveryTime: string | null | undefined,
guaranteedProduct: string,
selectedAncillary: SelectedAncillary | null,
breakfastData: BreakfastData | null,
cardType?: string,
roomTypeCode?: string
) {
trackEvent({
event: "AncillarySuccess",
hotelInfo: {
bnr: confirmationNumber,
roomTypeCode: roomTypeCode,
lateArrivalGuarantee: "yes",
guaranteedProduct: guaranteedProduct,
},
paymentInfo: {
status: "glacardsaveconfirmed",
type: cardType,
},
ancillaries: breakfastData
? buildBreakfastTracking(breakfastData, selectedAncillary?.hotelId)
: buildAncillariesTracking(packages, selectedAncillary, deliveryTime),
})
}
export function trackAncillaryFailed(
packages: {
code: string
quantity: number
comment?: string
}[],
deliveryTime: string | null | undefined,
selectedAncillary: SelectedAncillary | null,
breakfastData: BreakfastData | null
) {
trackEvent({
event: "GuaranteeFailAncillary",
ancillaries: breakfastData
? buildBreakfastTracking(breakfastData, selectedAncillary?.hotelId)
: buildAncillariesTracking(packages, selectedAncillary, deliveryTime),
hotelInfo: {
hotelId: selectedAncillary?.hotelId,
lateArrivalGuarantee: "yes",
guaranteedProduct: "ancillary",
},
})
}
export function buildBreakfastTracking(
breakfastData: BreakfastData,
hotelId?: number
) {
const items = []
if (breakfastData.nrOfAdults) {
items.push({
hotelId,
productId: BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST,
productName: "Breakfast",
productUnits: breakfastData.nrOfAdults * breakfastData.nrOfNights,
productPrice:
breakfastData.priceAdult *
breakfastData.nrOfAdults *
breakfastData.nrOfNights,
currency: breakfastData.currency,
productCategory: "Food",
})
}
if (breakfastData.nrOfPayingChildren) {
items.push({
hotelId,
productId: BreakfastPackageEnum.ANCILLARY_CHILD_PAYING_BREAKFAST,
productName: "Breakfast",
productUnits: breakfastData.nrOfPayingChildren * breakfastData.nrOfNights,
productPrice:
breakfastData.priceChild *
breakfastData.nrOfPayingChildren *
breakfastData.nrOfNights,
currency: breakfastData.currency,
productCategory: "Food",
})
}
return items
}
export function trackViewAncillary(
ancillary: SelectedAncillary,
booking: Room
) {
const { hotelId, id, title, categoryName } = ancillary
const isBreakfast = id === BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST
const hasPayingChildren = booking.childrenAges.some((age) => age >= 4)
const ancillaries = [
{
hotelId,
productId: id,
productName: title,
productCategory: categoryName,
},
]
if (isBreakfast && hasPayingChildren) {
ancillaries.push({
hotelId,
productId: BreakfastPackageEnum.ANCILLARY_CHILD_PAYING_BREAKFAST,
productName: title,
productCategory: categoryName,
})
}
trackEvent({
event: "viewAncillary",
ancillaries,
})
}
export function trackRemoveAncillary(
ancillary: PackageSchema,
hotelId: string,
deliveryTime?: string,
addedBreakfastPackages?: PackageSchema[]
) {
const isBreakfastPackage =
ancillary.code === BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST
const isPoints = ancillary.currency === CurrencyEnum.POINTS
const packagesWithoutFreeChildBreakfast = addedBreakfastPackages?.filter(
(p) => p.code !== BreakfastPackageEnum.FREE_CHILD_BREAKFAST
)
const ancillaries = isBreakfastPackage
? (packagesWithoutFreeChildBreakfast?.map((pkg) => ({
hotelId,
productId: pkg.code,
productPrice: pkg.totalPrice,
productUnits: pkg.totalUnit,
productType: pkg.type,
})) ?? [])
: [
{
hotelId,
productId: ancillary.code,
productPrice: isPoints ? 0 : ancillary.totalPrice,
productPoints: isPoints ? ancillary.totalPrice : 0,
productUnits: ancillary.totalUnit,
productType: ancillary.type,
productDeliveryTime: deliveryTime,
},
]
trackEvent({
event: "removeAncillary",
ancillaries,
})
}
export function trackAddAncillary(
ancillary: SelectedAncillary | null,
quantityWithCard: number | null,
quantityWithPoints: number | null,
breakfastData: BreakfastData | null
) {
if (breakfastData) {
return trackEvent({
event: "addAncillary",
ancillaries: buildBreakfastTracking(breakfastData, ancillary?.hotelId),
})
}
const ancillaries = []
if ((quantityWithCard ?? 0) > 0) {
ancillaries.push({
hotelId: ancillary?.hotelId,
productId: ancillary?.id,
productName: ancillary?.title,
productUnits: quantityWithCard,
productPrice: (ancillary?.price.total ?? 0) * (quantityWithCard ?? 0),
currency: ancillary?.price.currency,
productCategory: ancillary?.categoryName,
})
}
if ((quantityWithPoints ?? 0) > 0) {
ancillaries.push({
hotelId: ancillary?.hotelId,
productId: ancillary?.loyaltyCode,
productName: ancillary?.title,
productUnits: quantityWithPoints,
productPoints: (ancillary?.points ?? 0) * (quantityWithPoints ?? 0),
productCategory: ancillary?.categoryName,
})
}
trackEvent({
event: "addAncillary",
ancillaries,
})
}