Merged in feat/SW-1078-rate-terms-scenarios (pull request #1500)
feat(SW-1078): mixed rate scenario * feat(SW-1078): mixed rate scenario * fix: change from css string modification to array join * refactor: split out big reduce function into smaller parts * fix: minor fixes and improvments * fix: added room index map to localization string Approved-by: Christian Andolf
This commit is contained in:
@@ -93,6 +93,7 @@ export default async function DetailsPage({
|
|||||||
rooms.push({
|
rooms.push({
|
||||||
bedTypes: roomAvailability.bedTypes,
|
bedTypes: roomAvailability.bedTypes,
|
||||||
breakfastIncluded: roomAvailability.breakfastIncluded,
|
breakfastIncluded: roomAvailability.breakfastIncluded,
|
||||||
|
cancellationRule: roomAvailability.cancellationRule,
|
||||||
cancellationText: roomAvailability.cancellationText,
|
cancellationText: roomAvailability.cancellationText,
|
||||||
mustBeGuaranteed: roomAvailability.mustBeGuaranteed,
|
mustBeGuaranteed: roomAvailability.mustBeGuaranteed,
|
||||||
packages,
|
packages,
|
||||||
@@ -196,7 +197,6 @@ export default async function DetailsPage({
|
|||||||
hotel.merchantInformationData.alternatePaymentOptions
|
hotel.merchantInformationData.alternatePaymentOptions
|
||||||
}
|
}
|
||||||
supportedCards={hotel.merchantInformationData.cards}
|
supportedCards={hotel.merchantInformationData.cards}
|
||||||
mustBeGuaranteed={isCardOnlyPayment}
|
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
|
import { formatPrice } from "@/utils/numberFormatting"
|
||||||
|
|
||||||
|
import {
|
||||||
|
calculateTotalRoomPrice,
|
||||||
|
hasFlexibleRate,
|
||||||
|
hasPrepaidRate,
|
||||||
|
} from "../helpers"
|
||||||
|
|
||||||
|
import styles from "./mixedRatePaymentBreakdown.module.css"
|
||||||
|
|
||||||
|
import type { RoomState } from "@/types/stores/enter-details"
|
||||||
|
|
||||||
|
type PaymentBreakdownState = {
|
||||||
|
roomsWithPrepaidRate: number[]
|
||||||
|
roomsWithFlexRate: number[]
|
||||||
|
payNowPrice: number
|
||||||
|
payNowComparisonPrice: number
|
||||||
|
payAtCheckInPrice: number
|
||||||
|
payAtCheckInComparisonPrice: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MixedRatePaymentBreakdownProps {
|
||||||
|
rooms: RoomState[]
|
||||||
|
currency: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MixedRatePaymentBreakdown({
|
||||||
|
rooms,
|
||||||
|
currency,
|
||||||
|
}: MixedRatePaymentBreakdownProps) {
|
||||||
|
const intl = useIntl()
|
||||||
|
const payNowTitle = intl.formatMessage({ id: "Pay now" })
|
||||||
|
const payAtCheckInTitle = intl.formatMessage({ id: "Pay at check-in" })
|
||||||
|
|
||||||
|
const initialState: PaymentBreakdownState = {
|
||||||
|
roomsWithPrepaidRate: [],
|
||||||
|
roomsWithFlexRate: [],
|
||||||
|
payNowPrice: 0,
|
||||||
|
payNowComparisonPrice: 0,
|
||||||
|
payAtCheckInPrice: 0,
|
||||||
|
payAtCheckInComparisonPrice: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
roomsWithPrepaidRate,
|
||||||
|
roomsWithFlexRate,
|
||||||
|
payNowPrice,
|
||||||
|
payNowComparisonPrice,
|
||||||
|
payAtCheckInPrice,
|
||||||
|
payAtCheckInComparisonPrice,
|
||||||
|
} = rooms.reduce((acc, room, idx) => {
|
||||||
|
if (hasPrepaidRate(room)) {
|
||||||
|
acc.roomsWithPrepaidRate.push(idx)
|
||||||
|
const { totalPrice, comparisonPrice } = calculateTotalRoomPrice(room)
|
||||||
|
acc.payNowPrice += totalPrice
|
||||||
|
acc.payNowComparisonPrice += comparisonPrice
|
||||||
|
}
|
||||||
|
if (hasFlexibleRate(room)) {
|
||||||
|
acc.roomsWithFlexRate.push(idx)
|
||||||
|
const { totalPrice, comparisonPrice } = calculateTotalRoomPrice(room)
|
||||||
|
acc.payAtCheckInPrice += totalPrice
|
||||||
|
acc.payAtCheckInComparisonPrice += comparisonPrice
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, initialState)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<PaymentCard
|
||||||
|
title={payNowTitle}
|
||||||
|
price={payNowPrice}
|
||||||
|
comparisonPrice={payNowComparisonPrice}
|
||||||
|
currency={currency}
|
||||||
|
roomIndexes={roomsWithPrepaidRate}
|
||||||
|
/>
|
||||||
|
<PaymentCard
|
||||||
|
title={payAtCheckInTitle}
|
||||||
|
price={payAtCheckInPrice}
|
||||||
|
comparisonPrice={payAtCheckInComparisonPrice}
|
||||||
|
currency={currency}
|
||||||
|
roomIndexes={roomsWithFlexRate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PaymentCardProps {
|
||||||
|
title: string
|
||||||
|
price: number
|
||||||
|
comparisonPrice: number
|
||||||
|
currency: string
|
||||||
|
roomIndexes: number[]
|
||||||
|
}
|
||||||
|
|
||||||
|
function PaymentCard({
|
||||||
|
title,
|
||||||
|
price,
|
||||||
|
comparisonPrice,
|
||||||
|
currency,
|
||||||
|
roomIndexes,
|
||||||
|
}: PaymentCardProps) {
|
||||||
|
const intl = useIntl()
|
||||||
|
const isMemberRateApplied = price < comparisonPrice
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.card}>
|
||||||
|
<Caption
|
||||||
|
type="bold"
|
||||||
|
textTransform="uppercase"
|
||||||
|
className={styles.cardTitle}
|
||||||
|
>
|
||||||
|
{title}{" "}
|
||||||
|
<span>
|
||||||
|
/{" "}
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "Room {roomIndex}" },
|
||||||
|
{
|
||||||
|
roomIndex: roomIndexes.map((idx) => idx + 1).join(" & "),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</Caption>
|
||||||
|
<Body textTransform="bold" className={styles.priceItem}>
|
||||||
|
{formatPrice(intl, price, currency)}
|
||||||
|
{isMemberRateApplied && comparisonPrice ? (
|
||||||
|
<span>{formatPrice(intl, comparisonPrice, currency)}</span>
|
||||||
|
) : null}
|
||||||
|
</Body>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--Spacing-x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
background-color: var(--Scandic-Blue-00);
|
||||||
|
padding: var(--Spacing-x-one-and-half);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: var(--Corner-radius-Medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardTitle {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardTitle > span {
|
||||||
|
color: var(--UI-Text-Placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.inactive {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.priceItem {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--Spacing-x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.priceItem > span {
|
||||||
|
font-weight: 400;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
@@ -38,6 +38,8 @@ import { trackPaymentEvent } from "@/utils/tracking"
|
|||||||
import { bedTypeMap } from "../../utils"
|
import { bedTypeMap } from "../../utils"
|
||||||
import PriceChangeDialog from "../PriceChangeDialog"
|
import PriceChangeDialog from "../PriceChangeDialog"
|
||||||
import GuaranteeDetails from "./GuaranteeDetails"
|
import GuaranteeDetails from "./GuaranteeDetails"
|
||||||
|
import { hasFlexibleRate, hasPrepaidRate, isPaymentMethodEnum } from "./helpers"
|
||||||
|
import MixedRatePaymentBreakdown from "./MixedRatePaymentBreakdown"
|
||||||
import PaymentOption from "./PaymentOption"
|
import PaymentOption from "./PaymentOption"
|
||||||
import { type PaymentFormData, paymentSchema } from "./schema"
|
import { type PaymentFormData, paymentSchema } from "./schema"
|
||||||
|
|
||||||
@@ -51,14 +53,9 @@ const retryInterval = 2000
|
|||||||
|
|
||||||
export const formId = "submit-booking"
|
export const formId = "submit-booking"
|
||||||
|
|
||||||
function isPaymentMethodEnum(value: string): value is PaymentMethodEnum {
|
|
||||||
return Object.values(PaymentMethodEnum).includes(value as PaymentMethodEnum)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PaymentClient({
|
export default function PaymentClient({
|
||||||
otherPaymentOptions,
|
otherPaymentOptions,
|
||||||
savedCreditCards,
|
savedCreditCards,
|
||||||
mustBeGuaranteed,
|
|
||||||
}: PaymentClientProps) {
|
}: PaymentClientProps) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const lang = useLang()
|
const lang = useLang()
|
||||||
@@ -90,6 +87,11 @@ export default function PaymentClient({
|
|||||||
|
|
||||||
const { toDate, fromDate, hotelId } = booking
|
const { toDate, fromDate, hotelId } = booking
|
||||||
|
|
||||||
|
const mustBeGuaranteed = rooms.every((r) => r.room.mustBeGuaranteed)
|
||||||
|
const hasPrepaidRates = rooms.some(hasPrepaidRate)
|
||||||
|
const hasFlexRates = rooms.some(hasFlexibleRate)
|
||||||
|
const hasMixedRates = hasPrepaidRates && hasFlexRates
|
||||||
|
|
||||||
usePaymentFailedToast()
|
usePaymentFailedToast()
|
||||||
|
|
||||||
const methods = useForm<PaymentFormData>({
|
const methods = useForm<PaymentFormData>({
|
||||||
@@ -351,6 +353,15 @@ export default function PaymentClient({
|
|||||||
<GuaranteeDetails />
|
<GuaranteeDetails />
|
||||||
</section>
|
</section>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{hasMixedRates ? (
|
||||||
|
<Body>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: "As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.",
|
||||||
|
})}
|
||||||
|
</Body>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{savedCreditCards?.length ? (
|
{savedCreditCards?.length ? (
|
||||||
<section className={styles.section}>
|
<section className={styles.section}>
|
||||||
<Body color="uiTextHighContrast" textTransform="bold">
|
<Body color="uiTextHighContrast" textTransform="bold">
|
||||||
@@ -374,6 +385,7 @@ export default function PaymentClient({
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<section className={styles.section}>
|
<section className={styles.section}>
|
||||||
{savedCreditCards?.length ? (
|
{savedCreditCards?.length ? (
|
||||||
<Body color="uiTextHighContrast" textTransform="bold">
|
<Body color="uiTextHighContrast" textTransform="bold">
|
||||||
@@ -399,7 +411,14 @@ export default function PaymentClient({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
{hasMixedRates ? (
|
||||||
|
<MixedRatePaymentBreakdown
|
||||||
|
rooms={rooms}
|
||||||
|
currency={totalPrice.local.currency}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className={styles.section}>
|
<section className={styles.section}>
|
||||||
<Caption>
|
<Caption>
|
||||||
{intl.formatMessage(
|
{intl.formatMessage(
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { CancellationRuleEnum, PaymentMethodEnum } from "@/constants/booking"
|
||||||
|
|
||||||
|
import type { RoomState } from "@/types/stores/enter-details"
|
||||||
|
|
||||||
|
export function isPaymentMethodEnum(value: string): value is PaymentMethodEnum {
|
||||||
|
return Object.values<string>(PaymentMethodEnum).includes(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasFlexibleRate({ room }: RoomState): boolean {
|
||||||
|
return room.cancellationRule === CancellationRuleEnum.CancellableBefore6PM
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasPrepaidRate({ room }: RoomState): boolean {
|
||||||
|
return room.cancellationRule !== CancellationRuleEnum.CancellableBefore6PM
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateTotalRoomPrice({ room }: RoomState) {
|
||||||
|
let totalPrice = room.roomPrice.perStay.local.price
|
||||||
|
|
||||||
|
if (room.breakfast) {
|
||||||
|
totalPrice += Number(room.breakfast.localPrice.totalPrice) * room.adults
|
||||||
|
}
|
||||||
|
|
||||||
|
if (room.roomFeatures) {
|
||||||
|
room.roomFeatures.forEach((pkg) => {
|
||||||
|
totalPrice += Number(pkg.localPrice.price)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let comparisonPrice = totalPrice
|
||||||
|
|
||||||
|
const isMember = room.guest.join || room.guest.membershipNo
|
||||||
|
if (isMember) {
|
||||||
|
const publicPrice = room.roomRate.publicRate?.localPrice.pricePerStay ?? 0
|
||||||
|
const memberPrice = room.roomRate.memberRate?.localPrice.pricePerStay ?? 0
|
||||||
|
const diff = publicPrice - memberPrice
|
||||||
|
comparisonPrice = totalPrice + diff
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
totalPrice,
|
||||||
|
comparisonPrice,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import type { PaymentProps } from "@/types/components/hotelReservation/enterDeta
|
|||||||
|
|
||||||
export default async function Payment({
|
export default async function Payment({
|
||||||
otherPaymentOptions,
|
otherPaymentOptions,
|
||||||
mustBeGuaranteed,
|
|
||||||
supportedCards,
|
supportedCards,
|
||||||
}: PaymentProps) {
|
}: PaymentProps) {
|
||||||
const savedCreditCards = await getSavedPaymentCardsSafely({
|
const savedCreditCards = await getSavedPaymentCardsSafely({
|
||||||
@@ -17,7 +16,6 @@ export default async function Payment({
|
|||||||
<PaymentClient
|
<PaymentClient
|
||||||
otherPaymentOptions={otherPaymentOptions}
|
otherPaymentOptions={otherPaymentOptions}
|
||||||
savedCreditCards={savedCreditCards}
|
savedCreditCards={savedCreditCards}
|
||||||
mustBeGuaranteed={mustBeGuaranteed}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ const rooms: RoomState[] = [
|
|||||||
bedTypes: [],
|
bedTypes: [],
|
||||||
breakfast: breakfastPackage,
|
breakfast: breakfastPackage,
|
||||||
breakfastIncluded: false,
|
breakfastIncluded: false,
|
||||||
|
cancellationRule: "",
|
||||||
cancellationText: "Non-refundable",
|
cancellationText: "Non-refundable",
|
||||||
childrenInRoom: [{ bed: ChildBedMapEnum.IN_EXTRA_BED, age: 5 }],
|
childrenInRoom: [{ bed: ChildBedMapEnum.IN_EXTRA_BED, age: 5 }],
|
||||||
guest: guestDetailsNonMember,
|
guest: guestDetailsNonMember,
|
||||||
@@ -64,6 +65,7 @@ const rooms: RoomState[] = [
|
|||||||
roomType: "Standard",
|
roomType: "Standard",
|
||||||
roomTypeCode: "QS",
|
roomTypeCode: "QS",
|
||||||
isAvailable: true,
|
isAvailable: true,
|
||||||
|
mustBeGuaranteed: false,
|
||||||
},
|
},
|
||||||
steps: {
|
steps: {
|
||||||
[StepEnum.selectBed]: {
|
[StepEnum.selectBed]: {
|
||||||
@@ -92,6 +94,7 @@ const rooms: RoomState[] = [
|
|||||||
bedTypes: [],
|
bedTypes: [],
|
||||||
breakfast: undefined,
|
breakfast: undefined,
|
||||||
breakfastIncluded: false,
|
breakfastIncluded: false,
|
||||||
|
cancellationRule: "",
|
||||||
cancellationText: "Non-refundable",
|
cancellationText: "Non-refundable",
|
||||||
childrenInRoom: [],
|
childrenInRoom: [],
|
||||||
guest: guestDetailsMember,
|
guest: guestDetailsMember,
|
||||||
@@ -102,6 +105,7 @@ const rooms: RoomState[] = [
|
|||||||
roomType: "Standard",
|
roomType: "Standard",
|
||||||
roomTypeCode: "QS",
|
roomTypeCode: "QS",
|
||||||
isAvailable: true,
|
isAvailable: true,
|
||||||
|
mustBeGuaranteed: false,
|
||||||
},
|
},
|
||||||
steps: {
|
steps: {
|
||||||
[StepEnum.selectBed]: {
|
[StepEnum.selectBed]: {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
"As our {level}": "Som vores {level}",
|
"As our {level}": "Som vores {level}",
|
||||||
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Da dette er et ophold med flere værelser, skal annullereringen gennemføres af personen, der har booket opholdet. Bedes du ringe til vores kundeservice på 08-517 517 00, hvis du har brug for yderligere hjælp.",
|
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Da dette er et ophold med flere værelser, skal annullereringen gennemføres af personen, der har booket opholdet. Bedes du ringe til vores kundeservice på 08-517 517 00, hvis du har brug for yderligere hjælp.",
|
||||||
"At a cost": "Mod betaling",
|
"At a cost": "Mod betaling",
|
||||||
|
"As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.": "Din booking inkluderer værelser med forskellige vilkår, vi vil blive opkræve en del af bookingen nu og resten vil blive indsamlet ved check-in.",
|
||||||
"At latest": "Senest",
|
"At latest": "Senest",
|
||||||
"At the hotel": "På hotellet",
|
"At the hotel": "På hotellet",
|
||||||
"Attractions": "Attraktioner",
|
"Attractions": "Attraktioner",
|
||||||
@@ -493,6 +494,7 @@
|
|||||||
"Parking / Garage": "Parkering / Garage",
|
"Parking / Garage": "Parkering / Garage",
|
||||||
"Parking can be reserved in advance": "Parkering kan reserveres på forhånd",
|
"Parking can be reserved in advance": "Parkering kan reserveres på forhånd",
|
||||||
"Password": "Adgangskode",
|
"Password": "Adgangskode",
|
||||||
|
"Pay at check-in": "Betal ved check-in",
|
||||||
"Pay later": "Betal senere",
|
"Pay later": "Betal senere",
|
||||||
"Pay now": "Betal nu",
|
"Pay now": "Betal nu",
|
||||||
"Pay the member price of {amount} for Room {roomNr}": "Betal medlemsprisen på {amount} til værelse {roomNr}",
|
"Pay the member price of {amount} for Room {roomNr}": "Betal medlemsprisen på {amount} til værelse {roomNr}",
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
"As our {level}": "Als unser {level}",
|
"As our {level}": "Als unser {level}",
|
||||||
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Da dies ein Mehrzimmer-Aufenthalt ist, muss die Stornierung von der Person, die die Buchung getätigt hat, durchgeführt werden. Bitte rufen Sie uns unter der Telefonnummer 08-517 517 00 an, wenn Sie weitere Hilfe benötigen.",
|
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Da dies ein Mehrzimmer-Aufenthalt ist, muss die Stornierung von der Person, die die Buchung getätigt hat, durchgeführt werden. Bitte rufen Sie uns unter der Telefonnummer 08-517 517 00 an, wenn Sie weitere Hilfe benötigen.",
|
||||||
"At a cost": "Gegen Gebühr",
|
"At a cost": "Gegen Gebühr",
|
||||||
|
"As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.": "Ihre Buchung enthält Zimmer mit unterschiedlichen Bedingungen, wir werden einen Teil der Buchung jetzt belasten und den Rest bei der Anreise durch die Reception erheben.",
|
||||||
"At latest": "Spätestens",
|
"At latest": "Spätestens",
|
||||||
"At the hotel": "Im Hotel",
|
"At the hotel": "Im Hotel",
|
||||||
"Attraction": "Attraktion",
|
"Attraction": "Attraktion",
|
||||||
@@ -493,6 +494,7 @@
|
|||||||
"Parking / Garage": "Parken / Garage",
|
"Parking / Garage": "Parken / Garage",
|
||||||
"Parking can be reserved in advance": "Parkplätze können im Voraus reserviert werden",
|
"Parking can be reserved in advance": "Parkplätze können im Voraus reserviert werden",
|
||||||
"Password": "Passwort",
|
"Password": "Passwort",
|
||||||
|
"Pay at check-in": "Beim Check-in bezahlen",
|
||||||
"Pay later": "Später bezahlen",
|
"Pay later": "Später bezahlen",
|
||||||
"Pay now": "Jetzt bezahlen",
|
"Pay now": "Jetzt bezahlen",
|
||||||
"Pay the member price of {amount} for Room {roomNr}": "Zahlen Sie den Mitgliedspreis von {amount} für Zimmer {roomNr}",
|
"Pay the member price of {amount} for Room {roomNr}": "Zahlen Sie den Mitgliedspreis von {amount} für Zimmer {roomNr}",
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
"As our {level}": "As our {level}",
|
"As our {level}": "As our {level}",
|
||||||
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.",
|
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.",
|
||||||
"At a cost": "At a cost",
|
"At a cost": "At a cost",
|
||||||
|
"As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.": "As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.",
|
||||||
"At latest": "At latest",
|
"At latest": "At latest",
|
||||||
"At the hotel": "At the hotel",
|
"At the hotel": "At the hotel",
|
||||||
"Attractions": "Attractions",
|
"Attractions": "Attractions",
|
||||||
@@ -499,6 +500,7 @@
|
|||||||
"Parking / Garage": "Parking / Garage",
|
"Parking / Garage": "Parking / Garage",
|
||||||
"Parking can be reserved in advance": "Parking can be reserved in advance",
|
"Parking can be reserved in advance": "Parking can be reserved in advance",
|
||||||
"Password": "Password",
|
"Password": "Password",
|
||||||
|
"Pay at check-in": "Pay at check-in",
|
||||||
"Pay later": "Pay later",
|
"Pay later": "Pay later",
|
||||||
"Pay now": "Pay now",
|
"Pay now": "Pay now",
|
||||||
"Pay the member price of {amount} for Room {roomNr}": "Pay the member price of {amount} for Room {roomNr}",
|
"Pay the member price of {amount} for Room {roomNr}": "Pay the member price of {amount} for Room {roomNr}",
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
"As our {level}": "{level}-etu",
|
"As our {level}": "{level}-etu",
|
||||||
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Koska tämä on monihuoneinen majoitus, peruutus on tehtävä henkilölle, joka teki varauksen. Ota yhteyttä asiakaspalveluun apua varten, jos tarvitset lisää apua.",
|
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Koska tämä on monihuoneinen majoitus, peruutus on tehtävä henkilölle, joka teki varauksen. Ota yhteyttä asiakaspalveluun apua varten, jos tarvitset lisää apua.",
|
||||||
"At a cost": "Maksua vastaan",
|
"At a cost": "Maksua vastaan",
|
||||||
|
"As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.": "Sinun varauksessasi on huoneita eri hinnoilla, me veloitamme osan varauksesta nyt ja loput tarkistukseen tapahtuvan tarkistuksen yhteydessä.",
|
||||||
"At latest": "Viimeistään",
|
"At latest": "Viimeistään",
|
||||||
"At the hotel": "Hotellissa",
|
"At the hotel": "Hotellissa",
|
||||||
"Attractions": "Nähtävyydet",
|
"Attractions": "Nähtävyydet",
|
||||||
@@ -492,6 +493,7 @@
|
|||||||
"Parking / Garage": "Pysäköinti / Autotalli",
|
"Parking / Garage": "Pysäköinti / Autotalli",
|
||||||
"Parking can be reserved in advance": "Pysäköintipaikan voi varata etukäteen",
|
"Parking can be reserved in advance": "Pysäköintipaikan voi varata etukäteen",
|
||||||
"Password": "Salasana",
|
"Password": "Salasana",
|
||||||
|
"Pay at check-in": "Maksa tarkistuksessa",
|
||||||
"Pay later": "Maksa myöhemmin",
|
"Pay later": "Maksa myöhemmin",
|
||||||
"Pay now": "Maksa nyt",
|
"Pay now": "Maksa nyt",
|
||||||
"Pay the member price of {amount} for Room {roomNr}": "Maksa jäsenhinta {amount} varten Huone {roomNr}",
|
"Pay the member price of {amount} for Room {roomNr}": "Maksa jäsenhinta {amount} varten Huone {roomNr}",
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
"As our {level}": "Som vår {level}",
|
"As our {level}": "Som vår {level}",
|
||||||
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Som dette er et ophold med flere rom, må annullereringen gjøres av personen som booket opholdet. Vennligst ring 08-517 517 00 til vår kundeservice hvis du trenger mer hjelp.",
|
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Som dette er et ophold med flere rom, må annullereringen gjøres av personen som booket opholdet. Vennligst ring 08-517 517 00 til vår kundeservice hvis du trenger mer hjelp.",
|
||||||
"At a cost": "Mot betaling",
|
"At a cost": "Mot betaling",
|
||||||
|
"As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.": "Din bestilling inkluderer rom med ulike vilkår, vi vil belaste en del av bestillingen nå og den resterende vil bli samlet inn ved check-in.",
|
||||||
"At latest": "Senest",
|
"At latest": "Senest",
|
||||||
"At the hotel": "På hotellet",
|
"At the hotel": "På hotellet",
|
||||||
"Attractions": "Attraksjoner",
|
"Attractions": "Attraksjoner",
|
||||||
@@ -491,6 +492,7 @@
|
|||||||
"Parking / Garage": "Parkering / Garasje",
|
"Parking / Garage": "Parkering / Garasje",
|
||||||
"Parking can be reserved in advance": "Parkering kan reserveres på forhånd",
|
"Parking can be reserved in advance": "Parkering kan reserveres på forhånd",
|
||||||
"Password": "Passord",
|
"Password": "Passord",
|
||||||
|
"Pay at check-in": "Betal ved check-in",
|
||||||
"Pay later": "Betal senere",
|
"Pay later": "Betal senere",
|
||||||
"Pay now": "Betal nå",
|
"Pay now": "Betal nå",
|
||||||
"Pay the member price of {amount} for Room {roomNr}": "Betal medlemsprisen på {amount} for rom {roomNr}",
|
"Pay the member price of {amount} for Room {roomNr}": "Betal medlemsprisen på {amount} for rom {roomNr}",
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
"As our {level}": "Som vår {level}",
|
"As our {level}": "Som vår {level}",
|
||||||
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Då detta är en vistelse med flera rum måste avbokningen göras av personen som bokade vistelsen. Kontakta vår kundsupport på 08-517 517 00 om du behöver mer hjälp.",
|
"As this is a multiroom stay, the cancellation has to be done by the person who made the booking. Please call 08-517 517 00 to talk to our customer service if you would need further assistance.": "Då detta är en vistelse med flera rum måste avbokningen göras av personen som bokade vistelsen. Kontakta vår kundsupport på 08-517 517 00 om du behöver mer hjälp.",
|
||||||
"At a cost": "Mot en kostnad",
|
"At a cost": "Mot en kostnad",
|
||||||
|
"As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.": "Din bokning innehåller rum med olika villkor, vi kommer att debitera en del av bokningen nu och resten kommer att samlas in vid check-in.",
|
||||||
"At latest": "Senast",
|
"At latest": "Senast",
|
||||||
"At the hotel": "På hotellet",
|
"At the hotel": "På hotellet",
|
||||||
"Attractions": "Sevärdheter",
|
"Attractions": "Sevärdheter",
|
||||||
@@ -491,6 +492,7 @@
|
|||||||
"Parking / Garage": "Parkering / Garage",
|
"Parking / Garage": "Parkering / Garage",
|
||||||
"Parking can be reserved in advance": "Parkering kan reserveras i förväg",
|
"Parking can be reserved in advance": "Parkering kan reserveras i förväg",
|
||||||
"Password": "Lösenord",
|
"Password": "Lösenord",
|
||||||
|
"Pay at check-in": "Betala vid check-in",
|
||||||
"Pay later": "Betala senare",
|
"Pay later": "Betala senare",
|
||||||
"Pay now": "Betala nu",
|
"Pay now": "Betala nu",
|
||||||
"Pay the member price of {amount} for Room {roomNr}": "Betala medlemspriset på {amount} för rum {roomNr}",
|
"Pay the member price of {amount} for Room {roomNr}": "Betala medlemspriset på {amount} för rum {roomNr}",
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export default function EnterDetailsProvider({
|
|||||||
.map((room) => ({
|
.map((room) => ({
|
||||||
isAvailable: room.isAvailable,
|
isAvailable: room.isAvailable,
|
||||||
breakfastIncluded: !!room.breakfastIncluded,
|
breakfastIncluded: !!room.breakfastIncluded,
|
||||||
|
cancellationRule: room.cancellationRule,
|
||||||
cancellationText: room.cancellationText,
|
cancellationText: room.cancellationText,
|
||||||
rateDetails: room.rateDetails,
|
rateDetails: room.rateDetails,
|
||||||
rateTitle: room.rateTitle,
|
rateTitle: room.rateTitle,
|
||||||
@@ -54,6 +55,7 @@ export default function EnterDetailsProvider({
|
|||||||
description: room.bedTypes[0].description,
|
description: room.bedTypes[0].description,
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
|
mustBeGuaranteed: room.mustBeGuaranteed,
|
||||||
})),
|
})),
|
||||||
vat,
|
vat,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -788,6 +788,7 @@ export const hotelQueryRouter = router({
|
|||||||
return {
|
return {
|
||||||
selectedRoom,
|
selectedRoom,
|
||||||
rateDetails: rateDefinition?.generalTerms,
|
rateDetails: rateDefinition?.generalTerms,
|
||||||
|
cancellationRule: rateDefinition?.cancellationRule,
|
||||||
cancellationText: rateDefinition?.cancellationText ?? "",
|
cancellationText: rateDefinition?.cancellationText ?? "",
|
||||||
mustBeGuaranteed: !!rateDefinition?.mustBeGuaranteed,
|
mustBeGuaranteed: !!rateDefinition?.mustBeGuaranteed,
|
||||||
breakfastIncluded: !!rateDefinition?.breakfastIncluded,
|
breakfastIncluded: !!rateDefinition?.breakfastIncluded,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import type { PaymentMethodEnum } from "@/constants/booking"
|
|||||||
|
|
||||||
export interface PaymentProps {
|
export interface PaymentProps {
|
||||||
otherPaymentOptions: PaymentMethodEnum[]
|
otherPaymentOptions: PaymentMethodEnum[]
|
||||||
mustBeGuaranteed: boolean
|
|
||||||
supportedCards: PaymentMethodEnum[]
|
supportedCards: PaymentMethodEnum[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import type { Packages } from "@/types/requests/packages"
|
|||||||
export interface Room {
|
export interface Room {
|
||||||
bedTypes?: BedTypeSelection[]
|
bedTypes?: BedTypeSelection[]
|
||||||
breakfastIncluded?: boolean
|
breakfastIncluded?: boolean
|
||||||
|
cancellationRule?: string
|
||||||
cancellationText: string
|
cancellationText: string
|
||||||
mustBeGuaranteed?: boolean
|
mustBeGuaranteed: boolean
|
||||||
packages: Packages | null
|
packages: Packages | null
|
||||||
rateDetails: string[]
|
rateDetails: string[]
|
||||||
rateTitle?: string
|
rateTitle?: string
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ export interface InitialRoomData {
|
|||||||
bedTypes: BedTypeSelection[]
|
bedTypes: BedTypeSelection[]
|
||||||
breakfastIncluded: boolean
|
breakfastIncluded: boolean
|
||||||
cancellationText: string
|
cancellationText: string
|
||||||
|
cancellationRule?: string
|
||||||
rateDetails: string[] | undefined
|
rateDetails: string[] | undefined
|
||||||
rateTitle?: string
|
rateTitle?: string
|
||||||
roomFeatures: Packages | null
|
roomFeatures: Packages | null
|
||||||
roomRate: RoomRate
|
roomRate: RoomRate
|
||||||
roomType: string
|
roomType: string
|
||||||
roomTypeCode: string
|
roomTypeCode: string
|
||||||
|
mustBeGuaranteed: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RoomStep = {
|
export type RoomStep = {
|
||||||
|
|||||||
Reference in New Issue
Block a user