Merged in feat/sw-2873-move-selecthotel-to-booking-flow (pull request #2727)

feat(SW-2873): Move select-hotel to booking flow

* crude setup of select-hotel in partner-sas

* wip

* Fix linting

* restructure tracking files

* Remove dependency on trpc in tracking hooks

* Move pageview tracking to common

* Fix some lint and import issues

* Add AlternativeHotelsPage

* Add SelectHotelMapPage

* Add AlternativeHotelsMapPage

* remove next dependency in tracking store

* Remove dependency on react in tracking hooks

* move isSameBooking to booking-flow

* Inject searchParamsComparator into tracking store

* Move useTrackHardNavigation to common

* Move useTrackSoftNavigation to common

* Add TrackingSDK to partner-sas

* call serverclient in layout

* Remove unused css

* Update types

* Move HotelPin type

* Fix todos

* Merge branch 'master' into feat/sw-2873-move-selecthotel-to-booking-flow

* Merge branch 'master' into feat/sw-2873-move-selecthotel-to-booking-flow

* Fix component


Approved-by: Joakim Jäderberg
This commit is contained in:
Anton Gunnarsson
2025-09-01 08:37:00 +00:00
parent 93a90bef9d
commit 87402a2092
157 changed files with 2026 additions and 1376 deletions

View File

@@ -1,18 +0,0 @@
export type AvailabilityInput = {
cityId: string
roomStayStartDate: string
roomStayEndDate: string
adults: number
children?: string
bookingCode?: string
redemption?: boolean
}
export type AlternativeHotelsAvailabilityInput = {
roomStayStartDate: string
roomStayEndDate: string
adults: number
children?: string
bookingCode?: string
redemption?: boolean
}

View File

@@ -1,6 +0,0 @@
import type { CategorizedHotelFilters } from "./hotelFilters"
export type FilterAndSortModalProps = {
filters: CategorizedHotelFilters
setShowSkeleton?: (showSkeleton: boolean) => void
}

View File

@@ -1,7 +0,0 @@
export type FilterCheckboxProps = {
name: string
id: string
isDisabled?: boolean
isSelected: boolean
onChange: (filterId: string) => void
}

View File

@@ -1,25 +0,0 @@
import type { ProductType } from "@scandic-hotels/trpc/types/availability"
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
import type { HotelResponse } from "@/components/HotelReservation/SelectHotel/helpers"
export enum HotelCardListingTypeEnum {
MapListing = "mapListing",
PageListing = "pageListing",
}
export type HotelData = {
hotelData: Hotel
price: ProductType
}
export type HotelCardListingProps = {
hotelData: HotelResponse[]
unfilteredHotelCount: number
type?: HotelCardListingTypeEnum
isAlternative?: boolean
}
export interface NullableHotelData extends Omit<HotelData, "hotelData"> {
hotelData: HotelData["hotelData"] | null
}

View File

@@ -1,11 +0,0 @@
import type { HotelResponse } from "@/components/HotelReservation/SelectHotel/helpers"
import type { HotelCardListingTypeEnum } from "./hotelCardListingProps"
export type HotelCardProps = {
hotelData: HotelResponse
isUserLoggedIn: boolean
type?: HotelCardListingTypeEnum
state?: "default" | "active"
bookingCode?: string | null
isAlternative?: boolean
}

View File

@@ -0,0 +1,11 @@
import type { ProductType } from "@scandic-hotels/trpc/types/availability"
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
export type HotelData = {
hotelData: Hotel
price: ProductType
}
export interface NullableHotelData extends Omit<HotelData, "hotelData"> {
hotelData: HotelData["hotelData"] | null
}

View File

@@ -1,15 +0,0 @@
export const enum SortOrder {
Distance = "distance",
Name = "name",
Price = "price",
TripAdvisorRating = "tripadvisor",
}
export type SortItem = {
label: string
value: string
}
export type HotelSorterProps = {
discreet?: boolean
}

View File

@@ -4,26 +4,6 @@ import type { Amenities } from "@scandic-hotels/trpc/types/hotel"
import type { z } from "zod"
import type { Coordinates } from "@/types/components/maps/coordinates"
import type { HotelResponse } from "@/components/HotelReservation/SelectHotel/helpers"
import type { CategorizedHotelFilters } from "./hotelFilters"
import type { SelectHotelBooking } from "./selectHotel"
export interface HotelListingProps {
hotels: HotelResponse[]
unfilteredHotelCount: number
}
export interface SelectHotelMapProps {
apiKey: string
hotelPins: HotelPin[]
mapId: string
hotels: HotelResponse[]
filterList: CategorizedHotelFilters
cityCoordinates: Coordinates
bookingCode: string | undefined
isBookingCodeRateAvailable?: boolean
isAlternativeHotels?: boolean
}
type ImageSizes = z.infer<typeof imageSchema>["imageSizes"]
type ImageMetaData = z.infer<typeof imageSchema>["metaData"]
@@ -56,13 +36,3 @@ export interface HotelCardDialogProps {
data: HotelPin
handleClose: (event: { stopPropagation: () => void }) => void
}
export interface HotelCardDialogListingProps {
hotels: HotelResponse[]
unfilteredHotelCount: number
}
export type SelectHotelMapContainerProps = {
booking: SelectHotelBooking
isAlternativeHotels?: boolean
}

View File

@@ -1,10 +0,0 @@
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
export type NoAvailabilityAlertProp = {
hotelsLength: number
bookingCode?: string
isAllUnavailable: boolean
isAlternative?: boolean
isBookingCodeRateNotAvailable?: boolean
operaId: Hotel["operaId"]
}

View File

@@ -1,5 +1,5 @@
import type { BookingSearchType } from "@scandic-hotels/booking-flow/searchType"
import type { RateEnum } from "@scandic-hotels/trpc/enums/rate"
import type { RateEnum } from "@scandic-hotels/common/constants/rate"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { PackageEnum, Packages } from "@scandic-hotels/trpc/types/packages"
import type {

View File

@@ -1,202 +0,0 @@
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { MembershipLevel } from "@scandic-hotels/common/constants/membershipLevels"
import type { RateEnum } from "@scandic-hotels/trpc/enums/rate"
import type { LoginType } from "@scandic-hotels/trpc/types/loginType"
export enum TrackingChannelEnum {
"scandic-friends" = "scandic-friends",
"static-content-page" = "static-content-page",
"hotelreservation" = "hotelreservation",
"collection-page" = "collection-page",
"campaign-page" = "campaign-page",
"campaign-overview-page" = "campaign-overview-page",
"hotels" = "hotels",
"homepage" = "homepage",
}
export type TrackingChannel = keyof typeof TrackingChannelEnum
export type TrackingSDKPageData = {
pageId: string
createDate?: string
publishDate?: string
domainLanguage: Lang
pageType: string
channel: TrackingChannel
siteVersion: "new-web"
pageName: string
domain?: string
siteSections: string
pageLoadTime?: number // Page load time in seconds
lcpTime?: number // Largest contentful paint time in seconds
sessionId?: string | null
}
export type TrackingSDKUserData =
| {
loginStatus: "logged in"
loginType?: LoginType
memberId?: string
membershipNumber?: string
memberLevel?: MembershipLevel
noOfNightsStayed?: number
totalPointsAvailableToSpend?: number
loginAction?: "login success"
}
| {
loginStatus: "Non-logged in"
}
| { loginStatus: "Error" }
export type TrackingSDKAncillaries = Ancillary[]
export type TrackingSDKHotelInfo = {
ageOfChildren?: string // "10", "2,5,10"
analyticsRateCode?: RateEnum | string
arrivalDate?: string
availableResults?: number // Number of hotels to choose from after a city search
bedType?: string
bedTypePosition?: number // Which position the bed type had in the list of available bed types
bnr?: string // Booking number
breakfastOption?: string // "no breakfast" or "breakfast buffet"
//bonuscheque?: boolean
bookingCode?: string
bookingCodeAvailability?: string
bookingTypeofDay?: "weekend" | "weekday"
childBedPreference?: string
country?: string // Country of the hotel
departureDate?: string
discount?: number | string
duration?: number // Number of nights to stay
hotelID?: string
leadTime?: number // Number of days from booking date until arrivalDate
lowestRoomPrice?: number
multiroomRateIdentity?: string
//modifyValues?: string // <price:<value>,roomtype:value>,bed:<value,<breakfast:value>
noOfAdults?: number | string // multiroom support, "2,1,3"
noOfChildren?: number | string // multiroom support, "2,1,3"
noOfRooms?: number
rateCode?: string
rateCodeCancellationRule?: string
rateCodeName?: string // Scandic Friends - full flex inkl. frukost
rateCodeType?: string // regular, promotion etc
region?: string // Region of the hotel
revenueCurrencyCode?: string // SEK, DKK, NOK, EUR
rewardNight?: string
rewardNightAvailability?: string
points?: number | string // Should be sent on confirmation page and enter-details page
roomPrice?: number | string
roomTypeCode?: string
roomTypeName?: string
roomTypePosition?: number // Which position the room had in the list of available rooms
searchTerm?: string
searchType?: "destination" | "hotel"
specialRoomType?: string // allergy room, pet-friendly, accesibillity room
totalPrice?: number | string
lateArrivalGuarantee?: string
guaranteedProduct?: string
emailId?: string // Encrypted hash value on booking confirmation page
mobileNumber?: string // Encrypted hash value on booking confirmation page
}
export type Ancillary = {
productId: string
productUnits?: number
hotelid?: string
productPoints: number
productPrice: number
productType: string
productName: string
productCategory: string
}
export type TrackingSDKPaymentInfo = {
edccCurrencyFrom?: string
edccCurrencyTo?: string
isedcc?: string
isSavedCard?: boolean
isCreditCard?: boolean
paymentStatus?: "confirmed" | "glacardsaveconfirmed"
paymentType?: string
type?: string
status?: string
}
export type TrackingSDKProps = {
pageData: TrackingSDKPageData
hotelInfo?: TrackingSDKHotelInfo
paymentInfo?: TrackingSDKPaymentInfo
ancillaries?: TrackingSDKAncillaries
}
export type TrackingSDKData = TrackingSDKPageData & {
pathName: string
}
type BasePaymentEvent = {
event: string
hotelId: string | undefined
method?: string | null
isSavedCreditCard?: boolean
smsEnable?: boolean
status: "attempt" | "cancelled" | "failed"
}
export type PaymentAttemptStartEvent = BasePaymentEvent
export type PaymentCancelEvent = BasePaymentEvent
export type PaymentFailEvent = BasePaymentEvent & {
errorMessage?: string
}
export type PaymentEvent =
| PaymentAttemptStartEvent
| PaymentCancelEvent
| PaymentFailEvent
export type LowestRoomPriceEvent = {
hotelId: string | null
arrivalDate: string | null
departureDate: string | null
lowestPrice: string
currency?: string
}
// Old tracking setup types:
// TODO: Remove this when we delete "current site"
export type TrackingProps = {
pageData: {
pageId: string
createdDate: string
publishedDate: string
englishUrl?: string
lang: Lang
}
}
export type TrackingData = {
lang: Lang
englishUrl?: string
pathName: string
queryString: string
pageId: string
publishedDate: string
createdDate: string
}
export type SiteSectionObject = {
sitesection1: string
sitesection2: string
sitesection3: string
sitesection4: string
sitesection5: string
sitesection6: string
}
export type TrackingPosition =
| "top menu"
| "hamburger menu"
| "join scandic friends sidebar"
| "enter details"
| "my stay"