Merged in feat/sw-2864-move-hotels-router-to-trpc-package (pull request #2410)

feat (SW-2864): Move booking router to trpc package

* Add env to trpc package

* Add eslint to trpc package

* Apply lint rules

* Use direct imports from trpc package

* Add lint-staged config to trpc

* Move lang enum to common

* Restructure trpc package folder structure

* WIP first step

* update internal imports in trpc

* Fix most errors in scandic-web

Just 100 left...

* Move Props type out of trpc

* Fix CategorizedFilters types

* Move more schemas in hotel router

* Fix deps

* fix getNonContentstackUrls

* Fix import error

* Fix entry error handling

* Fix generateMetadata metrics

* Fix alertType enum

* Fix duplicated types

* lint:fix

* Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package

* Fix broken imports

* Move booking router to trpc package

* Merge branch 'master' into feat/sw-2864-move-hotels-router-to-trpc-package


Approved-by: Linus Flood
This commit is contained in:
Anton Gunnarsson
2025-06-26 09:02:59 +00:00
parent 002d093af4
commit bbcabfa0ba
135 changed files with 1403 additions and 1387 deletions

View File

@@ -3,8 +3,8 @@
import { z } from "zod"
import * as api from "@scandic-hotels/trpc/api"
import { countriesMap } from "@scandic-hotels/trpc/constants/countries"
import { countriesMap } from "@/constants/countries"
import { ApiLang } from "@/constants/languages"
import { getProfile } from "@/lib/trpc/memoizedRequests"
import { protectedServerActionProcedure } from "@/server/trpc"

View File

@@ -1,11 +1,9 @@
import { notFound } from "next/navigation"
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
import {
BookingErrorCodeEnum,
PaymentCallbackStatusEnum,
} from "@/constants/booking"
import { PaymentCallbackStatusEnum } from "@/constants/booking"
import { serverClient } from "@/lib/trpc/server"
import GuaranteeCallback from "@/components/HotelReservation/MyStay/Ancillaries/GuaranteeCallback"

View File

@@ -1,11 +1,9 @@
import { notFound } from "next/navigation"
import { getServiceToken } from "@scandic-hotels/common/tokenManager"
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
import {
BookingErrorCodeEnum,
PaymentCallbackStatusEnum,
} from "@/constants/booking"
import { PaymentCallbackStatusEnum } from "@/constants/booking"
import {
bookingConfirmation,
details,

View File

@@ -1,6 +1,8 @@
import { notFound } from "next/navigation"
import { combineRegExps, rateTypeRegex, REDEMPTION } from "@/constants/booking"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { combineRegExps, rateTypeRegex } from "@/constants/booking"
import SelectRate from "@/components/HotelReservation/SelectRate"
import { parseSelectRateSearchParams } from "@/utils/url"

View File

@@ -1,10 +1,10 @@
import NextAuth, { type NextAuthConfig, type User } from "next-auth"
import { LoginTypeEnum } from "@scandic-hotels/trpc/types/loginType"
import { PRE_REFRESH_TIME_IN_SECONDS } from "@/constants/auth"
import { env } from "@/env/server"
import { LoginTypeEnum } from "./types/components/tracking"
import type { JWT } from "next-auth/jwt"
import type { OIDCConfig } from "next-auth/providers"

View File

@@ -1,10 +1,10 @@
import { Lang } from "@scandic-hotels/common/constants/language"
import { dt } from "@scandic-hotels/common/dt"
import { getFriendsMembership } from "@scandic-hotels/trpc/routers/user/helpers"
import Body from "@/components/TempDesignSystem/Text/Body"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import { getFriendsMembership } from "@/utils/user"
import type { UserProps } from "@/types/components/myPages/user"

View File

@@ -1,9 +1,9 @@
import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels"
import { getFriendsMembership } from "@scandic-hotels/trpc/routers/user/helpers"
import { serverClient } from "@/lib/trpc/server"
import { getIntl } from "@/i18n"
import { getFriendsMembership } from "@/utils/user"
import PointsContainer from "./Container"
import { PointsColumn } from "./PointsColumn"

View File

@@ -23,7 +23,7 @@ import { UnlinkSAS } from "./UnlinkSAS"
import styles from "./linkedAccounts.module.css"
import type { UserLoyalty } from "@/types/user"
import type { UserLoyalty } from "@scandic-hotels/trpc/types/user"
type Props = {
title?: string

View File

@@ -7,8 +7,8 @@ import { FormProvider, useForm } from "react-hook-form"
import { dt } from "@scandic-hotels/common/dt"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { REDEMPTION } from "@/constants/booking"
import { trpc } from "@/lib/trpc/client"
import { StickyElementNameEnum } from "@/stores/sticky-position"

View File

@@ -6,8 +6,7 @@ import { useMediaQuery } from "usehooks-ts"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { REDEMPTION } from "@/constants/booking"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import Modal from "@/components/Modal"
import Button from "@/components/TempDesignSystem/Button"

View File

@@ -7,8 +7,7 @@ import { useMediaQuery } from "usehooks-ts"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { REDEMPTION } from "@/constants/booking"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import Modal from "@/components/Modal"
import Button from "@/components/TempDesignSystem/Button"

View File

@@ -7,8 +7,8 @@ import { useIntl } from "react-intl"
import { dt } from "@scandic-hotels/common/dt"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { REDEMPTION } from "@/constants/booking"
import { hotelreservation } from "@/constants/routes/hotelReservation"
import DatePicker from "@/components/DatePicker"

View File

@@ -5,11 +5,12 @@ import { useTransition } from "react"
import { Form as FormRAC } from "react-aria-components"
import { useFormContext } from "react-hook-form"
import { REDEMPTION } from "@/constants/booking"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import {
selectHotel,
selectHotelMap,
selectRate,
} from "@/constants/routes/hotelReservation"
import useLang from "@/hooks/useLang"

View File

@@ -1,9 +1,8 @@
import { z } from "zod"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import { REDEMPTION } from "@/constants/booking"
export const bookingWidgetErrors = {
AGE_REQUIRED: "AGE_REQUIRED",
BED_CHOICE_REQUIRED: "BED_CHOICE_REQUIRED",

View File

@@ -6,8 +6,7 @@ import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { REDEMPTION } from "@/constants/booking"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import Button from "../TempDesignSystem/Button"
import { Tooltip } from "../TempDesignSystem/Tooltip"

View File

@@ -20,9 +20,9 @@ import MyPagesMenuContent, { useMyPagesNavigation } from "../MyPagesMenuContent"
import styles from "./myPagesMenu.module.css"
import type { LoyaltyLevel } from "@scandic-hotels/trpc/routers/contentstack/loyaltyLevel/output"
import type { FriendsMembership, User } from "@scandic-hotels/trpc/types/user"
import { DropdownTypeEnum } from "@/types/components/dropdown/dropdown"
import type { FriendsMembership, User } from "@/types/user"
export type MyPagesMenuProps = {
user: Pick<User, "firstName" | "lastName">

View File

@@ -6,8 +6,9 @@ import {
packageSchema,
} from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
import type { Package } from "@scandic-hotels/trpc/types/packages"
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
import type { Package } from "@/types/requests/packages"
import type { Room } from "@/types/stores/booking-confirmation"
export function mapToPrice(rooms: (Room | null)[], nights: number) {

View File

@@ -4,11 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { useCallback, useEffect, useState } from "react"
import { FormProvider, useForm } from "react-hook-form"
import {
BED_TYPE_ICONS,
type BedTypeEnum,
type ExtraBedTypeEnum,
} from "@/constants/booking"
import { BED_TYPE_ICONS } from "@/constants/booking"
import { useEnterDetailsStore } from "@/stores/enter-details"
import RadioCard from "@/components/TempDesignSystem/Form/RadioCard"
@@ -20,6 +16,10 @@ import { bedTypeFormSchema } from "./schema"
import styles from "./bedOptions.module.css"
import type { IconProps } from "@scandic-hotels/design-system/Icons"
import type {
BedTypeEnum,
ExtraBedTypeEnum,
} from "@scandic-hotels/trpc/enums/bedType"
import type { BedTypeFormSchema } from "@/types/components/hotelReservation/enterDetails/bedType"

View File

@@ -23,7 +23,7 @@ import PaymentOptionsGroup from "../../Payment/PaymentOptionsGroup"
import styles from "./guarantee.module.css"
import type { CreditCard } from "@/types/user"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
interface GuaranteeProps {
savedCreditCards: CreditCard[] | null

View File

@@ -11,7 +11,7 @@ import Guarantee from "./Guarantee"
import styles from "./confirm.module.css"
import type { CreditCard } from "@/types/user"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
interface ConfirmBookingProps {
savedCreditCards: CreditCard[] | null

View File

@@ -4,10 +4,10 @@ import { usePathname, useSearchParams } from "next/navigation"
import { useEffect, useRef, useState } from "react"
import { useIntl } from "react-intl"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
import { AlertTypeEnum } from "@scandic-hotels/trpc/types/alertType"
import { BookingErrorCodeEnum } from "@/constants/booking"
import { selectRate } from "@/constants/routes/hotelReservation"
import { useEnterDetailsStore } from "@/stores/enter-details"
import Alert from "@/components/TempDesignSystem/Alert"

View File

@@ -9,19 +9,15 @@ import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { Button } from "@scandic-hotels/design-system/Button"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { bedTypeMap } from "@scandic-hotels/trpc/constants/bedTypeMap"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import {
BookingStatusEnum,
PAYMENT_METHOD_TITLES,
REDEMPTION,
} from "@/constants/booking"
import {
bookingConfirmation,
selectRate,
} from "@/constants/routes/hotelReservation"
import { BookingStatusEnum, PAYMENT_METHOD_TITLES } from "@/constants/booking"
import { bookingConfirmation } from "@/constants/routes/hotelReservation"
import { env } from "@/env/client"
import { trpc } from "@/lib/trpc/client"
import { useEnterDetailsStore } from "@/stores/enter-details"
@@ -38,7 +34,6 @@ import { trackPaymentEvent } from "@/utils/tracking"
import { trackEvent } from "@/utils/tracking/base"
import { trackGlaSaveCardAttempt } from "@/utils/tracking/myStay"
import { bedTypeMap } from "../../utils"
import ConfirmBooking, { ConfirmBookingRedemption } from "../Confirm"
import PriceChangeDialog from "../PriceChangeDialog"
import { writeGlaToSessionStorage } from "./PaymentCallback/helpers"

View File

@@ -4,10 +4,10 @@ import { useRouter } from "next/navigation"
import { useTransition } from "react"
import { useIntl } from "react-intl"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { Button } from "@scandic-hotels/design-system/Button"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { selectRate } from "@/constants/routes/hotelReservation"
import { useEnterDetailsStore } from "@/stores/enter-details"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"

View File

@@ -9,9 +9,9 @@ import { getTracking } from "./tracking"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
import type { Room } from "@scandic-hotels/trpc/types/room"
import type { DetailsBooking } from "@/types/components/hotelReservation/enterDetails/details"
import type { Room } from "@/types/providers/details/room"
interface TrackingWrapperProps {
booking: DetailsBooking

View File

@@ -1,17 +1,17 @@
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import { PackageTypeEnum } from "@scandic-hotels/trpc/enums/packages"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import { REDEMPTION } from "@/constants/booking"
import { sumPackages } from "@/components/HotelReservation/utils"
import { getSpecialRoomType } from "@/utils/specialRoomType"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
import type { Room } from "@scandic-hotels/trpc/types/room"
import type {
PriceProduct,
Product,
@@ -28,7 +28,6 @@ import {
type TrackingSDKHotelInfo,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import type { Room } from "@/types/providers/details/room"
import type { RoomState } from "@/types/stores/enter-details"
export function getTracking(

View File

@@ -7,7 +7,7 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import styles from "./hotelChequeCard.module.css"
import type { ProductTypeCheque } from "@/types/trpc/routers/hotel/availability"
import type { ProductTypeCheque } from "@scandic-hotels/trpc/types/availability"
export default function HotelChequeCard({
productTypeCheque,

View File

@@ -7,7 +7,7 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import styles from "./hotelVoucherCard.module.css"
import type { ProductTypeVoucher } from "@/types/trpc/routers/hotel/availability"
import type { ProductTypeVoucher } from "@scandic-hotels/trpc/types/availability"
export default function HotelVoucherCard({
productTypeVoucher,

View File

@@ -10,11 +10,12 @@ import {
import { memo } from "react"
import { useIntl } from "react-intl"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { Divider } from "@scandic-hotels/design-system/Divider"
import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { selectHotelMap, selectRate } from "@/constants/routes/hotelReservation"
import { selectHotelMap } from "@/constants/routes/hotelReservation"
import { useHotelsMapStore } from "@/stores/hotels-map"
import BookingCodeChip from "@/components/BookingCodeChip"

View File

@@ -3,12 +3,11 @@ import { useSession } from "next-auth/react"
import { useState } from "react"
import { useIntl } from "react-intl"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { IconButton } from "@scandic-hotels/design-system/IconButton"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { selectRate } from "@/constants/routes/hotelReservation"
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link"

View File

@@ -3,12 +3,11 @@ import { useSession } from "next-auth/react"
import { useState } from "react"
import { useIntl } from "react-intl"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { IconButton } from "@scandic-hotels/design-system/IconButton"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { selectRate } from "@/constants/routes/hotelReservation"
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link"

View File

@@ -8,8 +8,7 @@ import PaymentOption from "../PaymentOption"
import styles from "./mySavedCards.module.css"
import type { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
import type { CreditCard } from "@/types/user"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
interface MySavedCardsProps {
savedCreditCards: CreditCard[] | null

View File

@@ -1,9 +1,10 @@
import type { User } from "@scandic-hotels/trpc/types/user"
import type {
Ancillaries,
Ancillary,
SelectedAncillary,
} from "@/types/components/myPages/myStay/ancillaries"
import type { User } from "@/types/user"
function filterPoints(ancillaries: Ancillaries, user: User | null) {
return ancillaries.map((ancillary) => {

View File

@@ -7,8 +7,9 @@ import BoldRow from "./Row/Bold"
import RegularRow from "./Row/Regular"
import Tbody from "./Tbody"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
interface BreakfastProps {
adults: number

View File

@@ -5,7 +5,7 @@ import { formatPrice } from "@/utils/numberFormatting"
import RegularRow from "../Regular"
import type { Packages as PackagesType } from "@/types/requests/packages"
import type { Packages as PackagesType } from "@scandic-hotels/trpc/types/packages"
interface PackagesProps {
packages: PackagesType | null

View File

@@ -1,5 +1,6 @@
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
import type { Packages } from "@/types/requests/packages"
export interface SharedPriceRowProps {
bedType: BedTypeSchema | undefined

View File

@@ -27,13 +27,13 @@ import Tbody from "./Tbody"
import styles from "./priceDetailsTable.module.css"
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { RateDefinition } from "@scandic-hotels/trpc/types/roomAvailability"
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
import type { Price } from "@/types/components/hotelReservation/price"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Packages } from "@/types/requests/packages"
type RoomPrice =
| CorporateChequePriceType

View File

@@ -1,17 +1,21 @@
import { AvailabilityEnum } from "@scandic-hotels/trpc/enums/selectHotel"
import { generateChildrenString } from "@scandic-hotels/trpc/routers/hotels/helpers"
import {
type AdditionalData,
type Hotel,
} from "@scandic-hotels/trpc/types/hotel"
import {
type HotelLocation,
type Location,
} from "@scandic-hotels/trpc/types/locations"
import { getHotel } from "@/lib/trpc/memoizedRequests"
import { serverClient } from "@/lib/trpc/server"
import { getLang } from "@/i18n/serverContext"
import { generateChildrenString } from "../utils"
import type { AdditionalData, Hotel } from "@scandic-hotels/trpc/types/hotel"
import type {
HotelLocation,
Location,
} from "@scandic-hotels/trpc/types/locations"
import type { HotelsAvailabilityItem } from "@scandic-hotels/trpc/types/availability"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type {
AlternativeHotelsAvailabilityInput,
@@ -21,8 +25,6 @@ import type {
CategorizedHotelFilters,
HotelFilter,
} from "@/types/components/hotelReservation/selectHotel/hotelFilters"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { HotelsAvailabilityItem } from "@/types/trpc/routers/hotel/availability"
interface AvailabilityResponse {
availability: HotelsAvailabilityItem[]

View File

@@ -4,7 +4,7 @@ import { usePathname, useSearchParams } from "next/navigation"
import { useEffect } from "react"
import { useIntl } from "react-intl"
import { BookingErrorCodeEnum } from "@/constants/booking"
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
import { toast } from "@/components/TempDesignSystem/Toasts"

View File

@@ -14,12 +14,13 @@ import { getMemberPrice, isBookingCodeRate } from "../utils"
import styles from "./room.module.css"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type {
RoomPrice,
RoomRate,
} from "@/types/components/hotelReservation/enterDetails/details"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Packages } from "@/types/requests/packages"
interface RoomProps {
room: {

View File

@@ -1,11 +1,12 @@
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { Price } from "@/types/components/hotelReservation/price"
import type {
Rate,
Room,
} from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Packages } from "@/types/requests/packages"
export function mapRate(
room: Rate,

View File

@@ -3,11 +3,11 @@ import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType"
import { sumPackages } from "@/components/HotelReservation/utils"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { RedemptionProduct } from "@scandic-hotels/trpc/types/roomAvailability"
import type { Price } from "@/types/components/hotelReservation/price"
import type { Rate } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Packages } from "@/types/requests/packages"
export function calculateTotalPrice(
selectedRateSummary: Rate[],

View File

@@ -1,6 +1,6 @@
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import type { PackageEnum } from "@/types/requests/packages"
import type { PackageEnum } from "@scandic-hotels/trpc/types/packages"
export function includesAllergyRoom(codes: PackageEnum[]) {
return codes.includes(RoomPackageCodeEnum.ALLERGY_ROOM)

View File

@@ -1,4 +1,4 @@
import type { PackageEnum } from "@/types/requests/packages"
import type { PackageEnum } from "@scandic-hotels/trpc/types/packages"
export type FormValues = {
selectedPackages: PackageEnum[]

View File

@@ -16,7 +16,8 @@ import Checkboxes from "./Checkboxes"
import styles from "./form.module.css"
import type { PackageEnum } from "@/types/requests/packages"
import type { PackageEnum } from "@scandic-hotels/trpc/types/packages"
import type { FormValues } from "./formValues"
export default function Form({ close }: { close: () => void }) {

View File

@@ -17,7 +17,7 @@ import { getIconNameByPackageCode } from "./utils"
import styles from "./roomPackageFilter.module.css"
import type { PackageEnum } from "@/types/requests/packages"
import type { PackageEnum } from "@scandic-hotels/trpc/types/packages"
export default function RoomPackageFilter() {
const lang = useLang()

View File

@@ -1,8 +1,7 @@
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import type { MaterialSymbolProps } from "@scandic-hotels/design-system/Icons/MaterialIcon/MaterialSymbol"
import type { PackageEnum } from "@/types/requests/packages"
import type { PackageEnum } from "@scandic-hotels/trpc/types/packages"
export function getIconNameByPackageCode(
packageCode: PackageEnum

View File

@@ -3,7 +3,7 @@
import { useSearchParams } from "next/navigation"
import React from "react"
import { REDEMPTION } from "@/constants/booking"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import TrackingSDK from "@/components/TrackingSDK"
import useLang from "@/hooks/useLang"

View File

@@ -1,6 +1,7 @@
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
export function convertToChildType(

View File

@@ -6,14 +6,10 @@ import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import { ChildBedTypeEnum } from "@scandic-hotels/trpc/enums/childBedTypeEnum"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { JSX } from "react"
import {
// RoomPackageCodeEnum,
type RoomPackageCodes,
} from "@/types/components/hotelReservation/selectRate/roomFilter"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Packages } from "@/types/requests/packages"
import { type RoomPackageCodes } from "@/types/components/hotelReservation/selectRate/roomFilter"
interface IconForFeatureCodeProps {
featureCode: RoomPackageCodes
@@ -33,13 +29,6 @@ export function IconForFeatureCode({
}
}
export const bedTypeMap: Record<number, ChildBedTypeEnum> = {
[ChildBedMapEnum.IN_ADULTS_BED]: ChildBedTypeEnum.ParentsBed,
[ChildBedMapEnum.IN_CRIB]: ChildBedTypeEnum.Crib,
[ChildBedMapEnum.IN_EXTRA_BED]: ChildBedTypeEnum.ExtraBed,
[ChildBedMapEnum.UNKNOWN]: ChildBedTypeEnum.Unknown,
}
export const invertedBedTypeMap: Record<ChildBedTypeEnum, string> = {
[ChildBedTypeEnum.ParentsBed]: ChildBedMapEnum[ChildBedMapEnum.IN_ADULTS_BED],
[ChildBedTypeEnum.Crib]: ChildBedMapEnum[ChildBedMapEnum.IN_CRIB],
@@ -47,16 +36,6 @@ export const invertedBedTypeMap: Record<ChildBedTypeEnum, string> = {
[ChildBedTypeEnum.Unknown]: ChildBedMapEnum[ChildBedMapEnum.UNKNOWN],
}
export function generateChildrenString(children: Child[]): string {
return `[${children
.map((child) => {
const age = child.age
const bedType = bedTypeMap[parseInt(child.bed.toString())]
return `${age}:${bedType}`
})
.join(",")}]`
}
export function sumPackages(packages: Packages | null) {
if (!packages || !packages.length) {
return {

View File

@@ -2,7 +2,7 @@ import { getInitials } from "@/utils/user"
import styles from "./avatar.module.css"
import type { User } from "@/types/user"
import type { User } from "@scandic-hotels/trpc/types/user"
export default function Avatar({
firstName,

View File

@@ -15,7 +15,7 @@ import DigitalTeamMemberCardContent from "./Content"
import styles from "./digitalTeamMemberCard.module.css"
import type { User } from "@/types/user"
import type { User } from "@scandic-hotels/trpc/types/user"
interface DigitalTeamMemberCardClientProps {
user: User

View File

@@ -9,7 +9,7 @@ import { debounce } from "@/utils/debounce"
import styles from "./digitalTeamMemberCard.module.css"
import type { User } from "@/types/user"
import type { User } from "@scandic-hotels/trpc/types/user"
interface DigitalTeamMemberCardCardProps {
user: User

View File

@@ -2,7 +2,7 @@ import { env } from "@/env/server"
import DigitalTeamMemberCardClient from "./Client"
import type { User } from "@/types/user"
import type { User } from "@scandic-hotels/trpc/types/user"
interface DigitalTeamMemberCardProps {
user: User

View File

@@ -3,8 +3,8 @@ import { isValidLang } from "@scandic-hotels/common/utils/languages"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { countriesMap } from "@scandic-hotels/trpc/constants/countries"
import { countriesMap } from "@/constants/countries"
import { languages } from "@/constants/languages"
import { profileEdit } from "@/constants/routes/myPages"
import { getProfile } from "@/lib/trpc/memoizedRequests"

View File

@@ -8,7 +8,7 @@ import CreditCardRow from "../CreditCardRow"
import styles from "./CreditCardList.module.css"
import type { CreditCard } from "@/types/user"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
export default function CreditCardList({
initialData,

View File

@@ -25,13 +25,13 @@ import RoomDetails from "./RoomDetails"
import styles from "./bookedRoomSidePeek.module.css"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { Room as HotelRoom } from "@scandic-hotels/trpc/types/hotel"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Packages } from "@/types/requests/packages"
import type { BookingConfirmationSchema } from "@/types/trpc/routers/booking/confirmation"
import type { SafeUser } from "@/types/user"

View File

@@ -16,8 +16,7 @@ import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { countries } from "@/constants/countries"
import { countries } from "@scandic-hotels/trpc/constants/countries"
import useLang from "@/hooks/useLang"

View File

@@ -5,8 +5,7 @@ import { useController } from "react-hook-form"
import { useIntl } from "react-intl"
import { Select } from "@scandic-hotels/design-system/Select"
import { countries } from "@/constants/countries"
import { countries } from "@scandic-hotels/trpc/constants/countries"
import useLang from "@/hooks/useLang"

View File

@@ -7,9 +7,14 @@ import BedSingleIcon from "@scandic-hotels/design-system/Icons/BedSingleIcon"
import BedSofaExtraIcon from "@scandic-hotels/design-system/Icons/BedSofaExtraIcon"
import BedTwinIcon from "@scandic-hotels/design-system/Icons/BedTwinIcon"
import BedWallExtraIcon from "@scandic-hotels/design-system/Icons/BedWallExtraIcon"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import type { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
import type { IconProps } from "@scandic-hotels/design-system/Icons"
import type {
BedTypeEnum,
ExtraBedTypeEnum,
} from "@scandic-hotels/trpc/enums/bedType"
import type { JSX } from "react"
export enum BookingStatusEnum {
@@ -31,25 +36,11 @@ export enum BookingStatusEnum {
export const FamilyAndFriendsCodes = ["D000029555", "D000029271", "D000029195"]
export const REDEMPTION = "redemption"
export const bookingSearchTypes = [REDEMPTION] as const
export const SEARCHTYPE = "searchtype"
export const MEMBERSHIP_FAILED_ERROR = "MembershipFailedError"
export enum BookingErrorCodeEnum {
InternalError = "InternalError",
ReservationError = "ReservationError",
AvailabilityError = "AvailabilityError",
BookingStatusNotFound = "BookingStatusNotFound",
TransactionAbandoned = "TransactionAbandoned",
TransactionCancelled = "TransactionCancelled",
TransactionFailed = "TransactionFailed",
BookingStateError = "BookingStateError",
MembershipFailedError = "MembershipFailedError",
NoAvailabilityForRateAndRoomType = "NoAvailabilityForRateAndRoomType",
}
export const PAYMENT_METHOD_TITLES: Record<
keyof typeof PaymentMethodEnum,
string
@@ -100,21 +91,6 @@ export const PAYMENT_METHOD_ICONS: Record<
discover: "/_static/icons/payment/discover.svg",
}
export enum BedTypeEnum {
King = "King",
Queen = "Queen",
Single = "Single",
Twin = "Twin",
Other = "Other",
}
export enum ExtraBedTypeEnum {
SofaBed = "SofaBed",
WallBed = "WallBed",
PullOutBed = "PullOutBed",
BunkBed = "BunkBed",
}
export type BedTypes = keyof typeof BedTypeEnum | keyof typeof ExtraBedTypeEnum
export const BED_TYPE_ICONS: Record<

View File

@@ -1,6 +1,6 @@
import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels"
import type { EurobonusTier } from "@/types/user"
import type { EurobonusTier } from "@scandic-hotels/trpc/types/user"
export const FriendsMembershipLevels = [
"L1",

View File

@@ -37,13 +37,6 @@ export function selectHotelMap(lang) {
return `${hotelreservation(lang)}/select-hotel/map`
}
/**
* @param {Lang} lang
*/
export function selectRate(lang) {
return `${hotelreservation(lang)}/select-rate`
}
/**
* @param {Lang} lang
* @param {string} hotelId

View File

@@ -1,2 +1,4 @@
import "@scandic-hotels/common/global.d.ts"
import "@scandic-hotels/trpc/types.d.ts"
import "@scandic-hotels/trpc/auth.d.ts"
import "@scandic-hotels/trpc/jwt.d.ts"

View File

@@ -4,7 +4,7 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { useCallback, useEffect } from "react"
import { useIntl } from "react-intl"
import { BookingErrorCodeEnum } from "@/constants/booking"
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
import { toast } from "@/components/TempDesignSystem/Toasts"

View File

@@ -9,18 +9,18 @@ import { serverClient } from "../server"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { GetHotelsByCSFilterInput } from "@scandic-hotels/trpc/routers/hotels/input"
import type { RoomsAvailabilityExtendedInputSchema } from "@scandic-hotels/trpc/types/availability"
import type { Country } from "@scandic-hotels/trpc/types/country"
import type {
CityCoordinatesInput,
HotelInput,
} from "@scandic-hotels/trpc/types/hotel"
import type {
AncillaryPackagesInput,
BreackfastPackagesInput,
PackagesInput,
} from "@/types/requests/packages"
import type { RoomsAvailabilityExtendedInputSchema } from "@/types/trpc/routers/hotel/availability"
} from "@scandic-hotels/trpc/types/packages"
import type { GetSavedPaymentCardsInput } from "@/server/routers/user/input"
export const getLocations = cache(async function getMemoizedLocations() {

View File

@@ -1,11 +1,13 @@
import { type NextMiddleware, NextResponse } from "next/server"
import { REDEMPTION, SEARCHTYPE } from "@/constants/booking"
import { findLang } from "@scandic-hotels/common/utils/languages"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { SEARCHTYPE } from "@/constants/booking"
import { login } from "@/constants/routes/handleAuth"
import { getPublicNextURL } from "@/server/utils"
import { auth } from "@/auth"
import { findLang } from "@scandic-hotels/common/utils/languages"
import { isValidSession } from "@/utils/session"
import { getDefaultRequestHeaders } from "./utils"

View File

@@ -3,6 +3,8 @@ import { notFound } from "next/navigation"
import { use, useRef } from "react"
import { useIntl } from "react-intl"
import { type RoomCategories } from "@scandic-hotels/trpc/types/hotel"
import { trpc } from "@/lib/trpc/client"
import { createMyStayStore } from "@/stores/my-stay"
@@ -10,15 +12,14 @@ import { MyStaySkeleton } from "@/components/HotelReservation/MyStay/myStaySkele
import { MyStayContext } from "@/contexts/MyStay"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
import type { Packages } from "@/types/components/myPages/myStay/ancillaries"
import type { MyStayStore } from "@/types/contexts/my-stay"
import type { RoomCategories } from "@scandic-hotels/trpc/types/hotel"
import type {
BookingConfirmation,
BookingConfirmationSchema,
} from "@/types/trpc/routers/booking/confirmation"
import type { CreditCard } from "@/types/user"
interface MyStayProviderProps {
bookingConfirmation: BookingConfirmation

View File

@@ -1,10 +1,10 @@
/** Routers */
import { router } from "@scandic-hotels/trpc"
import { contentstackRouter } from "@scandic-hotels/trpc/routers/contentstack"
import { hotelsRouter } from "@scandic-hotels/trpc/routers/hotels"
import { autocompleteRouter } from "./routers/autocomplete"
import { bookingRouter } from "./routers/booking"
import { hotelsRouter } from "./routers/hotels"
import { navigationRouter } from "./routers/navigation"
import { partnerRouter } from "./routers/partners"
import { userRouter } from "./routers/user"

View File

@@ -1,751 +0,0 @@
import stringify from "json-stable-stringify-without-jsonify"
import { getCacheClient } from "@scandic-hotels/common/dataCache"
import { createCounter } from "@scandic-hotels/common/telemetry"
import * as api from "@scandic-hotels/trpc/api"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import { AvailabilityEnum } from "@scandic-hotels/trpc/enums/selectHotel"
import { badRequestError } from "@scandic-hotels/trpc/errors"
import { type RoomFeaturesInput } from "@scandic-hotels/trpc/routers/hotels/input"
import {
hotelsAvailabilitySchema,
packagesSchema,
roomFeaturesSchema,
roomsAvailabilitySchema,
} from "@scandic-hotels/trpc/routers/hotels/output"
import { toApiLang } from "@scandic-hotels/trpc/utils"
import { sortRoomConfigs } from "@scandic-hotels/trpc/utils/sortRoomConfigs"
import { BookingErrorCodeEnum, REDEMPTION } from "@/constants/booking"
import { selectRate } from "@/constants/routes/hotelReservation"
import { env } from "@/env/server"
import { generateChildrenString } from "@/components/HotelReservation/utils"
import type { Room as RoomCategory } from "@scandic-hotels/trpc/types/hotel"
import type {
Product,
Products,
RateDefinition,
RedemptionsProduct,
RoomConfiguration,
} from "@scandic-hotels/trpc/types/roomAvailability"
import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
import type { PackagesOutput } from "@/types/requests/packages"
import type {
HotelsAvailabilityInputSchema,
HotelsByHotelIdsAvailabilityInputSchema,
RoomsAvailabilityExtendedInputSchema,
RoomsAvailabilityInputRoom,
RoomsAvailabilityOutputSchema,
} from "@/types/trpc/routers/hotel/availability"
export const TWENTYFOUR_HOURS = 60 * 60 * 24
function findProduct(product: Products, rateDefinition: RateDefinition) {
if ("corporateCheque" in product) {
return product.corporateCheque.rateCode === rateDefinition.rateCode
}
if (("member" in product && product.member) || "public" in product) {
let isMemberRate = false
if (product.member) {
isMemberRate = product.member.rateCode === rateDefinition.rateCode
}
let isPublicRate = false
if (product.public) {
isPublicRate = product.public.rateCode === rateDefinition.rateCode
}
return isMemberRate || isPublicRate
}
if ("voucher" in product) {
return product.voucher.rateCode === rateDefinition.rateCode
}
if (Array.isArray(product)) {
return product.find(
(r) => r.redemption.rateCode === rateDefinition.rateCode
)
}
}
export async function getHotelsAvailabilityByCity(
input: HotelsAvailabilityInputSchema,
apiLang: string,
token: string, // Either service token or user access token in case of redemption search
userPoints: number = 0
) {
const {
cityId,
roomStayStartDate,
roomStayEndDate,
adults,
children,
bookingCode,
redemption,
} = input
const params: Record<string, string | number> = {
roomStayStartDate,
roomStayEndDate,
adults,
...(children && { children }),
...(bookingCode && { bookingCode }),
...(redemption ? { isRedemption: "true" } : {}),
language: apiLang,
}
const getHotelsAvailabilityByCityCounter = createCounter(
"hotel",
"getHotelsAvailabilityByCity"
)
const metricsGetHotelsAvailabilityByCity =
getHotelsAvailabilityByCityCounter.init({
apiLang,
cityId,
roomStayStartDate,
roomStayEndDate,
adults,
children,
bookingCode,
redemption,
})
metricsGetHotelsAvailabilityByCity.start()
const apiResponse = await api.get(
api.endpoints.v1.Availability.city(cityId),
{
headers: {
Authorization: `Bearer ${token}`,
},
},
params
)
if (!apiResponse.ok) {
await metricsGetHotelsAvailabilityByCity.httpError(apiResponse)
throw new Error("Failed to fetch hotels availability by city")
}
const apiJson = await apiResponse.json()
const validateAvailabilityData = hotelsAvailabilitySchema.safeParse(apiJson)
if (!validateAvailabilityData.success) {
metricsGetHotelsAvailabilityByCity.validationError(
validateAvailabilityData.error
)
throw badRequestError()
}
if (redemption) {
validateAvailabilityData.data.data.forEach((data) => {
data.attributes.productType?.redemptions?.forEach((r) => {
r.hasEnoughPoints = userPoints >= r.localPrice.pointsPerStay
})
})
}
const result = {
availability: validateAvailabilityData.data.data.flatMap(
(hotels) => hotels.attributes
),
}
metricsGetHotelsAvailabilityByCity.success()
return result
}
export async function getHotelsAvailabilityByHotelIds(
input: HotelsByHotelIdsAvailabilityInputSchema,
apiLang: string,
serviceToken: string
) {
const {
hotelIds,
roomStayStartDate,
roomStayEndDate,
adults,
children,
bookingCode,
} = input
const params = new URLSearchParams([
["roomStayStartDate", roomStayStartDate],
["roomStayEndDate", roomStayEndDate],
["adults", adults.toString()],
["children", children ?? ""],
["bookingCode", bookingCode],
["language", apiLang],
])
const getHotelsAvailabilityByHotelIdsCounter = createCounter(
"hotel",
"getHotelsAvailabilityByHotelIds"
)
const metricsGetHotelsAvailabilityByHotelIds =
getHotelsAvailabilityByHotelIdsCounter.init({
apiLang,
hotelIds,
roomStayStartDate,
roomStayEndDate,
adults,
children,
bookingCode,
})
metricsGetHotelsAvailabilityByHotelIds.start()
const cacheClient = await getCacheClient()
const result = cacheClient.cacheOrGet(
`${apiLang}:hotels:availability:${hotelIds.join(",")}:${roomStayStartDate}:${roomStayEndDate}:${adults}:${children}:${bookingCode}`,
async () => {
/**
* Since API expects the params appended and not just
* a comma separated string we need to initialize the
* SearchParams with a sequence of pairs
* (hotelIds=810&hotelIds=879&hotelIds=222 etc.)
**/
hotelIds.forEach((hotelId) =>
params.append("hotelIds", hotelId.toString())
)
const apiResponse = await api.get(
api.endpoints.v1.Availability.hotels(),
{
headers: {
Authorization: `Bearer ${serviceToken}`,
},
},
params
)
if (!apiResponse.ok) {
await metricsGetHotelsAvailabilityByHotelIds.httpError(apiResponse)
throw new Error("Failed to fetch hotels availability by hotelIds")
}
const apiJson = await apiResponse.json()
const validateAvailabilityData =
hotelsAvailabilitySchema.safeParse(apiJson)
if (!validateAvailabilityData.success) {
metricsGetHotelsAvailabilityByHotelIds.validationError(
validateAvailabilityData.error
)
throw badRequestError()
}
return {
availability: validateAvailabilityData.data.data.flatMap(
(hotels) => hotels.attributes
),
}
},
env.CACHE_TIME_CITY_SEARCH
)
metricsGetHotelsAvailabilityByHotelIds.success()
return result
}
async function getRoomFeaturesInventory(
input: RoomFeaturesInput,
token: string
) {
const {
adults,
childrenInRoom,
endDate,
hotelId,
roomFeatureCodes,
startDate,
} = input
const params = {
adults,
hotelId,
roomFeatureCode: roomFeatureCodes,
roomStayEndDate: endDate,
roomStayStartDate: startDate,
...(childrenInRoom?.length && {
children: generateChildrenString(childrenInRoom),
}),
}
const getRoomFeaturesInventoryCounter = createCounter(
"hotel",
"getRoomFeaturesInventory"
)
const metricsGetRoomFeaturesInventory =
getRoomFeaturesInventoryCounter.init(params)
metricsGetRoomFeaturesInventory.start()
const cacheClient = await getCacheClient()
const result = cacheClient.cacheOrGet(
stringify(input),
async function () {
const apiResponse = await api.get(
api.endpoints.v1.Availability.roomFeatures(hotelId),
{
headers: {
Authorization: `Bearer ${token}`,
},
},
params
)
if (!apiResponse.ok) {
await metricsGetRoomFeaturesInventory.httpError(apiResponse)
return null
}
const data = await apiResponse.json()
const validatedRoomFeaturesData = roomFeaturesSchema.safeParse(data)
if (!validatedRoomFeaturesData.success) {
metricsGetRoomFeaturesInventory.validationError(
validatedRoomFeaturesData.error
)
return null
}
return validatedRoomFeaturesData.data
},
"5m"
)
metricsGetRoomFeaturesInventory.success()
return result
}
export async function getPackages(input: PackagesOutput, serviceToken: string) {
const { adults, children, endDate, hotelId, lang, packageCodes, startDate } =
input
const getPackagesCounter = createCounter("hotel", "getPackages")
const metricsGetPackages = getPackagesCounter.init({
input,
})
metricsGetPackages.start()
const cacheClient = await getCacheClient()
const result = cacheClient.cacheOrGet(
stringify(input),
async function () {
const apiLang = toApiLang(lang)
const searchParams = new URLSearchParams({
adults: adults.toString(),
children: children.toString(),
endDate,
language: apiLang,
startDate,
})
packageCodes.forEach((code) => {
searchParams.append("packageCodes", code)
})
const apiResponse = await api.get(
api.endpoints.v1.Package.Packages.hotel(hotelId),
{
headers: {
Authorization: `Bearer ${serviceToken}`,
},
},
searchParams
)
if (!apiResponse.ok) {
await metricsGetPackages.httpError(apiResponse)
return null
}
const apiJson = await apiResponse.json()
const validatedPackagesData = packagesSchema.safeParse(apiJson)
if (!validatedPackagesData.success) {
metricsGetPackages.validationError(validatedPackagesData.error)
return null
}
return validatedPackagesData.data
},
"3h"
)
metricsGetPackages.success()
return result
}
export async function getRoomsAvailability(
input: RoomsAvailabilityOutputSchema,
token: string,
serviceToken: string,
userPoints: number | undefined
) {
const {
booking: { bookingCode, fromDate, hotelId, rooms, searchType, toDate },
lang,
} = input
const redemption = searchType === REDEMPTION
const getRoomsAvailabilityCounter = createCounter(
"hotel",
"getRoomsAvailability"
)
const metricsGetRoomsAvailability = getRoomsAvailabilityCounter.init({
input,
redemption,
})
metricsGetRoomsAvailability.start()
const apiLang = toApiLang(lang)
const baseCacheKey = {
bookingCode,
fromDate,
hotelId,
lang,
searchType,
toDate,
}
const cacheClient = await getCacheClient()
const availabilityResponses = await Promise.allSettled(
rooms.map((room: RoomsAvailabilityInputRoom) => {
const cacheKey = {
...baseCacheKey,
room,
}
const result = cacheClient.cacheOrGet(
stringify(cacheKey),
async function () {
{
const params = {
adults: room.adults,
language: apiLang,
roomStayStartDate: fromDate,
roomStayEndDate: toDate,
...(room.childrenInRoom?.length && {
children: generateChildrenString(room.childrenInRoom),
}),
...(room.bookingCode && { bookingCode: room.bookingCode }),
...(redemption && { isRedemption: "true" }),
}
const apiResponse = await api.get(
api.endpoints.v1.Availability.hotel(hotelId),
{
cache: undefined, // overwrite default
headers: {
Authorization: `Bearer ${token}`,
},
},
params
)
if (!apiResponse.ok) {
await metricsGetRoomsAvailability.httpError(apiResponse)
const text = await apiResponse.text()
return { error: "http_error", details: text }
}
const apiJson = await apiResponse.json()
const validateAvailabilityData =
roomsAvailabilitySchema.safeParse(apiJson)
if (!validateAvailabilityData.success) {
metricsGetRoomsAvailability.validationError(
validateAvailabilityData.error
)
return {
error: "validation_error",
details: validateAvailabilityData.error,
}
}
if (redemption) {
for (const roomConfig of validateAvailabilityData.data
.roomConfigurations) {
for (const product of roomConfig.redemptions) {
if (userPoints) {
product.redemption.hasEnoughPoints =
userPoints >= product.redemption.localPrice.pointsPerStay
}
}
}
}
const roomFeatures = await getPackages(
{
adults: room.adults,
children: room.childrenInRoom?.length || 0,
endDate: input.booking.toDate,
hotelId: input.booking.hotelId,
lang,
packageCodes: [
RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
RoomPackageCodeEnum.ALLERGY_ROOM,
RoomPackageCodeEnum.PET_ROOM,
],
startDate: input.booking.fromDate,
},
serviceToken
)
if (roomFeatures) {
validateAvailabilityData.data.packages = roomFeatures
}
// Fetch packages
if (room.packages?.length) {
const roomFeaturesInventory = await getRoomFeaturesInventory(
{
adults: room.adults,
childrenInRoom: room.childrenInRoom,
endDate: input.booking.toDate,
hotelId: input.booking.hotelId,
lang,
roomFeatureCodes: room.packages,
startDate: input.booking.fromDate,
},
serviceToken
)
if (roomFeaturesInventory) {
const features = roomFeaturesInventory.reduce<
Record<string, number>
>((fts, feat) => {
fts[feat.roomTypeCode] = feat.features?.[0]?.inventory ?? 0
return fts
}, {})
const updatedRoomConfigurations =
validateAvailabilityData.data.roomConfigurations
// This filter is needed since we can get availability
// back from roomFeatures yet the availability call
// says there are no rooms left...
.filter((rc) => rc.roomsLeft)
.filter((rc) => features?.[rc.roomTypeCode])
.map((rc) => ({
...rc,
roomsLeft: features[rc.roomTypeCode],
status: AvailabilityEnum.Available,
}))
validateAvailabilityData.data.roomConfigurations =
updatedRoomConfigurations
}
}
return validateAvailabilityData.data
}
},
"1m"
)
return result
})
)
const data = availabilityResponses.map((availability) => {
if (availability.status === "fulfilled") {
return availability.value
}
return {
details: availability.reason,
error: "request_failure",
}
})
metricsGetRoomsAvailability.success()
return data
}
export function getSelectedRoomAvailability(
rateCode: string,
rateDefinitions: RateDefinition[],
roomConfigurations: RoomConfiguration[],
roomTypeCode: string,
userPoints: number | undefined
) {
const rateDefinition = rateDefinitions.find((rd) => rd.rateCode === rateCode)
if (!rateDefinition) {
return null
}
const selectedRoom = roomConfigurations.find(
(room) =>
room.roomTypeCode === roomTypeCode &&
room.products.find((product) => findProduct(product, rateDefinition))
)
if (!selectedRoom) {
return null
}
let product: Product | RedemptionsProduct | undefined =
selectedRoom.products.find((product) =>
findProduct(product, rateDefinition)
)
if (!product) {
return null
}
if (Array.isArray(product)) {
const redemptionProduct = userPoints
? product.find(
(r) =>
r.redemption.rateCode === rateDefinition.rateCode &&
r.redemption.localPrice.pointsPerStay <= userPoints
)
: undefined
if (!redemptionProduct) {
return null
}
product = redemptionProduct
}
return {
rateDefinition,
rateDefinitions,
rooms: roomConfigurations,
product,
selectedRoom,
}
}
export function getBedTypes(
rooms: RoomConfiguration[],
roomType: string,
roomCategories?: RoomCategory[]
) {
if (!roomCategories) {
return []
}
return rooms
.filter(
(room) => room.status === AvailabilityEnum.Available || room.roomsLeft > 0
)
.filter((room) => room.roomType === roomType)
.map((availRoom) => {
const matchingRoom = roomCategories
?.find((room) =>
room.roomTypes
.map((roomType) => roomType.code)
.includes(availRoom.roomTypeCode)
)
?.roomTypes.find((roomType) => roomType.code === availRoom.roomTypeCode)
if (matchingRoom) {
return {
description: matchingRoom.description,
size: matchingRoom.mainBed.widthRange,
value: matchingRoom.code,
type: matchingRoom.mainBed.type,
roomsLeft: availRoom.roomsLeft,
extraBed: matchingRoom.fixedExtraBed
? {
type: matchingRoom.fixedExtraBed.type,
description: matchingRoom.fixedExtraBed.description,
}
: undefined,
}
}
})
.filter((bed): bed is BedTypeSelection => Boolean(bed))
}
export function mergeRoomTypes(roomConfigurations: RoomConfiguration[]) {
// Initial sort to guarantee if one bed is NotAvailable and whereas
// the other is Available to make sure data is added to the correct
// roomConfig
roomConfigurations.sort(sortRoomConfigs)
const roomConfigs = new Map<string, RoomConfiguration>()
for (const roomConfig of roomConfigurations) {
if (roomConfigs.has(roomConfig.roomType)) {
const currentRoomConf = roomConfigs.get(roomConfig.roomType)
if (currentRoomConf) {
currentRoomConf.features = roomConfig.features.reduce(
(feats, feature) => {
const currentFeatureIndex = feats.findIndex(
(f) => f.code === feature.code
)
if (currentFeatureIndex !== -1) {
feats[currentFeatureIndex].inventory =
feats[currentFeatureIndex].inventory + feature.inventory
} else {
feats.push(feature)
}
return feats
},
currentRoomConf.features
)
currentRoomConf.roomsLeft =
currentRoomConf.roomsLeft + roomConfig.roomsLeft
roomConfigs.set(currentRoomConf.roomType, currentRoomConf)
}
} else {
roomConfigs.set(roomConfig.roomType, roomConfig)
}
}
return Array.from(roomConfigs.values())
}
export function selectRateRedirectURL(
input: RoomsAvailabilityExtendedInputSchema,
selectedRooms: boolean[]
) {
const searchParams = new URLSearchParams({
errorCode: BookingErrorCodeEnum.AvailabilityError,
fromdate: input.booking.fromDate,
hotel: input.booking.hotelId,
todate: input.booking.toDate,
})
if (input.booking.searchType) {
searchParams.set("searchtype", input.booking.searchType)
}
for (const [idx, room] of input.booking.rooms.entries()) {
searchParams.set(`room[${idx}].adults`, room.adults.toString())
if (selectedRooms[idx]) {
if (room.counterRateCode) {
searchParams.set(`room[${idx}].counterratecode`, room.counterRateCode)
}
searchParams.set(`room[${idx}].ratecode`, room.rateCode)
searchParams.set(`room[${idx}].roomtype`, room.roomTypeCode)
} else {
if (!searchParams.has("modifyRateIndex")) {
searchParams.set("modifyRateIndex", idx.toString())
}
}
if (room.bookingCode) {
searchParams.set(`room[${idx}].bookingCode`, room.bookingCode)
}
if (room.packages) {
searchParams.set(`room[${idx}].packages`, room.packages.join(","))
}
if (room.childrenInRoom?.length) {
for (const [i, kid] of room.childrenInRoom.entries()) {
searchParams.set(`room[${idx}].child[${i}].age`, kid.age.toString())
searchParams.set(`room[${idx}].child[${i}].bed`, kid.bed.toString())
}
}
}
return `${selectRate(input.lang)}?${searchParams.toString()}`
}

View File

@@ -9,8 +9,8 @@ import { getIntl } from "@/i18n"
import { getEurobonusMembership } from "@/utils/user"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { UserLoyalty } from "@scandic-hotels/trpc/types/user"
import type { UserLoyalty } from "@/types/user"
import type { MyPagesLink } from "./MyPagesLink"
export const getPrimaryLinks = cache(

View File

@@ -3,8 +3,7 @@ import { z } from "zod"
import { Lang } from "@scandic-hotels/common/constants/language"
import { safeProtectedProcedure } from "@scandic-hotels/trpc/procedures"
import { getVerifiedUser } from "@/server/routers/user/utils"
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils"
import { isValidSession } from "@/utils/session"

View File

@@ -4,13 +4,12 @@ import { z } from "zod"
import * as api from "@scandic-hotels/trpc/api"
import { protectedProcedure } from "@scandic-hotels/trpc/procedures"
import { getUserSchema } from "@scandic-hotels/trpc/routers/user/output"
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils"
import { FriendsMembershipLevels } from "@/constants/membershipLevels"
import { getUserSchema } from "../../user/output"
import { getVerifiedUser } from "../../user/utils"
import type { FriendsTier } from "@/types/user"
import type { FriendsTier } from "@scandic-hotels/trpc/types/user"
const matchedSchema = z.object({
tierMatchState: z.enum(["matched"]),

View File

@@ -2,122 +2,6 @@ import { z } from "zod"
import { imageSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/image"
import { countriesMap } from "@/constants/countries"
import { getFriendsMembership } from "@/utils/user"
const scandicFriendsTier = z.enum(["L1", "L2", "L3", "L4", "L5", "L6", "L7"])
const sasEurobonusTier = z.enum(["EBB", "EBS", "EBG", "EBD", "EBP"])
const commonMembershipSchema = z.object({
membershipNumber: z.string(),
tierExpires: z.string().nullish().default(null),
memberSince: z.string().nullish(),
})
// This prevents validation errors if the API returns an unhandled membership type
const otherMembershipSchema = z
.object({
// This ensures that `type` won't widen into "string", losing the literal types, when used in a union
type: z.string().refine((val): val is string & {} => true),
})
.merge(commonMembershipSchema)
export const sasMembershipSchema = z
.object({
type: z.literal("SAS_EB"),
tier: sasEurobonusTier,
nextTier: sasEurobonusTier.nullish(),
spendablePoints: z.number().nullish(),
boostedByScandic: z.boolean().nullish(),
boostedTier: sasEurobonusTier.nullish(),
boostedTierExpires: z.string().nullish().default(null),
})
.merge(commonMembershipSchema)
.transform((response) => {
return {
...response,
tierExpires:
// SAS API returns 1900-01-01 for non-expiring tiers
response.tierExpires === "1900-01-01" ? null : response.tierExpires,
}
})
export const friendsMembershipSchema = z
.object({
type: z.literal("SCANDIC_NATIVE"),
tier: scandicFriendsTier,
nextTier: scandicFriendsTier.nullish(),
pointsToNextTier: z.number().nullish(),
nightsToTopTier: z.number().nullish(),
})
.merge(commonMembershipSchema)
export const membershipSchema = z.union([
friendsMembershipSchema,
sasMembershipSchema,
otherMembershipSchema,
])
const pointExpirationSchema = z.object({
points: z.number().int(),
expires: z.string(),
})
export const userLoyaltySchema = z.object({
memberships: z.array(membershipSchema),
points: z.object({
spendable: z.number().int(),
earned: z.number().int(),
spent: z.number().int(),
}),
tier: scandicFriendsTier,
tierExpires: z.string(),
tierBoostedBy: z.string().nullish(),
pointExpirations: z.array(pointExpirationSchema),
})
export const getUserSchema = z
.object({
data: z.object({
attributes: z.object({
dateOfBirth: z.string().optional().default("1900-01-01"),
email: z.string().email(),
firstName: z.string(),
language: z
.string()
// Preserve Profile v1 formatting for now so it matches ApiLang enum
.transform((s) => s.charAt(0).toUpperCase() + s.slice(1))
.optional(),
lastName: z.string(),
phoneNumber: z.string().optional(),
profileId: z.string(),
membershipNumber: z.string(),
address: z
.object({
city: z.string().optional(),
country: z.string().optional(),
countryCode: z.nativeEnum(countriesMap).optional(),
streetAddress: z.string().optional(),
zipCode: z.string().optional(),
})
.optional()
.nullable(),
loyalty: userLoyaltySchema.optional(),
}),
type: z.string(),
}),
})
.transform((apiResponse) => {
return {
...apiResponse.data.attributes,
membership: apiResponse.data.attributes.loyalty
? getFriendsMembership(apiResponse.data.attributes.loyalty)
: null,
name: `${apiResponse.data.attributes.firstName} ${apiResponse.data.attributes.lastName}`,
}
})
// Schema is the same for upcoming and previous stays endpoints
export const getStaysSchema = z.object({
data: z.array(
@@ -234,35 +118,6 @@ type GetFriendTransactionsData = z.infer<typeof getFriendTransactionsSchema>
export type FriendTransaction = GetFriendTransactionsData["data"][number]
export const creditCardSchema = z
.object({
attribute: z.object({
cardName: z.string().optional(),
alias: z.string(),
truncatedNumber: z.string().transform((s) => s.slice(-4)),
expirationDate: z.string(),
cardType: z
.string()
.transform((s) => s.charAt(0).toLowerCase() + s.slice(1)),
}),
id: z.string(),
type: z.string(),
})
.transform((apiResponse) => {
return {
id: apiResponse.id,
type: apiResponse.attribute.cardType,
truncatedNumber: apiResponse.attribute.truncatedNumber,
alias: apiResponse.attribute.alias,
expirationDate: apiResponse.attribute.expirationDate,
cardType: apiResponse.attribute.cardType,
}
})
export const creditCardsSchema = z.object({
data: z.array(creditCardSchema),
})
export const initiateSaveCardSchema = z.object({
data: z.object({
attribute: z.object({

View File

@@ -6,10 +6,12 @@ import {
protectedProcedure,
safeProtectedProcedure,
} from "@scandic-hotels/trpc/procedures"
import { getFriendsMembership } from "@scandic-hotels/trpc/routers/user/helpers"
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils"
import { toApiLang } from "@scandic-hotels/trpc/utils"
import { isValidSession } from "@/utils/session"
import { getFriendsMembership, getMembershipCards } from "@/utils/user"
import { getMembershipCards } from "@/utils/user"
import {
friendTransactionsInput,
@@ -22,13 +24,14 @@ import {
getCreditCards,
getPreviousStays,
getUpcomingStays,
getVerifiedUser,
parsedUser,
updateStaysBookingUrl,
} from "./utils"
import type { LoginType } from "@scandic-hotels/trpc/types/loginType"
import type {
LoginType,
// LoginType,
TrackingSDKUserData,
} from "@/types/components/tracking"
import { Transactions } from "@/types/enums/transactions"

View File

@@ -2,9 +2,12 @@ import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
import { dt } from "@scandic-hotels/common/dt"
import { createCounter } from "@scandic-hotels/common/telemetry"
import * as api from "@scandic-hotels/trpc/api"
import { countries } from "@scandic-hotels/trpc/constants/countries"
import { getFriendsMembership } from "@scandic-hotels/trpc/routers/user/helpers"
import { creditCardsSchema } from "@scandic-hotels/trpc/routers/user/output"
import { getVerifiedUser } from "@scandic-hotels/trpc/routers/user/utils"
import { toApiLang } from "@scandic-hotels/trpc/utils"
import { countries } from "@/constants/countries"
import { myBookingPath } from "@/constants/myBooking"
import { env } from "@/env/server"
@@ -13,93 +16,13 @@ import { encrypt } from "@/utils/encryption"
import * as maskValue from "@/utils/maskValue"
import { isValidSession } from "@/utils/session"
import { getCurrentWebUrl } from "@/utils/url"
import { getFriendsMembership } from "@/utils/user"
import {
creditCardsSchema,
type FriendTransaction,
getStaysSchema,
getUserSchema,
type Stay,
} from "./output"
import { type FriendTransaction, getStaysSchema, type Stay } from "./output"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { User } from "@scandic-hotels/trpc/types/user"
import type { Session } from "next-auth"
import type { User } from "@/types/user"
export const getVerifiedUser = cache(
async ({
session,
includeExtendedPartnerData,
}: {
session: Session
includeExtendedPartnerData?: boolean
}) => {
const getVerifiedUserCounter = createCounter("user", "getVerifiedUser")
const metricsGetVerifiedUser = getVerifiedUserCounter.init()
metricsGetVerifiedUser.start()
const now = Date.now()
if (session.token.expires_at && session.token.expires_at < now) {
metricsGetVerifiedUser.dataError(`Token expired`)
return { error: true, cause: "token_expired" } as const
}
const apiResponse = await api.get(
api.endpoints.v2.Profile.profile,
{
headers: {
Authorization: `Bearer ${session.token.access_token}`,
},
},
includeExtendedPartnerData
? { includes: "extendedPartnerInformation" }
: {}
)
if (!apiResponse.ok) {
await metricsGetVerifiedUser.httpError(apiResponse)
if (apiResponse.status === 401) {
return { error: true, cause: "unauthorized" } as const
} else if (apiResponse.status === 403) {
return { error: true, cause: "forbidden" } as const
} else if (apiResponse.status === 404) {
return { error: true, cause: "notfound" } as const
}
return {
error: true,
cause: "unknown",
status: apiResponse.status,
} as const
}
const apiJson = await apiResponse.json()
if (!apiJson.data?.attributes) {
metricsGetVerifiedUser.dataError(
`Missing data attributes in API response`,
{
data: apiJson,
}
)
return null
}
const verifiedData = getUserSchema.safeParse(apiJson)
if (!verifiedData.success) {
metricsGetVerifiedUser.validationError(verifiedData.error)
return null
}
metricsGetVerifiedUser.success()
return verifiedData
}
)
export async function getMembershipNumber(
session: Session | null
): Promise<string | undefined> {

View File

@@ -11,6 +11,7 @@ import {
import { detailsStorageName } from "."
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type {
CorporateChequeProduct,
PriceProduct,
@@ -22,7 +23,6 @@ import type { BreakfastPackage } from "@/types/components/hotelReservation/break
import { type RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
import type { Price } from "@/types/components/hotelReservation/price"
import type { SelectRateBooking } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Packages } from "@/types/requests/packages"
import type { PersistedState, RoomState } from "@/types/stores/enter-details"
import type { SafeUser } from "@/types/user"

View File

@@ -2,11 +2,10 @@ import { produce } from "immer"
import { useContext } from "react"
import { create, useStore } from "zustand"
import { REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import { AvailabilityEnum } from "@scandic-hotels/trpc/enums/selectHotel"
import { REDEMPTION } from "@/constants/booking"
import { RatesContext } from "@/contexts/Rates"
import { serializeBookingSearchParams } from "@/utils/url"
@@ -16,10 +15,10 @@ import {
findSelectedRate,
} from "./helpers"
import type { Package, Packages } from "@scandic-hotels/trpc/types/packages"
import type { PriceProduct } from "@scandic-hotels/trpc/types/roomAvailability"
import { BookingCodeFilterEnum } from "@/types/enums/bookingCodeFilter"
import type { Package, Packages } from "@/types/requests/packages"
import type { InitialState, RatesState } from "@/types/stores/rates"
export function createRatesStore({

View File

@@ -1,4 +1,4 @@
import type { Child } from "../hotelReservation/selectRate/selectRate"
import type { Child } from "@scandic-hotels/trpc/types/child"
export type ChildBed = {
label: string

View File

@@ -1,10 +1,10 @@
import type { Image } from "@scandic-hotels/trpc/types/image"
import type { User } from "@scandic-hotels/trpc/types/user"
import type {
CurrentHeaderLink,
TopMenuHeaderLink,
} from "@/types/requests/currentHeader"
import type { User } from "@/types/user"
export type MainMenuProps = {
frontpageLinkText: string

View File

@@ -1,7 +1,6 @@
import type { meetingRoomsSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/meetingRoom"
import type { z } from "zod"
import type { meetingRoomsSchema } from "@/server/routers/hotels/schemas/meetingRoom"
export type MeetingRoomData = z.output<typeof meetingRoomsSchema>
export type MeetingRooms = MeetingRoomData["data"]
export type MeetingRoom = MeetingRooms[number]["attributes"]

View File

@@ -4,24 +4,6 @@ import type {
bedTypeFormSchema,
bedTypeSchema,
} from "@/components/HotelReservation/EnterDetails/BedType/schema"
import type { BedTypeEnum, ExtraBedTypeEnum } from "@/constants/booking"
export type BedTypeSelection = {
description: string
size: {
min: number
max: number
}
value: string
type: BedTypeEnum
roomsLeft: number
extraBed:
| {
description: string
type: ExtraBedTypeEnum
}
| undefined
}
export interface BedTypeFormSchema extends z.output<typeof bedTypeFormSchema> {}

View File

@@ -1,17 +1,17 @@
import type { productTypePointsSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/productTypePrice"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { PackageEnum } from "@scandic-hotels/trpc/types/packages"
import type { Product } from "@scandic-hotels/trpc/types/roomAvailability"
import type { z } from "zod"
import type { PackageEnum } from "@/types/requests/packages"
import type { Product } from "@scandic-hotels/trpc/types/roomAvailability"
import type { SafeUser } from "@/types/user"
import type { getMultiroomDetailsSchema } from "@/components/HotelReservation/EnterDetails/Details/Multiroom/schema"
import type {
guestDetailsSchema,
signedInDetailsSchema,
} from "@/components/HotelReservation/EnterDetails/Details/RoomOne/schema"
import type { productTypePointsSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/productTypePrice"
import type { BookingSearchType } from "../booking"
import type { Price } from "../price"
import type { Child } from "../selectRate/selectRate"
export type DetailsSchema = z.output<typeof guestDetailsSchema>
export type MultiroomDetailsSchema = z.output<

View File

@@ -1,6 +1,5 @@
import type { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
import type { CreditCard } from "@/types/user"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
export interface PaymentProps {
otherPaymentOptions: PaymentMethodEnum[]

View File

@@ -1,5 +1,6 @@
import type { ProductType } from "@scandic-hotels/trpc/types/availability"
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
import type { ProductType } from "@/types/trpc/routers/hotel/availability"
import type { HotelResponse } from "@/components/HotelReservation/SelectHotel/helpers"
export enum HotelCardListingTypeEnum {

View File

@@ -1,9 +1,9 @@
import type { imageSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/image"
import type { ProductTypeCheque } from "@scandic-hotels/trpc/types/availability"
import type { Amenities } from "@scandic-hotels/trpc/types/hotel"
import type { z } from "zod"
import type { Coordinates } from "@/types/components/maps/coordinates"
import type { ProductTypeCheque } from "@/types/trpc/routers/hotel/availability"
import type { HotelResponse } from "@/components/HotelReservation/SelectHotel/helpers"
import type { CategorizedHotelFilters } from "./hotelFilters"
import type { SelectHotelBooking } from "./selectHotel"

View File

@@ -2,7 +2,7 @@ import type {
ProductTypeCheque,
ProductTypePrices,
ProductTypeVoucher,
} from "@/types/trpc/routers/hotel/availability"
} from "@scandic-hotels/trpc/types/availability"
export type PriceCardProps = {
productTypePrices: ProductTypePrices

View File

@@ -1,6 +1,7 @@
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
import type { BookingSearchType } from "../booking"
import type { Child } from "../selectRate/selectRate"
import type { SidePeekEnum } from "../sidePeek"
export interface ReadMoreProps {

View File

@@ -1,4 +1,4 @@
import type { Package } from "@/types/requests/packages"
import type { Package } from "@scandic-hotels/trpc/types/packages"
import type { RoomConfiguration } from "@scandic-hotels/trpc/types/roomAvailability"
export type RoomListItemProps = {

View File

@@ -1,18 +1,13 @@
import type { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import type { RateEnum } from "@scandic-hotels/trpc/enums/rate"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { PackageEnum, Packages } from "@scandic-hotels/trpc/types/packages"
import type {
Product,
RoomConfiguration,
} from "@scandic-hotels/trpc/types/roomAvailability"
import type { PackageEnum, Packages } from "@/types/requests/packages"
import type { BookingSearchType } from "../booking"
export interface Child {
bed: ChildBedMapEnum
age: number
}
export interface Room {
adults: number
childrenInRoom?: Child[]

View File

@@ -1,5 +1,7 @@
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import type { Packages } from "@/types/requests/packages"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { RoomState } from "@/types/stores/enter-details"
import type {
DetailsBooking,
@@ -7,7 +9,7 @@ import type {
RoomRate,
} from "./enterDetails/details"
import type { Price } from "./price"
import type { Child, SelectRateBooking } from "./selectRate/selectRate"
import type { SelectRateBooking } from "./selectRate/selectRate"
export type RoomsData = {
rateDetails: string[] | undefined

View File

@@ -1,4 +1,4 @@
import type { User } from "@/types/user"
import type { User } from "@scandic-hotels/trpc/types/user"
export interface FriendProps
extends React.PropsWithChildren<Pick<User, "membership" | "name">> {}

View File

@@ -1,6 +1,6 @@
import type { User } from "@scandic-hotels/trpc/types/user"
import type { VariantProps } from "class-variance-authority"
import type { User } from "@/types/user"
import type { membershipNumberVariants } from "@/components/Blocks/DynamicContent/Overview/Friend/MembershipNumber/membershipNumberVariants"
export interface MembershipNumberProps

View File

@@ -1,4 +1,4 @@
import type { CreditCard } from "@/types/user"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
export type CreditCardRowProps = {
card: CreditCard

View File

@@ -1,4 +1,4 @@
import type { User } from "@/types/user"
import type { User } from "@scandic-hotels/trpc/types/user"
export type EditFormProps = {
user: User

View File

@@ -1,11 +1,11 @@
import type { z } from "zod"
import type { Room } from "@/types/stores/my-stay"
import type { CreditCard, User } from "@/types/user"
import type {
ancillaryPackagesSchema,
packagesSchema,
} from "@scandic-hotels/trpc/routers/hotels/output"
import type { CreditCard, User } from "@scandic-hotels/trpc/types/user"
import type { z } from "zod"
import type { Room } from "@/types/stores/my-stay"
export type Ancillaries = z.output<typeof ancillaryPackagesSchema>
export type Ancillary = Ancillaries[number]

View File

@@ -1,4 +1,5 @@
import type { User } from "@/types/user"
import type { User } from "@scandic-hotels/trpc/types/user"
import type { userQueryRouter } from "@/server/routers/user/query"
export type UserQueryRouter = typeof userQueryRouter

View File

@@ -1,6 +1,7 @@
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",
@@ -31,14 +32,6 @@ export type TrackingSDKPageData = {
sessionId?: string | null
}
export enum LoginTypeEnum {
email = "email",
"membership number" = "membership number",
"email link" = "email link",
"dtmc" = "dtmc",
}
export type LoginType = keyof typeof LoginTypeEnum
export type TrackingSDKUserData =
| {
loginStatus: "logged in"

View File

@@ -1,4 +1,5 @@
import type { Package } from "@/types/requests/packages"
import type { Package } from "@scandic-hotels/trpc/types/packages"
import type { RatesState, SelectedRoom } from "@/types/stores/rates"
export interface RoomContextValue extends Omit<SelectedRoom, "actions"> {

View File

@@ -1,29 +1,4 @@
import type { RateEnum } from "@scandic-hotels/trpc/enums/rate"
import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
import type { RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
import type { Package } from "@/types/requests/packages"
export interface Room {
bedTypes: BedTypeSelection[]
breakfastIncluded: boolean
cancellationRule: string
cancellationText: string
mustBeGuaranteed: boolean
memberMustBeGuaranteed: boolean | undefined
packages: Package[]
rate: RateEnum
rateDefinitionTitle: string
rateDetails: string[]
memberRateDetails: string[] | undefined
rateTitle: string | undefined
rateType: string
roomRate: RoomRate
roomType: string
roomTypeCode: string
isAvailable: boolean
isFlexRate: boolean
}
import type { Room } from "@scandic-hotels/trpc/types/room"
export interface RoomProviderProps extends React.PropsWithChildren {
idx: number

View File

@@ -1,4 +1,5 @@
import type { Room } from "@/types/providers/details/room"
import type { Room } from "@scandic-hotels/trpc/types/room"
import type { SafeUser } from "@/types/user"
import type { Lang } from "@/constants/routes/hotelReservation"
import type { BreakfastPackages } from "../components/hotelReservation/breakfast"

View File

@@ -1,11 +1,13 @@
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import type { BedTypeSelection } from "@scandic-hotels/trpc/types/bedTypeSelection"
import type { Child } from "@scandic-hotels/trpc/types/child"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type {
BreakfastPackage,
BreakfastPackages,
} from "@/types/components/hotelReservation/breakfast"
import type {
BedTypeSchema,
BedTypeSelection,
} from "@/types/components/hotelReservation/enterDetails/bedType"
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
import type {
DetailsBooking,
DetailsSchema,
@@ -14,11 +16,8 @@ import type {
RoomRate,
SignedInDetailsSchema,
} from "@/types/components/hotelReservation/enterDetails/details"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { StepEnum } from "@/types/enums/step"
import type { Price } from "../components/hotelReservation/price"
import type { CurrencyEnum } from "../../../../packages/common/constants/currency"
import type { Packages } from "../requests/packages"
export interface InitialRoomData {
// used when there is only one bedtype to preselect it

Some files were not shown because too many files have changed in this diff Show More