Merged in feat/SW-2078-update-confirmation-page-vouchers (pull request #1731)
Feat/SW-2078 update confirmation page vouchers and Corp Cheques rate * feat: SW-2078 Tablet bookingCode ref forward issue fix (cherry picked from commit 16a6a00fd99b6b6220a98ad74de062d67d35e1c0) * feat: SW-2078 Display Vouchers and Cheques prices on confirmation page (cherry picked from commit a76494de497a7d5e7641cb0036bd7055acf875c1) * feat: SW-2078 Rebase issue fix * feat: SW-2079 Updated rate title in terms modal * feat: SW-2078 Optimized code * feat: SW-2078 Removed extra tags Approved-by: Christian Andolf
This commit is contained in:
@@ -322,6 +322,15 @@ function TabletBookingCode({
|
|||||||
const codeVoucher = intl.formatMessage({ id: "Code / Voucher" })
|
const codeVoucher = intl.formatMessage({ id: "Code / Voucher" })
|
||||||
|
|
||||||
function toggleModal(isOpen: boolean) {
|
function toggleModal(isOpen: boolean) {
|
||||||
|
if (document.body) {
|
||||||
|
if (isOpen) {
|
||||||
|
document.body.style.overflow = "visible"
|
||||||
|
} else {
|
||||||
|
// !important needed to override 'overflow: hidden' set by react-aria.
|
||||||
|
// 'overflow: hidden' does not work in combination with other sticky positioned elements, which clip does.
|
||||||
|
document.body.style.overflow = "clip !important"
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!isOpen && !bookingCode?.value) {
|
if (!isOpen && !bookingCode?.value) {
|
||||||
setValue("bookingCode.flag", false)
|
setValue("bookingCode.flag", false)
|
||||||
setIsOpen(isOpen)
|
setIsOpen(isOpen)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
|
|||||||
|
|
||||||
import Modal from "@/components/Modal"
|
import Modal from "@/components/Modal"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import IconChip from "@/components/TempDesignSystem/IconChip"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
import { formatPrice } from "@/utils/numberFormatting"
|
import { formatPrice } from "@/utils/numberFormatting"
|
||||||
@@ -45,15 +46,26 @@ function TableSection({ children }: React.PropsWithChildren) {
|
|||||||
function TableSectionHeader({
|
function TableSectionHeader({
|
||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
|
bold,
|
||||||
}: {
|
}: {
|
||||||
title: string
|
title: string
|
||||||
subtitle?: string
|
subtitle?: string
|
||||||
|
bold?: boolean
|
||||||
}) {
|
}) {
|
||||||
|
const typographyVariant = bold
|
||||||
|
? "Body/Paragraph/mdBold"
|
||||||
|
: "Body/Paragraph/mdRegular"
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<th colSpan={2}>
|
<th colSpan={2} align="left">
|
||||||
<Body>{title}</Body>
|
<Typography variant={typographyVariant}>
|
||||||
{subtitle ? <Body>{subtitle}</Body> : null}
|
<p>{title}</p>
|
||||||
|
</Typography>
|
||||||
|
{subtitle ? (
|
||||||
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
|
<p>{subtitle}</p>
|
||||||
|
</Typography>
|
||||||
|
) : null}
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
@@ -130,12 +142,13 @@ export default function PriceDetailsModal() {
|
|||||||
<React.Fragment key={idx}>
|
<React.Fragment key={idx}>
|
||||||
<TableSection>
|
<TableSection>
|
||||||
{rooms.length > 1 && (
|
{rooms.length > 1 && (
|
||||||
<Body textTransform="bold">
|
<TableSectionHeader
|
||||||
{intl.formatMessage(
|
title={intl.formatMessage(
|
||||||
{ id: "Room {roomIndex}" },
|
{ id: "Room {roomIndex}" },
|
||||||
{ roomIndex: idx + 1 }
|
{ roomIndex: idx + 1 }
|
||||||
)}
|
)}
|
||||||
</Body>
|
bold
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<TableSectionHeader title={room.name} subtitle={duration} />
|
<TableSectionHeader title={room.name} subtitle={duration} />
|
||||||
{room.roomFeatures
|
{room.roomFeatures
|
||||||
@@ -179,14 +192,14 @@ export default function PriceDetailsModal() {
|
|||||||
currencyCode
|
currencyCode
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{room.children ? (
|
{room.childrenAges?.length ? (
|
||||||
<Row
|
<Row
|
||||||
label={intl.formatMessage(
|
label={intl.formatMessage(
|
||||||
{
|
{
|
||||||
id: "Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
id: "Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
totalChildren: room.children,
|
totalChildren: room.childrenAges.length,
|
||||||
totalBreakfasts: diff,
|
totalBreakfasts: diff,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
@@ -237,11 +250,26 @@ export default function PriceDetailsModal() {
|
|||||||
</tr>
|
</tr>
|
||||||
{bookingCode && (
|
{bookingCode && (
|
||||||
<tr className={styles.row}>
|
<tr className={styles.row}>
|
||||||
<td>
|
<td colSpan={2} align="left">
|
||||||
<MaterialIcon icon="sell" />
|
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||||
{bookingCode}
|
<IconChip
|
||||||
|
color="blue"
|
||||||
|
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "<strong>Booking code</strong>: {value}" },
|
||||||
|
{
|
||||||
|
value: bookingCode,
|
||||||
|
strong: (text) => (
|
||||||
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
|
<strong>{text}</strong>
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</IconChip>
|
||||||
|
</Typography>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</TableSection>
|
</TableSection>
|
||||||
|
|||||||
@@ -23,10 +23,13 @@ export default function ReceiptRoom({
|
|||||||
roomIndex,
|
roomIndex,
|
||||||
}: BookingConfirmationReceiptRoomProps) {
|
}: BookingConfirmationReceiptRoomProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const { room, currencyCode } = useBookingConfirmationStore((state) => ({
|
const { room, currencyCode, isVatCurrency } = useBookingConfirmationStore(
|
||||||
room: state.rooms[roomIndex],
|
(state) => ({
|
||||||
currencyCode: state.currencyCode,
|
room: state.rooms[roomIndex],
|
||||||
}))
|
currencyCode: state.currencyCode,
|
||||||
|
isVatCurrency: state.isVatCurrency,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
if (!room) {
|
if (!room) {
|
||||||
return <RoomSkeletonLoader />
|
return <RoomSkeletonLoader />
|
||||||
@@ -56,7 +59,7 @@ export default function ReceiptRoom({
|
|||||||
) : (
|
) : (
|
||||||
<Typography variant="Body/Paragraph/mdRegular">
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
<p className={styles.uiTextHighContrast}>
|
<p className={styles.uiTextHighContrast}>
|
||||||
{formatPrice(intl, room.roomPrice, currencyCode)}
|
{room.formattedTotalCost}
|
||||||
</p>
|
</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
@@ -91,9 +94,9 @@ export default function ReceiptRoom({
|
|||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
title={
|
title={
|
||||||
(room.roomPoints
|
(isVatCurrency
|
||||||
? room.rateDefinition.title
|
? room.rateDefinition.cancellationText
|
||||||
: room.rateDefinition.cancellationText) || ""
|
: room.rateDefinition.title) || ""
|
||||||
}
|
}
|
||||||
subtitle={
|
subtitle={
|
||||||
room.rateDefinition.cancellationRule ===
|
room.rateDefinition.cancellationRule ===
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { LinkedReservationCardSkeleton } from "./LinkedReservationCardSkeleton"
|
|||||||
import Retry from "./Retry"
|
import Retry from "./Retry"
|
||||||
|
|
||||||
import type { LinkedReservationProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/linkedReservation"
|
import type { LinkedReservationProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/linkedReservation"
|
||||||
|
import { CurrencyEnum } from "@/types/enums/currency"
|
||||||
|
|
||||||
export function LinkedReservation({
|
export function LinkedReservation({
|
||||||
checkInTime,
|
checkInTime,
|
||||||
@@ -27,13 +28,19 @@ export function LinkedReservation({
|
|||||||
confirmationNumber,
|
confirmationNumber,
|
||||||
lang,
|
lang,
|
||||||
})
|
})
|
||||||
const { setRoom, setFormattedTotalCost, currencyCode, totalBookingPrice } =
|
const {
|
||||||
useBookingConfirmationStore((state) => ({
|
setRoom,
|
||||||
setRoom: state.actions.setRoom,
|
setFormattedTotalCost,
|
||||||
setFormattedTotalCost: state.actions.setFormattedTotalCost,
|
currencyCode,
|
||||||
currencyCode: state.currencyCode,
|
totalBookingPrice,
|
||||||
totalBookingPrice: state.totalBookingPrice,
|
totalBookingCheques,
|
||||||
}))
|
} = useBookingConfirmationStore((state) => ({
|
||||||
|
setRoom: state.actions.setRoom,
|
||||||
|
setFormattedTotalCost: state.actions.setFormattedTotalCost,
|
||||||
|
currencyCode: state.currencyCode,
|
||||||
|
totalBookingPrice: state.totalBookingPrice,
|
||||||
|
totalBookingCheques: state.totalBookingCheques,
|
||||||
|
}))
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -41,18 +48,24 @@ export function LinkedReservation({
|
|||||||
const roomData = mapRoomState(data.booking, data.room, intl)
|
const roomData = mapRoomState(data.booking, data.room, intl)
|
||||||
setRoom(roomData, roomIndex)
|
setRoom(roomData, roomIndex)
|
||||||
|
|
||||||
const formattedTotalCost = formatPrice(
|
const formattedTotalCost = totalBookingCheques
|
||||||
intl,
|
? formatPrice(
|
||||||
totalBookingPrice,
|
intl,
|
||||||
currencyCode
|
totalBookingCheques,
|
||||||
)
|
CurrencyEnum.CC,
|
||||||
|
totalBookingPrice,
|
||||||
|
currencyCode
|
||||||
|
)
|
||||||
|
: formatPrice(intl, totalBookingPrice, currencyCode)
|
||||||
|
|
||||||
setFormattedTotalCost(formattedTotalCost)
|
setFormattedTotalCost(formattedTotalCost)
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
data,
|
data,
|
||||||
roomIndex,
|
roomIndex,
|
||||||
setRoom,
|
|
||||||
intl,
|
intl,
|
||||||
|
setRoom,
|
||||||
|
totalBookingCheques,
|
||||||
totalBookingPrice,
|
totalBookingPrice,
|
||||||
currencyCode,
|
currencyCode,
|
||||||
setFormattedTotalCost,
|
setFormattedTotalCost,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export function getTracking(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const noOfAdults = rooms.map((r) => r.adults).join(",")
|
const noOfAdults = rooms.map((r) => r.adults).join(",")
|
||||||
const noOfChildren = rooms.map((r) => r.children ?? 0).join(",")
|
const noOfChildren = rooms.map((r) => r.childrenAges?.length ?? 0).join(",")
|
||||||
const noOfRooms = rooms.length
|
const noOfRooms = rooms.length
|
||||||
|
|
||||||
const hotelsTrackingData: TrackingSDKHotelInfo = {
|
const hotelsTrackingData: TrackingSDKHotelInfo = {
|
||||||
|
|||||||
@@ -32,6 +32,20 @@ export function mapRoomState(
|
|||||||
booking.totalPrice,
|
booking.totalPrice,
|
||||||
booking.currencyCode
|
booking.currencyCode
|
||||||
)
|
)
|
||||||
|
} else if (booking.cheques) {
|
||||||
|
formattedTotalCost = formatPrice(
|
||||||
|
intl,
|
||||||
|
booking.cheques,
|
||||||
|
CurrencyEnum.CC,
|
||||||
|
booking.totalPrice,
|
||||||
|
booking.currencyCode
|
||||||
|
)
|
||||||
|
} else if (booking.vouchers) {
|
||||||
|
formattedTotalCost = formatPrice(
|
||||||
|
intl,
|
||||||
|
booking.vouchers,
|
||||||
|
CurrencyEnum.Voucher
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -39,7 +53,7 @@ export function mapRoomState(
|
|||||||
bedDescription: room.bedType.description,
|
bedDescription: room.bedType.description,
|
||||||
breakfast,
|
breakfast,
|
||||||
breakfastIncluded,
|
breakfastIncluded,
|
||||||
children: booking.childrenAges.length,
|
cheques: booking.cheques,
|
||||||
childrenAges: booking.childrenAges,
|
childrenAges: booking.childrenAges,
|
||||||
childBedPreferences: booking.childBedPreferences,
|
childBedPreferences: booking.childBedPreferences,
|
||||||
confirmationNumber: booking.confirmationNumber,
|
confirmationNumber: booking.confirmationNumber,
|
||||||
@@ -57,5 +71,6 @@ export function mapRoomState(
|
|||||||
totalPrice: booking.totalPrice,
|
totalPrice: booking.totalPrice,
|
||||||
totalPriceExVat: booking.totalPriceExVat,
|
totalPriceExVat: booking.totalPriceExVat,
|
||||||
vatAmount: booking.vatAmount,
|
vatAmount: booking.vatAmount,
|
||||||
|
vouchers: booking.vouchers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
import { Fragment } from "react"
|
import { Fragment } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
|
||||||
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
|
|
||||||
|
import IconChip from "@/components/TempDesignSystem/IconChip"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
@@ -328,13 +330,28 @@ export default function PriceDetailsTable({
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : null}
|
) : null}
|
||||||
{bookingCode && totalPrice.local.regularPrice && (
|
{bookingCode && (
|
||||||
<tr className={styles.row}>
|
<tr className={styles.row}>
|
||||||
<td>
|
<td colSpan={2} align="left">
|
||||||
<MaterialIcon icon="sell" />
|
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||||
{bookingCode}
|
<IconChip
|
||||||
|
color="blue"
|
||||||
|
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "<strong>Booking code</strong>: {value}" },
|
||||||
|
{
|
||||||
|
value: bookingCode,
|
||||||
|
strong: (text) => (
|
||||||
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
|
<strong>{text}</strong>
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</IconChip>
|
||||||
|
</Typography>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</TableSection>
|
</TableSection>
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
import { Fragment } from "react"
|
import { Fragment } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
|
|
||||||
@@ -12,6 +14,7 @@ import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Deskto
|
|||||||
import Modal from "@/components/Modal"
|
import Modal from "@/components/Modal"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
import Divider from "@/components/TempDesignSystem/Divider"
|
import Divider from "@/components/TempDesignSystem/Divider"
|
||||||
|
import IconChip from "@/components/TempDesignSystem/IconChip"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
@@ -450,10 +453,24 @@ export default function SummaryUI({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{booking.bookingCode && (
|
{booking.bookingCode && (
|
||||||
<div>
|
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||||
<MaterialIcon icon="sell" />
|
<IconChip
|
||||||
{booking.bookingCode}
|
color="blue"
|
||||||
</div>
|
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "<strong>Booking code</strong>: {value}" },
|
||||||
|
{
|
||||||
|
value: booking.bookingCode,
|
||||||
|
strong: (text) => (
|
||||||
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
|
<strong>{text}</strong>
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</IconChip>
|
||||||
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<Divider className={styles.bottomDivider} color="primaryLightSubtle" />
|
<Divider className={styles.bottomDivider} color="primaryLightSubtle" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { useRouter, useSearchParams } from "next/navigation"
|
|||||||
import { memo, useCallback } from "react"
|
import { memo, useCallback } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
|
||||||
import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon"
|
import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import { selectHotelMap, selectRate } from "@/constants/routes/hotelReservation"
|
import { selectHotelMap, selectRate } from "@/constants/routes/hotelReservation"
|
||||||
@@ -185,14 +185,26 @@ function HotelCard({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{bookingCode && (
|
{bookingCode && (
|
||||||
<span className={`${fullPrice ? styles.strikedText : ""}`}>
|
<div className={`${fullPrice ? styles.strikedText : ""}`}>
|
||||||
<IconChip
|
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||||
color="blue"
|
<IconChip
|
||||||
icon={<MaterialIcon icon="sell" size={20} />}
|
color="blue"
|
||||||
>
|
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||||
{bookingCode}
|
>
|
||||||
</IconChip>
|
{intl.formatMessage(
|
||||||
</span>
|
{ id: "<strong>Booking code</strong>: {value}" },
|
||||||
|
{
|
||||||
|
value: bookingCode,
|
||||||
|
strong: (text) => (
|
||||||
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
|
<strong>{text}</strong>
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</IconChip>
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{(!isUserLoggedIn ||
|
{(!isUserLoggedIn ||
|
||||||
!price?.member ||
|
!price?.member ||
|
||||||
|
|||||||
@@ -273,17 +273,24 @@ export function ReferenceCard({
|
|||||||
<Typography variant="Title/Overline/sm">
|
<Typography variant="Title/Overline/sm">
|
||||||
<p>{intl.formatMessage({ id: "Booking code" })}</p>
|
<p>{intl.formatMessage({ id: "Booking code" })}</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconChip
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
color="blue"
|
<IconChip
|
||||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
color="blue"
|
||||||
>
|
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
>
|
||||||
<p className={styles.bookingCode}>
|
{intl.formatMessage(
|
||||||
<strong>{intl.formatMessage({ id: "Booking code" })}</strong>:{" "}
|
{ id: "<strong>Booking code</strong>: {value}" },
|
||||||
{bookingCode}
|
{
|
||||||
</p>
|
value: bookingCode,
|
||||||
</Typography>
|
strong: (text) => (
|
||||||
</IconChip>
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
|
<strong>{text}</strong>
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</IconChip>
|
||||||
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={styles.actionArea}>
|
<div className={styles.actionArea}>
|
||||||
|
|||||||
@@ -43,10 +43,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookingCode {
|
|
||||||
color: var(--UI-Semantic-Information);
|
|
||||||
}
|
|
||||||
|
|
||||||
.guaranteed {
|
.guaranteed {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
border-radius: var(--Corner-radius-Medium);
|
border-radius: var(--Corner-radius-Medium);
|
||||||
|
|||||||
@@ -343,19 +343,24 @@ export function SingleRoom({ bedType, image, hotel, user }: RoomProps) {
|
|||||||
</div>
|
</div>
|
||||||
<div className={styles.bookingInformation}>
|
<div className={styles.bookingInformation}>
|
||||||
{bookingCode && (
|
{bookingCode && (
|
||||||
<IconChip
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
color="blue"
|
<IconChip
|
||||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
color="blue"
|
||||||
>
|
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
>
|
||||||
<p className={styles.bookingCode}>
|
{intl.formatMessage(
|
||||||
<strong>
|
{ id: "<strong>Booking code</strong>: {value}" },
|
||||||
{intl.formatMessage({ id: "Booking code" })}
|
{
|
||||||
</strong>
|
value: bookingCode,
|
||||||
: {bookingCode}
|
strong: (text) => (
|
||||||
</p>
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
</Typography>
|
<strong>{text}</strong>
|
||||||
</IconChip>
|
</Typography>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</IconChip>
|
||||||
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<div className={styles.priceDetails}>
|
<div className={styles.priceDetails}>
|
||||||
<div className={styles.price}>
|
<div className={styles.price}>
|
||||||
|
|||||||
@@ -6,10 +6,6 @@
|
|||||||
padding: var(--Spacing-x3) 0;
|
padding: var(--Spacing-x3) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookingCode {
|
|
||||||
color: var(--UI-Semantic-Information);
|
|
||||||
}
|
|
||||||
|
|
||||||
.roomName {
|
.roomName {
|
||||||
color: var(--Scandic-Brand-Burgundy);
|
color: var(--Scandic-Brand-Burgundy);
|
||||||
padding: 0 var(--Spacing-x2);
|
padding: 0 var(--Spacing-x2);
|
||||||
|
|||||||
@@ -291,17 +291,24 @@ export default function BookedRoomSidePeek({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{bookingCode && (
|
{bookingCode && (
|
||||||
<IconChip
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
color="blue"
|
<IconChip
|
||||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
color="blue"
|
||||||
>
|
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
>
|
||||||
<p className={styles.bookingCode}>
|
{intl.formatMessage(
|
||||||
<strong>{intl.formatMessage({ id: "Booking code" })}</strong>
|
{ id: "<strong>Booking code</strong>: {value}" },
|
||||||
{bookingCode}
|
{
|
||||||
</p>
|
value: bookingCode,
|
||||||
</Typography>
|
strong: (text) => (
|
||||||
</IconChip>
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
|
<strong>{text}</strong>
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</IconChip>
|
||||||
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<GuestDetails
|
<GuestDetails
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { forwardRef } from "react"
|
||||||
import { Checkbox as AriaCheckbox } from "react-aria-components"
|
import { Checkbox as AriaCheckbox } from "react-aria-components"
|
||||||
import { useController, useFormContext } from "react-hook-form"
|
import { useController, useFormContext } from "react-hook-form"
|
||||||
|
|
||||||
@@ -11,14 +12,13 @@ import styles from "./checkbox.module.css"
|
|||||||
|
|
||||||
import type { CheckboxProps } from "@/types/components/checkbox"
|
import type { CheckboxProps } from "@/types/components/checkbox"
|
||||||
|
|
||||||
export default function Checkbox({
|
const Checkbox = forwardRef<
|
||||||
className,
|
HTMLInputElement,
|
||||||
name,
|
React.PropsWithChildren<CheckboxProps>
|
||||||
children,
|
>(function Checkbox(
|
||||||
registerOptions,
|
{ className, name, children, registerOptions, hideError, topAlign = false },
|
||||||
hideError,
|
ref
|
||||||
topAlign = false,
|
) {
|
||||||
}: React.PropsWithChildren<CheckboxProps>) {
|
|
||||||
const { control } = useFormContext()
|
const { control } = useFormContext()
|
||||||
const { field, fieldState } = useController({
|
const { field, fieldState } = useController({
|
||||||
control,
|
control,
|
||||||
@@ -43,6 +43,7 @@ export default function Checkbox({
|
|||||||
<span
|
<span
|
||||||
className={styles.checkbox}
|
className={styles.checkbox}
|
||||||
tabIndex={registerOptions?.disabled ? undefined : 0}
|
tabIndex={registerOptions?.disabled ? undefined : 0}
|
||||||
|
ref={ref}
|
||||||
>
|
>
|
||||||
{isSelected && (
|
{isSelected && (
|
||||||
<MaterialIcon icon="check" color="Icon/Inverted" />
|
<MaterialIcon icon="check" color="Icon/Inverted" />
|
||||||
@@ -60,4 +61,6 @@ export default function Checkbox({
|
|||||||
)}
|
)}
|
||||||
</AriaCheckbox>
|
</AriaCheckbox>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
|
export default Checkbox
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import { forwardRef, type HTMLAttributes, type WheelEvent } from "react"
|
||||||
import { Text, TextField } from "react-aria-components"
|
import { Text, TextField } from "react-aria-components"
|
||||||
import { Controller, useFormContext } from "react-hook-form"
|
import { Controller, useFormContext } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
@@ -10,24 +11,25 @@ import Caption from "@/components/TempDesignSystem/Text/Caption"
|
|||||||
|
|
||||||
import styles from "./input.module.css"
|
import styles from "./input.module.css"
|
||||||
|
|
||||||
import type { HTMLAttributes, WheelEvent } from "react"
|
|
||||||
|
|
||||||
import type { InputProps } from "./input"
|
import type { InputProps } from "./input"
|
||||||
|
|
||||||
export default function Input({
|
const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
||||||
"aria-label": ariaLabel,
|
{
|
||||||
className = "",
|
"aria-label": ariaLabel,
|
||||||
disabled = false,
|
className = "",
|
||||||
helpText = "",
|
disabled = false,
|
||||||
label,
|
helpText = "",
|
||||||
maxLength,
|
label,
|
||||||
name,
|
maxLength,
|
||||||
placeholder = "",
|
name,
|
||||||
readOnly = false,
|
placeholder = "",
|
||||||
registerOptions = {},
|
readOnly = false,
|
||||||
type = "text",
|
registerOptions = {},
|
||||||
hideError,
|
type = "text",
|
||||||
}: InputProps) {
|
hideError,
|
||||||
|
},
|
||||||
|
ref
|
||||||
|
) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const { control } = useFormContext()
|
const { control } = useFormContext()
|
||||||
let numberAttributes: HTMLAttributes<HTMLInputElement> = {}
|
let numberAttributes: HTMLAttributes<HTMLInputElement> = {}
|
||||||
@@ -58,6 +60,7 @@ export default function Input({
|
|||||||
>
|
>
|
||||||
<AriaInputWithLabel
|
<AriaInputWithLabel
|
||||||
{...field}
|
{...field}
|
||||||
|
ref={ref}
|
||||||
aria-labelledby={field.name}
|
aria-labelledby={field.name}
|
||||||
id={field.name}
|
id={field.name}
|
||||||
label={label}
|
label={label}
|
||||||
@@ -85,4 +88,5 @@ export default function Input({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
export default Input
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||||
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/nat per voksen",
|
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/nat per voksen",
|
||||||
|
"<strong>Booking code</strong>: {value}": "<strong>Bookingkode</strong>: {value}",
|
||||||
"<strong>Status</strong> Paid": "<strong>Status</strong> Betalt",
|
"<strong>Status</strong> Paid": "<strong>Status</strong> Betalt",
|
||||||
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ikke betalt",
|
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ikke betalt",
|
||||||
"A destination or hotel name is needed to be able to search for a hotel room.": "Et destinations- eller hotelnavn er nødvendigt for at kunne søge efter et hotelværelse.",
|
"A destination or hotel name is needed to be able to search for a hotel room.": "Et destinations- eller hotelnavn er nødvendigt for at kunne søge efter et hotelværelse.",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||||
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/Nacht pro Erwachsenem",
|
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/Nacht pro Erwachsenem",
|
||||||
|
"<strong>Booking code</strong>: {value}": "<strong>Buchungscode</strong>: {value}",
|
||||||
"<strong>Status</strong> Paid": "<strong>Status</strong> Bezahlt",
|
"<strong>Status</strong> Paid": "<strong>Status</strong> Bezahlt",
|
||||||
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Unbezahlt",
|
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Unbezahlt",
|
||||||
"A destination or hotel name is needed to be able to search for a hotel room.": "Ein Reiseziel oder Hotelname wird benötigt, um nach einem Hotelzimmer suchen zu können.",
|
"A destination or hotel name is needed to be able to search for a hotel room.": "Ein Reiseziel oder Hotelname wird benötigt, um nach einem Hotelzimmer suchen zu können.",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||||
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult",
|
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult",
|
||||||
|
"<strong>Booking code</strong>: {value}": "<strong>Booking code</strong>: {value}",
|
||||||
"<strong>Status</strong> Paid": "<strong>Status</strong> Paid",
|
"<strong>Status</strong> Paid": "<strong>Status</strong> Paid",
|
||||||
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Unpaid",
|
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Unpaid",
|
||||||
"A destination or hotel name is needed to be able to search for a hotel room.": "A destination or hotel name is needed to be able to search for a hotel room.",
|
"A destination or hotel name is needed to be able to search for a hotel room.": "A destination or hotel name is needed to be able to search for a hotel room.",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||||
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/yötä aikuista kohti",
|
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/yötä aikuista kohti",
|
||||||
|
"<strong>Booking code</strong>: {value}": "<strong>Varauskoodi</strong>: {value}",
|
||||||
"<strong>Status</strong> Paid": "<strong>Status</strong> Maksettu",
|
"<strong>Status</strong> Paid": "<strong>Status</strong> Maksettu",
|
||||||
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ei maksettu",
|
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ei maksettu",
|
||||||
"A destination or hotel name is needed to be able to search for a hotel room.": "Kohteen tai hotellin nimi tarvitaan, jotta hotellihuonetta voidaan hakea.",
|
"A destination or hotel name is needed to be able to search for a hotel room.": "Kohteen tai hotellin nimi tarvitaan, jotta hotellihuonetta voidaan hakea.",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||||
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/natt per voksen",
|
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/natt per voksen",
|
||||||
|
"<strong>Booking code</strong>: {value}": "<strong>Bestillingskode</strong>: {value}",
|
||||||
"<strong>Status</strong> Paid": "<strong>Status</strong> Betalt",
|
"<strong>Status</strong> Paid": "<strong>Status</strong> Betalt",
|
||||||
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ikke betalt",
|
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ikke betalt",
|
||||||
"A destination or hotel name is needed to be able to search for a hotel room.": "Et reisemål eller hotellnavn er nødvendig for å kunne søke etter et hotellrom.",
|
"A destination or hotel name is needed to be able to search for a hotel room.": "Et reisemål eller hotellnavn er nødvendig for å kunne søke etter et hotellrom.",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!": "<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched tiers. Level up in one of your memberships to qualify for an upgrade!",
|
||||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.": "<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||||
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/natt per vuxen",
|
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/natt per vuxen",
|
||||||
|
"<strong>Booking code</strong>: {value}": "<strong>Bokningskod</strong>: {value}",
|
||||||
"<strong>Status</strong> Paid": "<strong>Status</strong> Betalat",
|
"<strong>Status</strong> Paid": "<strong>Status</strong> Betalat",
|
||||||
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ej betalat",
|
"<strong>Status</strong> Unpaid": "<strong>Status</strong> Ej betalat",
|
||||||
"A destination or hotel name is needed to be able to search for a hotel room.": "Ett destinations- eller hotellnamn behövs för att kunna söka efter ett hotellrum.",
|
"A destination or hotel name is needed to be able to search for a hotel room.": "Ett destinations- eller hotellnamn behövs för att kunna söka efter ett hotellrum.",
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ export default function BookingConfirmationProvider({
|
|||||||
const totalBookingPoints = rooms.reduce((acc, room) => {
|
const totalBookingPoints = rooms.reduce((acc, room) => {
|
||||||
return acc + (room?.roomPoints ?? 0)
|
return acc + (room?.roomPoints ?? 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
const totalBookingCheques = rooms.reduce((acc, room) => {
|
||||||
|
return acc + (room?.cheques ?? 0)
|
||||||
|
}, 0)
|
||||||
|
const totalBookingVouchers = rooms.reduce((acc, room) => {
|
||||||
|
return acc + (room?.vouchers ?? 0)
|
||||||
|
}, 0)
|
||||||
|
|
||||||
let isVatCurrency = true
|
let isVatCurrency = true
|
||||||
if (totalBookingPoints) {
|
if (totalBookingPoints) {
|
||||||
isVatCurrency = false
|
isVatCurrency = false
|
||||||
@@ -43,6 +50,22 @@ export default function BookingConfirmationProvider({
|
|||||||
totalBookingPrice,
|
totalBookingPrice,
|
||||||
currencyCode
|
currencyCode
|
||||||
)
|
)
|
||||||
|
} else if (totalBookingCheques) {
|
||||||
|
isVatCurrency = false
|
||||||
|
formattedTotalCost = formatPrice(
|
||||||
|
intl,
|
||||||
|
totalBookingCheques,
|
||||||
|
CurrencyEnum.CC,
|
||||||
|
totalBookingPrice,
|
||||||
|
currencyCode
|
||||||
|
)
|
||||||
|
} else if (totalBookingVouchers) {
|
||||||
|
isVatCurrency = false
|
||||||
|
formattedTotalCost = formatPrice(
|
||||||
|
intl,
|
||||||
|
totalBookingVouchers,
|
||||||
|
CurrencyEnum.Voucher
|
||||||
|
)
|
||||||
}
|
}
|
||||||
const initialData = {
|
const initialData = {
|
||||||
bookingCode,
|
bookingCode,
|
||||||
@@ -54,6 +77,7 @@ export default function BookingConfirmationProvider({
|
|||||||
isVatCurrency,
|
isVatCurrency,
|
||||||
formattedTotalCost,
|
formattedTotalCost,
|
||||||
totalBookingPrice,
|
totalBookingPrice,
|
||||||
|
totalBookingCheques,
|
||||||
}
|
}
|
||||||
|
|
||||||
storeRef.current = createBookingConfirmationStore(initialData)
|
storeRef.current = createBookingConfirmationStore(initialData)
|
||||||
|
|||||||
@@ -19,22 +19,24 @@ export function createBookingConfirmationStore(initialState: InitialState) {
|
|||||||
formattedTotalCost: initialState.formattedTotalCost,
|
formattedTotalCost: initialState.formattedTotalCost,
|
||||||
isVatCurrency: initialState.isVatCurrency,
|
isVatCurrency: initialState.isVatCurrency,
|
||||||
totalBookingPrice: initialState.totalBookingPrice,
|
totalBookingPrice: initialState.totalBookingPrice,
|
||||||
|
totalBookingCheques: initialState.totalBookingCheques,
|
||||||
actions: {
|
actions: {
|
||||||
setRoom: (room, idx) => {
|
setRoom: (room, idx) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const rooms = [...state.rooms]
|
const rooms = [...state.rooms]
|
||||||
rooms[idx] = room
|
rooms[idx] = room
|
||||||
|
|
||||||
const totalBookingPrice = rooms.reduce((acc, room) => {
|
const totalBookingPrice = rooms.reduce((acc, room) => {
|
||||||
return acc + (room?.totalPrice ?? 0)
|
return acc + (room?.totalPrice ?? 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
const totalBookingCheques = rooms.reduce((acc, room) => {
|
||||||
return { rooms, totalBookingPrice }
|
return acc + (room?.cheques ?? 0)
|
||||||
|
}, 0)
|
||||||
|
return { rooms, totalBookingPrice, totalBookingCheques }
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setFormattedTotalCost: (updatedFormattedTotalCost: string) => {
|
setFormattedTotalCost: (formattedTotalCost) => {
|
||||||
set((state) => {
|
set(() => ({ formattedTotalCost }))
|
||||||
return { ...state, formattedTotalCost: updatedFormattedTotalCost }
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface Room {
|
|||||||
bedDescription: string
|
bedDescription: string
|
||||||
breakfast?: PackageSchema
|
breakfast?: PackageSchema
|
||||||
breakfastIncluded: boolean
|
breakfastIncluded: boolean
|
||||||
children?: number
|
cheques: number
|
||||||
childBedPreferences: ChildBedPreference[]
|
childBedPreferences: ChildBedPreference[]
|
||||||
childrenAges?: number[]
|
childrenAges?: number[]
|
||||||
confirmationNumber: string
|
confirmationNumber: string
|
||||||
@@ -32,6 +32,7 @@ export interface Room {
|
|||||||
totalPrice: number
|
totalPrice: number
|
||||||
totalPriceExVat: number
|
totalPriceExVat: number
|
||||||
vatAmount: number
|
vatAmount: number
|
||||||
|
vouchers: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InitialState {
|
export interface InitialState {
|
||||||
@@ -44,20 +45,12 @@ export interface InitialState {
|
|||||||
isVatCurrency: boolean
|
isVatCurrency: boolean
|
||||||
formattedTotalCost: string
|
formattedTotalCost: string
|
||||||
totalBookingPrice: number
|
totalBookingPrice: number
|
||||||
|
totalBookingCheques: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BookingConfirmationState {
|
export interface BookingConfirmationState extends InitialState {
|
||||||
bookingCode: string | null
|
|
||||||
isVatCurrency: boolean
|
|
||||||
rooms: (Room | null)[]
|
|
||||||
currencyCode: string
|
|
||||||
vat: number
|
|
||||||
fromDate: Date
|
|
||||||
toDate: Date
|
|
||||||
formattedTotalCost: string | null
|
|
||||||
totalBookingPrice: number
|
|
||||||
actions: {
|
actions: {
|
||||||
setRoom: (room: Room, idx: number) => void
|
setRoom: (room: Room, idx: number) => void
|
||||||
setFormattedTotalCost: (updatedFormattedTotalCost: string) => void
|
setFormattedTotalCost: (formattedTotalCost: string) => void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export function formatPrice(
|
|||||||
const localizedAdditionalPrice = intl.formatNumber(additionalPrice, {
|
const localizedAdditionalPrice = intl.formatNumber(additionalPrice, {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
})
|
})
|
||||||
formattedAdditionalPrice = ` ${localizedAdditionalPrice} ${additionalPriceCurrency}`
|
formattedAdditionalPrice = ` + ${localizedAdditionalPrice} ${additionalPriceCurrency}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${localizedPrice} ${currency}${formattedAdditionalPrice}`
|
return `${localizedPrice} ${currency}${formattedAdditionalPrice}`
|
||||||
|
|||||||
Reference in New Issue
Block a user