feat(SW-706): make eslint rule 'formatjs/no-literal-string-in-jsx' pass
This commit is contained in:
@@ -26,7 +26,11 @@ export default function AddToCalendar({
|
||||
createEvent(event, (error, value) => {
|
||||
if (error) {
|
||||
console.error("ICS Error:", error)
|
||||
toast.error(intl.formatMessage({ id: "Failed to add to calendar" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to add to calendar",
|
||||
})
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -42,7 +46,11 @@ export default function AddToCalendar({
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("Download error:", error)
|
||||
toast.error(intl.formatMessage({ id: "Failed to add to calendar" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to add to calendar",
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,11 @@ export default function Alerts({ booking }: BookingConfirmationAlertsProps) {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "Failed to verify membership",
|
||||
defaultMessage: "Failed to verify membership",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "The first or last name doesn't match the membership number you provided. Your booking(s) is confirmed but to get the membership attached you'll need to present your existing membership number upon check-in. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay, or we can assist upon arrival.",
|
||||
defaultMessage:
|
||||
"The first or last name doesn't match the membership number you provided. Your booking(s) is confirmed but to get the membership attached you'll need to present your existing membership number upon check-in. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay, or we can assist upon arrival.",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
@@ -38,10 +39,11 @@ export default function Alerts({ booking }: BookingConfirmationAlertsProps) {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "Failed to verify membership",
|
||||
defaultMessage: "Failed to verify membership",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.",
|
||||
defaultMessage:
|
||||
"Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -15,7 +15,9 @@ export default function AddToCalendarButton({
|
||||
return (
|
||||
<Button intent="text" size="small" theme="base" wrapping onPress={onPress}>
|
||||
<MaterialIcon icon="calendar_add_on" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "Add to calendar" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Add to calendar",
|
||||
})}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@ export default function DownloadInvoice({ mainRef }: DownloadInvoiceProps) {
|
||||
wrapping
|
||||
>
|
||||
<MaterialIcon icon="download" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "Download invoice" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Download invoice",
|
||||
})}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ export default function ManageBooking({ bookingUrl }: ManageBookingProps) {
|
||||
>
|
||||
<Link color="none" href={bookingUrl} weight="bold">
|
||||
<MaterialIcon icon="edit_square" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "Manage booking" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Manage booking",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -32,7 +32,8 @@ export default function Header({
|
||||
|
||||
const text = intl.formatMessage(
|
||||
{
|
||||
id: "Thank you for booking with us! We look forward to welcoming you and hope you have a pleasant stay. If you have any questions or need to make changes to your reservation, please <emailLink>contact us.</emailLink>",
|
||||
defaultMessage:
|
||||
"Thank you for booking with us! We look forward to welcoming you and hope you have a pleasant stay. If you have any questions or need to make changes to your reservation, please <emailLink>contact us.</emailLink>",
|
||||
},
|
||||
{
|
||||
emailLink: (str) => (
|
||||
@@ -68,7 +69,9 @@ export default function Header({
|
||||
<header className={styles.header}>
|
||||
<hgroup className={styles.hgroup}>
|
||||
<Title as="h2" color="red" textTransform="uppercase" type="h2">
|
||||
{intl.formatMessage({ id: "Booking confirmation" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Booking confirmation",
|
||||
})}
|
||||
</Title>
|
||||
<Title as="h2" color="burgundy" textTransform="uppercase" type="h1">
|
||||
{hotel.name}
|
||||
@@ -76,7 +79,9 @@ export default function Header({
|
||||
</hgroup>
|
||||
<Subtitle color="uiTextHighContrast" type="two">
|
||||
{intl.formatMessage(
|
||||
{ id: "Booking number {value}" },
|
||||
{
|
||||
defaultMessage: "Booking number {value}",
|
||||
},
|
||||
{
|
||||
value: booking.confirmationNumber,
|
||||
}
|
||||
|
||||
@@ -18,13 +18,17 @@ export default function HotelDetails({
|
||||
<div className={styles.container}>
|
||||
<div className={styles.details}>
|
||||
<Subtitle color="uiTextHighContrast" type="two">
|
||||
{intl.formatMessage({ id: "Hotel details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Hotel details",
|
||||
})}
|
||||
</Subtitle>
|
||||
<div className={styles.hotel}>
|
||||
<Body color="uiTextHighContrast">{hotel.name}</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "{streetAddress}, {zipCode} {city}" },
|
||||
{
|
||||
defaultMessage: "{streetAddress}, {zipCode} {city}",
|
||||
},
|
||||
{
|
||||
streetAddress: hotel.address.streetAddress,
|
||||
zipCode: hotel.address.zipCode,
|
||||
|
||||
@@ -24,13 +24,17 @@ export default function PaymentDetails() {
|
||||
return (
|
||||
<div className={styles.details}>
|
||||
<Subtitle color="uiTextHighContrast" type="two">
|
||||
{intl.formatMessage({ id: "Payment details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Payment details",
|
||||
})}
|
||||
</Subtitle>
|
||||
<div className={styles.payment}>
|
||||
{hasAllRoomsLoaded ? (
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Total cost: {amount}" },
|
||||
{
|
||||
defaultMessage: "Total cost: {amount}",
|
||||
},
|
||||
{
|
||||
amount: formattedTotalCost,
|
||||
}
|
||||
|
||||
@@ -117,7 +117,9 @@ export default function PriceDetailsModal() {
|
||||
|
||||
const diff = dt(checkOutDate).diff(checkInDate, "days")
|
||||
const nights = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights: diff }
|
||||
)
|
||||
|
||||
@@ -126,11 +128,15 @@ export default function PriceDetailsModal() {
|
||||
${dt(toDate).locale(lang).format("ddd, D MMM")} (${nights})`
|
||||
return (
|
||||
<Modal
|
||||
title={intl.formatMessage({ id: "Price details" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Price details",
|
||||
})}
|
||||
trigger={
|
||||
<Button intent="text">
|
||||
<Caption color="burgundy">
|
||||
{intl.formatMessage({ id: "Price details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price details",
|
||||
})}
|
||||
</Caption>
|
||||
<MaterialIcon icon="chevron_right" color="CurrentColor" size={20} />
|
||||
</Button>
|
||||
@@ -144,7 +150,9 @@ export default function PriceDetailsModal() {
|
||||
{rooms.length > 1 && (
|
||||
<TableSectionHeader
|
||||
title={intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: idx + 1 }
|
||||
)}
|
||||
bold
|
||||
@@ -172,7 +180,9 @@ export default function PriceDetailsModal() {
|
||||
) : null}
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({ id: "Room charge" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Room charge",
|
||||
})}
|
||||
value={room.formattedRoomCost}
|
||||
/>
|
||||
</TableSection>
|
||||
@@ -182,7 +192,8 @@ export default function PriceDetailsModal() {
|
||||
<Row
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
id: "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
|
||||
defaultMessage:
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
|
||||
},
|
||||
{ totalAdults: room.adults, totalBreakfasts: diff }
|
||||
)}
|
||||
@@ -196,7 +207,8 @@ export default function PriceDetailsModal() {
|
||||
<Row
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
id: "Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
||||
defaultMessage:
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
||||
},
|
||||
{
|
||||
totalChildren: room.childrenAges.length,
|
||||
@@ -209,7 +221,7 @@ export default function PriceDetailsModal() {
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({
|
||||
id: "Breakfast charge",
|
||||
defaultMessage: "Breakfast charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
@@ -223,15 +235,26 @@ export default function PriceDetailsModal() {
|
||||
) : null
|
||||
})}
|
||||
<TableSection>
|
||||
<TableSectionHeader title={intl.formatMessage({ id: "Total" })} />
|
||||
<TableSectionHeader
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
/>
|
||||
{isVatCurrency ? (
|
||||
<>
|
||||
<Row
|
||||
label={intl.formatMessage({ id: "Price excluding VAT" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Price excluding VAT",
|
||||
})}
|
||||
value={formatPrice(intl, bookingTotal.priceExVat, currencyCode)}
|
||||
/>
|
||||
<Row
|
||||
label={intl.formatMessage({ id: "VAT {vat}%" }, { vat })}
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "VAT {vat}%",
|
||||
},
|
||||
{ vat }
|
||||
)}
|
||||
value={formatPrice(intl, bookingTotal.vatAmount, currencyCode)}
|
||||
/>
|
||||
</>
|
||||
@@ -239,7 +262,11 @@ export default function PriceDetailsModal() {
|
||||
<tr className={styles.row}>
|
||||
<td>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<span>{intl.formatMessage({ id: "Price including VAT" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
</td>
|
||||
<td className={styles.price}>
|
||||
@@ -257,7 +284,10 @@ export default function PriceDetailsModal() {
|
||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "<strong>Booking code</strong>: {value}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"<strong>Booking code</strong>: {value}",
|
||||
},
|
||||
{
|
||||
value: bookingCode,
|
||||
strong: (text) => (
|
||||
|
||||
@@ -25,20 +25,30 @@ export default function Promos({
|
||||
return (
|
||||
<div className={styles.promos}>
|
||||
<Promo
|
||||
buttonText={intl.formatMessage({ id: "View and buy add-ons" })}
|
||||
buttonText={intl.formatMessage({
|
||||
defaultMessage: "View and buy add-ons",
|
||||
})}
|
||||
href={`${myBookingUrl}?bookingId=${confirmationNumber}&lastName=${lastName}`}
|
||||
text={intl.formatMessage({
|
||||
id: "Discover the little extra touches to make your upcoming stay even more unforgettable.",
|
||||
defaultMessage:
|
||||
"Discover the little extra touches to make your upcoming stay even more unforgettable.",
|
||||
})}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Spice things up",
|
||||
})}
|
||||
title={intl.formatMessage({ id: "Spice things up" })}
|
||||
/>
|
||||
<Promo
|
||||
buttonText={intl.formatMessage({ id: "Book another stay" })}
|
||||
buttonText={intl.formatMessage({
|
||||
defaultMessage: "Book another stay",
|
||||
})}
|
||||
href={`${homeUrl}?hotel=${hotelId}`}
|
||||
text={intl.formatMessage({
|
||||
id: "Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.",
|
||||
defaultMessage:
|
||||
"Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.",
|
||||
})}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Book your next stay",
|
||||
})}
|
||||
title={intl.formatMessage({ id: "Book your next stay" })}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -66,7 +66,10 @@ export default function ReceiptRoom({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.uiTextMediumContrast}>
|
||||
{intl.formatMessage(
|
||||
{ id: "{totalAdults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{
|
||||
totalAdults: room.adults,
|
||||
}
|
||||
@@ -88,7 +91,9 @@ export default function ReceiptRoom({
|
||||
textDecoration="underline"
|
||||
variant="icon"
|
||||
>
|
||||
{intl.formatMessage({ id: "Reservation policy" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Reservation policy",
|
||||
})}
|
||||
<MaterialIcon icon="info" color="CurrentColor" />
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -101,8 +106,12 @@ export default function ReceiptRoom({
|
||||
subtitle={
|
||||
room.rateDefinition.cancellationRule ===
|
||||
CancellationRuleEnum.CancellableBefore6PM
|
||||
? intl.formatMessage({ id: "Pay later" })
|
||||
: intl.formatMessage({ id: "Pay now" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Pay later",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Pay now",
|
||||
})
|
||||
}
|
||||
>
|
||||
<div className={styles.terms}>
|
||||
@@ -161,14 +170,18 @@ export default function ReceiptRoom({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.uiTextHighContrast}>
|
||||
{intl.formatMessage(
|
||||
{ id: "Crib (child) × {count}" },
|
||||
{
|
||||
defaultMessage: "Crib (child) × {count}",
|
||||
},
|
||||
{ count: childBedCrib.quantity }
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p className={styles.uiTextHighContrast}>
|
||||
{intl.formatMessage({ id: "Based on availability" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Based on availability",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -185,7 +198,9 @@ export default function ReceiptRoom({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.uiTextHighContrast}>
|
||||
{intl.formatMessage(
|
||||
{ id: "Extra bed (child) × {count}" },
|
||||
{
|
||||
defaultMessage: "Extra bed (child) × {count}",
|
||||
},
|
||||
{
|
||||
count: childBedExtraBed.quantity,
|
||||
}
|
||||
@@ -203,12 +218,18 @@ export default function ReceiptRoom({
|
||||
{room.breakfast || breakfastIncluded ? (
|
||||
<div className={styles.entry}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{intl.formatMessage({ id: "Breakfast buffet" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Breakfast buffet",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
{breakfastIncluded ? (
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.red}>
|
||||
{intl.formatMessage({ id: "Included" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Included",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
) : null}
|
||||
|
||||
@@ -30,7 +30,11 @@ export default function TotalPrice() {
|
||||
<div className={styles.price}>
|
||||
<div className={styles.entry}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "Total price" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total price",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
{hasAllRoomsLoaded ? (
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
|
||||
@@ -19,7 +19,9 @@ export default function Receipt() {
|
||||
return (
|
||||
<section className={styles.receipt}>
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage({ id: "Booking summary" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Booking summary",
|
||||
})}
|
||||
</Subtitle>
|
||||
|
||||
{rooms.map((room, idx) => (
|
||||
@@ -27,7 +29,9 @@ export default function Receipt() {
|
||||
{rooms.length > 1 ? (
|
||||
<Body color="uiTextHighContrast" textTransform={"bold"}>
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: idx + 1 }
|
||||
)}
|
||||
</Body>
|
||||
|
||||
@@ -13,10 +13,16 @@ export default function Retry({ handleRefetch }: RetryProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<div className={styles.retry}>
|
||||
<Body>{intl.formatMessage({ id: "Something went wrong!" })}</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Something went wrong!",
|
||||
})}
|
||||
</Body>
|
||||
|
||||
<Button size={"small"} onPress={handleRefetch}>
|
||||
{intl.formatMessage({ id: "Try again" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Try again",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -50,7 +50,9 @@ export default function Room({
|
||||
size={20}
|
||||
/>
|
||||
<Caption>
|
||||
{intl.formatMessage({ id: "Membership benefits applied" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Membership benefits applied",
|
||||
})}
|
||||
</Caption>
|
||||
</>
|
||||
) : null}
|
||||
@@ -65,10 +67,15 @@ export default function Room({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
<strong>
|
||||
{intl.formatMessage({ id: "Booking guaranteed." })}
|
||||
</strong>{" "}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Booking guaranteed.",
|
||||
})}
|
||||
</strong>
|
||||
{/* eslint-disable formatjs/no-literal-string-in-jsx */}{" "}
|
||||
{/* eslint-enable formatjs/no-literal-string-in-jsx */}
|
||||
{intl.formatMessage({
|
||||
id: "Your room will remain available for check-in even after 18:00.",
|
||||
defaultMessage:
|
||||
"Your room will remain available for check-in even after 18:00.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -92,7 +99,9 @@ export default function Room({
|
||||
{roomName}
|
||||
</Subtitle>
|
||||
<Link color="burgundy" href="" variant="icon">
|
||||
{intl.formatMessage({ id: "View room details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "View room details",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon="chevron_right"
|
||||
size={20}
|
||||
@@ -103,11 +112,15 @@ export default function Room({
|
||||
<ul className={styles.details}>
|
||||
<li className={styles.listItem}>
|
||||
<Body color="uiTextPlaceholder">
|
||||
{intl.formatMessage({ id: "Check-in" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-in",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "{checkInDate} from {checkInTime}" },
|
||||
{
|
||||
defaultMessage: "{checkInDate} from {checkInTime}",
|
||||
},
|
||||
{
|
||||
checkInDate: fromDate.format("ddd, D MMM"),
|
||||
checkInTime: checkInTime,
|
||||
@@ -117,11 +130,15 @@ export default function Room({
|
||||
</li>
|
||||
<li className={styles.listItem}>
|
||||
<Body color="uiTextPlaceholder">
|
||||
{intl.formatMessage({ id: "Check-out" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-out",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "{checkOutDate} from {checkOutTime}" },
|
||||
{
|
||||
defaultMessage: "{checkOutDate} from {checkOutTime}",
|
||||
},
|
||||
{
|
||||
checkOutDate: toDate.format("ddd, D MMM"),
|
||||
checkOutTime: checkOutTime,
|
||||
@@ -131,7 +148,9 @@ export default function Room({
|
||||
</li>
|
||||
<li className={styles.listItem}>
|
||||
<Body color="uiTextPlaceholder">
|
||||
{intl.formatMessage({ id: "Cancellation policy" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Cancellation policy",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{booking.rateDefinition.cancellationText}
|
||||
@@ -140,11 +159,15 @@ export default function Room({
|
||||
{isFlexBooking || isChangeBooking ? (
|
||||
<li className={styles.listItem}>
|
||||
<Body color="uiTextPlaceholder">
|
||||
{intl.formatMessage({ id: "Rebooking" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Rebooking",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Until {time}, {date}" },
|
||||
{
|
||||
defaultMessage: "Until {time}, {date}",
|
||||
},
|
||||
{ time: "18:00", date: fromDate.format("dddd D MMM") }
|
||||
)}
|
||||
</Body>
|
||||
@@ -153,13 +176,17 @@ export default function Room({
|
||||
</ul>
|
||||
<div className={styles.guest}>
|
||||
<Body color="uiTextPlaceholder">
|
||||
{intl.formatMessage({ id: "Main guest" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Main guest",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">{guestName}</Body>
|
||||
{booking.guest.membershipNumber ? (
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Friend no. {value}" },
|
||||
{
|
||||
defaultMessage: "Friend no. {value}",
|
||||
},
|
||||
{
|
||||
value: booking.guest.membershipNumber,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,12 @@ export default async function Rooms({
|
||||
<div className={styles.room}>
|
||||
{linkedReservations.length ? (
|
||||
<Subtitle color="mainGrey60" type="two">
|
||||
{intl.formatMessage({ id: "Room {roomIndex}" }, { roomIndex: 1 })}
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: 1 }
|
||||
)}
|
||||
</Subtitle>
|
||||
) : null}
|
||||
<Room
|
||||
@@ -38,7 +43,9 @@ export default async function Rooms({
|
||||
<div className={styles.room} key={reservation.confirmationNumber}>
|
||||
<Subtitle color="mainGrey60" type="two">
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: idx + 2 }
|
||||
)}
|
||||
</Subtitle>
|
||||
|
||||
@@ -27,7 +27,9 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
<ul className={styles.contactInfo}>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Address" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Address",
|
||||
})}
|
||||
</Body>
|
||||
<Body>
|
||||
{addressStr}
|
||||
@@ -37,19 +39,25 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
</li>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Driving directions" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Driving directions",
|
||||
})}
|
||||
</Body>
|
||||
<Link
|
||||
href={`https://www.google.com/maps/dir/?api=1&destination=${hotel.location.latitude},${hotel.location.longitude}`}
|
||||
>
|
||||
<span className={styles.link}>
|
||||
{intl.formatMessage({ id: "Google Maps" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Google Maps",
|
||||
})}
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Contact us" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Contact us",
|
||||
})}
|
||||
</Body>
|
||||
<Link href={`tel:${hotel.contactInformation.phoneNumber}`}>
|
||||
<span className={styles.link}>
|
||||
@@ -61,7 +69,9 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
{(hotel.socialMedia.facebook || hotel.socialMedia.instagram) && (
|
||||
<>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Follow us" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Follow us",
|
||||
})}
|
||||
</Body>
|
||||
<div className={styles.soMeIcons}>
|
||||
{hotel.socialMedia.instagram && (
|
||||
@@ -80,7 +90,9 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
</li>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Email" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Email",
|
||||
})}
|
||||
</Body>
|
||||
<Link href={`mailto:${hotel.contactInformation.email}`}>
|
||||
<span className={styles.link}>
|
||||
@@ -96,12 +108,18 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
<Image
|
||||
height={38}
|
||||
width={38}
|
||||
alt={intl.formatMessage({ id: "Nordic Swan Ecolabel" })}
|
||||
alt={intl.formatMessage({
|
||||
defaultMessage: "Nordic Swan Ecolabel",
|
||||
})}
|
||||
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.ecoLabelText}>
|
||||
<span>{intl.formatMessage({ id: "Nordic Swan Ecolabel" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Nordic Swan Ecolabel",
|
||||
})}
|
||||
</span>
|
||||
<span>
|
||||
{hotel.hotelFacts.ecoLabels.svanenEcoLabelCertificateNumber}
|
||||
</span>
|
||||
|
||||
@@ -17,11 +17,12 @@ export default function BedTypeInfo({ hasMultipleBedTypes }: BedTypeInfoProps) {
|
||||
)
|
||||
|
||||
const availabilityText = intl.formatMessage({
|
||||
id: "Your selected bed type will be provided based on availability",
|
||||
defaultMessage:
|
||||
"Your selected bed type will be provided based on availability",
|
||||
})
|
||||
|
||||
const extraBedText = intl.formatMessage({
|
||||
id: "Extra bed will be provided additionally",
|
||||
defaultMessage: "Extra bed will be provided additionally",
|
||||
})
|
||||
|
||||
const combinedStr = `${availabilityText}. ${extraBedText}`
|
||||
|
||||
@@ -72,7 +72,8 @@ export default function Breakfast() {
|
||||
{hasChildrenInRoom ? (
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "Children's breakfast is always free as part of the adult's breakfast.",
|
||||
defaultMessage:
|
||||
"Children's breakfast is always free as part of the adult's breakfast.",
|
||||
})}
|
||||
</Body>
|
||||
) : null}
|
||||
@@ -83,22 +84,29 @@ export default function Breakfast() {
|
||||
name="breakfast"
|
||||
value={pkg.code}
|
||||
Icon={BreakfastBuffetIcon}
|
||||
title={intl.formatMessage({ id: "Breakfast buffet" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Breakfast buffet",
|
||||
})}
|
||||
subtitle={
|
||||
pkg.code === BreakfastPackageEnum.FREE_MEMBER_BREAKFAST
|
||||
? intl.formatMessage({ id: "Included" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Included",
|
||||
})
|
||||
: `+ ${formatPrice(intl, pkg.localPrice.price, pkg.localPrice.currency ?? "")}`
|
||||
}
|
||||
subtitleSecondary={intl.formatMessage({ id: "Per adult/night" })}
|
||||
subtitleSecondary={intl.formatMessage({
|
||||
defaultMessage: "Per adult/night",
|
||||
})}
|
||||
description={
|
||||
hasChildrenInRoom
|
||||
? intl.formatMessage({
|
||||
id: "Free for kids aged 12 and under.",
|
||||
defaultMessage: "Free for kids aged 12 and under.",
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
descriptionSecondary={intl.formatMessage({
|
||||
id: "Includes vegan, gluten-free, and other allergy-friendly options.",
|
||||
defaultMessage:
|
||||
"Includes vegan, gluten-free, and other allergy-friendly options.",
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
@@ -106,15 +114,19 @@ export default function Breakfast() {
|
||||
name="breakfast"
|
||||
value="false"
|
||||
Icon={NoBreakfastBuffetIcon}
|
||||
title={intl.formatMessage({ id: "No breakfast" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "No breakfast",
|
||||
})}
|
||||
subtitle={`+ ${formatPrice(intl, totalPriceForNoBreakfast, packages?.[0].localPrice.currency ?? "")}`}
|
||||
descriptionSecondary={
|
||||
hasChildrenInRoom
|
||||
? intl.formatMessage({
|
||||
id: "Breakfast can be added after booking for an extra cost for adults and kids ages 4 and up.",
|
||||
defaultMessage:
|
||||
"Breakfast can be added after booking for an extra cost for adults and kids ages 4 and up.",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: "Breakfast can be added after booking for an additional fee.",
|
||||
defaultMessage:
|
||||
"Breakfast can be added after booking for an additional fee.",
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -44,7 +44,7 @@ export default function ConfirmBooking({
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Guarantee room for late arrival",
|
||||
defaultMessage: "Guarantee room for late arrival",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -57,27 +57,33 @@ export default function ConfirmBooking({
|
||||
onPress={() => setModalOpen(true)}
|
||||
>
|
||||
<MaterialIcon icon="info" size={20} color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "How does it work" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "How does it work",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
<Modal isOpen={isModalOpen} onToggle={() => setModalOpen(false)}>
|
||||
<div className={styles.modalContainer}>
|
||||
<Typography variant="Title/smRegular">
|
||||
<h3>
|
||||
{intl.formatMessage({ id: "Guarantee for late arrival" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Guarantee for late arrival",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Typography variant="Body/Lead text">
|
||||
<p className={styles.modalText}>
|
||||
{intl.formatMessage({
|
||||
id: "When guaranteeing your booking with a credit card, we will hold the booking until 07:00 the day after check-in.",
|
||||
defaultMessage:
|
||||
"When guaranteeing your booking with a credit card, we will hold the booking until 07:00 the day after check-in.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p className={styles.modalText}>
|
||||
{intl.formatMessage({
|
||||
id: "In case of a no-show, your credit card will be charged for the first night.",
|
||||
defaultMessage:
|
||||
"In case of a no-show, your credit card will be charged for the first night.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -88,7 +94,9 @@ export default function ConfirmBooking({
|
||||
onPress={() => setModalOpen(false)}
|
||||
className={styles.closeButton}
|
||||
>
|
||||
{intl.formatMessage({ id: "Close" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
@@ -97,7 +105,8 @@ export default function ConfirmBooking({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "I may arrive later than 18:00 and want to guarantee my booking with a credit card.",
|
||||
defaultMessage:
|
||||
"I may arrive later than 18:00 and want to guarantee my booking with a credit card.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -108,13 +117,19 @@ export default function ConfirmBooking({
|
||||
<>
|
||||
{savedCreditCards?.length ? (
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h4>{intl.formatMessage({ id: "OTHER" })}</h4>
|
||||
<h4>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "OTHER",
|
||||
})}
|
||||
</h4>
|
||||
</Typography>
|
||||
) : null}
|
||||
<PaymentOption
|
||||
name="paymentMethod"
|
||||
value={PaymentMethodEnum.card}
|
||||
label={intl.formatMessage({ id: "Credit card" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Credit card",
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -134,7 +149,8 @@ export function ConfirmBookingRedemption() {
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "When you confirm the booking the room will be guaranteed for late arrival. If you fail to arrive without cancelling in advance or if you cancel after 18:00 local time, you will be charged for one reward night.",
|
||||
defaultMessage:
|
||||
"When you confirm the booking the room will be guaranteed for late arrival. If you fail to arrive without cancelling in advance or if you cancel after 18:00 local time, you will be charged for one reward night.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -25,14 +25,26 @@ export default function JoinScandicFriendsCard({
|
||||
}
|
||||
|
||||
const list = [
|
||||
{ title: intl.formatMessage({ id: "Earn bonus nights & points" }) },
|
||||
{ title: intl.formatMessage({ id: "Get member benefits & offers" }) },
|
||||
{ title: intl.formatMessage({ id: "Join at no cost" }) },
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Earn bonus nights & points",
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Get member benefits & offers",
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Join at no cost",
|
||||
}),
|
||||
},
|
||||
]
|
||||
|
||||
const saveOnJoiningLabel = intl.formatMessage(
|
||||
{
|
||||
id: "Pay the member price of {amount} for Room {roomNr}",
|
||||
defaultMessage: "Pay the member price of {amount} for Room {roomNr}",
|
||||
},
|
||||
{
|
||||
amount: formatPrice(
|
||||
@@ -53,7 +65,8 @@ export default function JoinScandicFriendsCard({
|
||||
</Caption>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({
|
||||
id: "I promise to join Scandic Friends before checking in",
|
||||
defaultMessage:
|
||||
"I promise to join Scandic Friends before checking in",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
|
||||
@@ -75,42 +75,56 @@ export default function Details() {
|
||||
type="label"
|
||||
className={styles.fullWidth}
|
||||
>
|
||||
{intl.formatMessage({ id: "Guest information" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Guest information",
|
||||
})}
|
||||
</Footnote>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "First name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "First name",
|
||||
})}
|
||||
maxLength={30}
|
||||
name="firstName"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Last name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Last name",
|
||||
})}
|
||||
maxLength={30}
|
||||
name="lastName"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<CountrySelect
|
||||
className={styles.fullWidth}
|
||||
label={intl.formatMessage({ id: "Country" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country",
|
||||
})}
|
||||
name="countryCode"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
className={styles.fullWidth}
|
||||
label={intl.formatMessage({ id: "Email address" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Email address",
|
||||
})}
|
||||
name="email"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Phone
|
||||
className={styles.fullWidth}
|
||||
label={intl.formatMessage({ id: "Phone number" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Phone number",
|
||||
})}
|
||||
name="phoneNumber"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
{guestIsGoingToJoin ? null : (
|
||||
<Input
|
||||
className={styles.fullWidth}
|
||||
label={intl.formatMessage({ id: "Membership no" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Membership no",
|
||||
})}
|
||||
name="membershipNo"
|
||||
type="tel"
|
||||
/>
|
||||
@@ -131,9 +145,13 @@ export default function Details() {
|
||||
type="submit"
|
||||
>
|
||||
{isPaymentNext
|
||||
? intl.formatMessage({ id: "Continue" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Continue",
|
||||
})
|
||||
: intl.formatMessage(
|
||||
{ id: "Continue to room {nextRoomNumber}" },
|
||||
{
|
||||
defaultMessage: "Continue to room {nextRoomNumber}",
|
||||
},
|
||||
{ nextRoomNumber: roomNr + 1 }
|
||||
)}
|
||||
</Button>
|
||||
|
||||
@@ -32,14 +32,26 @@ export default function JoinScandicFriendsCard({
|
||||
}
|
||||
|
||||
const list = [
|
||||
{ title: intl.formatMessage({ id: "Friendly room rates" }) },
|
||||
{ title: intl.formatMessage({ id: "Earn & spend points" }) },
|
||||
{ title: intl.formatMessage({ id: "Join for free" }) },
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Friendly room rates",
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Earn & spend points",
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Join for free",
|
||||
}),
|
||||
},
|
||||
]
|
||||
|
||||
const saveOnJoiningLabel = intl.formatMessage(
|
||||
{
|
||||
id: "Get the member price: {amount}",
|
||||
defaultMessage: "Get the member price: {amount}",
|
||||
},
|
||||
{
|
||||
amount: formatPrice(
|
||||
@@ -62,20 +74,27 @@ export default function JoinScandicFriendsCard({
|
||||
textTransform="uppercase"
|
||||
color="uiTextHighContrast"
|
||||
>
|
||||
{intl.formatMessage({ id: "Join Scandic Friends" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Join Scandic Friends",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
</Checkbox>
|
||||
|
||||
<Footnote color="uiTextHighContrast" className={styles.login}>
|
||||
{intl.formatMessage({ id: "Already a friend?" })}{" "}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${intl.formatMessage({
|
||||
defaultMessage: "Already a friend?",
|
||||
})} `}
|
||||
<LoginButton
|
||||
color="burgundy"
|
||||
position="enter details"
|
||||
trackingId="join-scandic-friends-enter-details"
|
||||
variant="breadcrumb"
|
||||
>
|
||||
{intl.formatMessage({ id: "Log in" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Log in",
|
||||
})}
|
||||
</LoginButton>
|
||||
</Footnote>
|
||||
|
||||
@@ -99,7 +118,8 @@ export default function JoinScandicFriendsCard({
|
||||
<Footnote color="uiTextPlaceholder">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "By signing up you accept the Scandic Friends <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service",
|
||||
defaultMessage:
|
||||
"By signing up you accept the Scandic Friends <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service",
|
||||
},
|
||||
{
|
||||
termsAndConditionsLink: (str) => (
|
||||
|
||||
@@ -42,7 +42,7 @@ export default function MemberPriceModal({
|
||||
<MagicWandIcon width="265px" />
|
||||
<Title as="h3" level="h1" textTransform="regular">
|
||||
{intl.formatMessage({
|
||||
id: "Member price activated",
|
||||
defaultMessage: "Member price activated",
|
||||
})}
|
||||
</Title>
|
||||
|
||||
@@ -50,7 +50,7 @@ export default function MemberPriceModal({
|
||||
<span className={styles.newPrice}>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "The new price is",
|
||||
defaultMessage: "The new price is",
|
||||
})}
|
||||
</Body>
|
||||
<Subtitle type="two" color="red">
|
||||
@@ -64,7 +64,9 @@ export default function MemberPriceModal({
|
||||
)}
|
||||
</div>
|
||||
<Button intent="primary" theme="base" onClick={() => setIsOpen(false)}>
|
||||
{intl.formatMessage({ id: "OK" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "OK",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@@ -27,14 +27,18 @@ export default function Signup({ name }: { name: string }) {
|
||||
<div className={styles.additionalFormData}>
|
||||
<Input
|
||||
name="zipCode"
|
||||
label={intl.formatMessage({ id: "Zip code" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Zip code",
|
||||
})}
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<div className={styles.dateField}>
|
||||
<header>
|
||||
<Caption type="bold">
|
||||
<span className={styles.required}>
|
||||
{intl.formatMessage({ id: "Birth date" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Birth date",
|
||||
})}
|
||||
</span>
|
||||
</Caption>
|
||||
</header>
|
||||
@@ -43,7 +47,9 @@ export default function Signup({ name }: { name: string }) {
|
||||
</div>
|
||||
) : (
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Membership no" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Membership no",
|
||||
})}
|
||||
name="membershipNo"
|
||||
type="tel"
|
||||
/>
|
||||
|
||||
@@ -93,17 +93,23 @@ export default function Details({ user }: DetailsProps) {
|
||||
type="label"
|
||||
className={styles.fullWidth}
|
||||
>
|
||||
{intl.formatMessage({ id: "Guest information" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Guest information",
|
||||
})}
|
||||
</Footnote>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "First name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "First name",
|
||||
})}
|
||||
maxLength={30}
|
||||
name="firstName"
|
||||
readOnly={!!user}
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Last name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Last name",
|
||||
})}
|
||||
maxLength={30}
|
||||
name="lastName"
|
||||
readOnly={!!user}
|
||||
@@ -111,21 +117,27 @@ export default function Details({ user }: DetailsProps) {
|
||||
/>
|
||||
<CountrySelect
|
||||
className={styles.fullWidth}
|
||||
label={intl.formatMessage({ id: "Country" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country",
|
||||
})}
|
||||
name="countryCode"
|
||||
readOnly={!!user}
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
className={styles.fullWidth}
|
||||
label={intl.formatMessage({ id: "Email address" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Email address",
|
||||
})}
|
||||
name="email"
|
||||
readOnly={!!user}
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Phone
|
||||
className={styles.fullWidth}
|
||||
label={intl.formatMessage({ id: "Phone number" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Phone number",
|
||||
})}
|
||||
name="phoneNumber"
|
||||
readOnly={!!user}
|
||||
registerOptions={{ required: true }}
|
||||
@@ -151,9 +163,13 @@ export default function Details({ user }: DetailsProps) {
|
||||
type="submit"
|
||||
>
|
||||
{isPaymentNext
|
||||
? intl.formatMessage({ id: "Continue" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Continue",
|
||||
})
|
||||
: intl.formatMessage(
|
||||
{ id: "Continue to room {nextRoomNumber}" },
|
||||
{
|
||||
defaultMessage: "Continue to room {nextRoomNumber}",
|
||||
},
|
||||
{ nextRoomNumber: roomNr + 1 }
|
||||
)}
|
||||
</Button>
|
||||
|
||||
@@ -27,7 +27,9 @@ export default function SpecialRequests() {
|
||||
className={styles.header}
|
||||
textAlign="left"
|
||||
>
|
||||
{intl.formatMessage({ id: "Special requests" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Special requests",
|
||||
})}
|
||||
</Footnote>
|
||||
<MaterialIcon icon="keyboard_arrow_down" className={styles.chevron} />
|
||||
<Divider className={styles.divider} color="subtle" />
|
||||
@@ -74,7 +76,8 @@ export default function SpecialRequests() {
|
||||
/> */}
|
||||
<TextArea
|
||||
label={intl.formatMessage({
|
||||
id: "Is there anything else you would like us to know before your arrival?",
|
||||
defaultMessage:
|
||||
"Is there anything else you would like us to know before your arrival?",
|
||||
})}
|
||||
name="specialRequest.comment"
|
||||
/>
|
||||
|
||||
@@ -29,7 +29,9 @@ export default function ToggleSidePeek({
|
||||
wrapping
|
||||
className={styles.toggle}
|
||||
>
|
||||
{intl.formatMessage({ id: "See hotel details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={14} color="Icon/Inverted" />
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -35,10 +35,13 @@ export default async function HotelHeader({
|
||||
</Title>
|
||||
<div className={styles.address}>
|
||||
<Caption color="white">{addressStr}</Caption>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Caption color="white">∙</Caption>
|
||||
<Caption color="white">
|
||||
{intl.formatMessage(
|
||||
{ id: "{number} km to city center" },
|
||||
{
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
number: getSingleDecimal(
|
||||
hotel.location.distanceToCentre / 1000
|
||||
|
||||
@@ -13,7 +13,9 @@ export default function GuaranteeDetails() {
|
||||
<details>
|
||||
<Caption color="burgundy" type="bold" asChild>
|
||||
<summary className={styles.summary}>
|
||||
{intl.formatMessage({ id: "How it works" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "How it works",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon="keyboard_arrow_down"
|
||||
color="Icon/Interactive/Default"
|
||||
@@ -24,29 +26,35 @@ export default function GuaranteeDetails() {
|
||||
<section className={styles.content}>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "When guaranteeing your booking, we will hold the booking until 07:00 until the day after check-in. This will provide you as a guest with added flexibility for check-in times.",
|
||||
defaultMessage:
|
||||
"When guaranteeing your booking, we will hold the booking until 07:00 until the day after check-in. This will provide you as a guest with added flexibility for check-in times.",
|
||||
})}
|
||||
</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "What you have to do to guarantee booking:",
|
||||
defaultMessage: "What you have to do to guarantee booking:",
|
||||
})}
|
||||
</Body>
|
||||
<ol>
|
||||
<Body asChild>
|
||||
<li>{intl.formatMessage({ id: "Complete the booking" })}</li>
|
||||
<li>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Complete the booking",
|
||||
})}
|
||||
</li>
|
||||
</Body>
|
||||
<Body asChild>
|
||||
<li>
|
||||
{intl.formatMessage({
|
||||
id: "Provide a payment card in the next step",
|
||||
defaultMessage: "Provide a payment card in the next step",
|
||||
})}
|
||||
</li>
|
||||
</Body>
|
||||
</ol>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "Please note that this is mandatory, and that your card will only be charged in the event of a no-show.",
|
||||
defaultMessage:
|
||||
"Please note that this is mandatory, and that your card will only be charged in the event of a no-show.",
|
||||
})}
|
||||
</Body>
|
||||
</section>
|
||||
|
||||
@@ -34,8 +34,12 @@ export default function MixedRatePaymentBreakdown({
|
||||
currency,
|
||||
}: MixedRatePaymentBreakdownProps) {
|
||||
const intl = useIntl()
|
||||
const payNowTitle = intl.formatMessage({ id: "Pay now" })
|
||||
const payAtCheckInTitle = intl.formatMessage({ id: "Pay at check-in" })
|
||||
const payNowTitle = intl.formatMessage({
|
||||
defaultMessage: "Pay now",
|
||||
})
|
||||
const payAtCheckInTitle = intl.formatMessage({
|
||||
defaultMessage: "Pay at check-in",
|
||||
})
|
||||
|
||||
const initialState: PaymentBreakdownState = {
|
||||
roomsWithPrepaidRate: [],
|
||||
@@ -114,11 +118,15 @@ function PaymentCard({
|
||||
textTransform="uppercase"
|
||||
className={styles.cardTitle}
|
||||
>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{title}{" "}
|
||||
<span>
|
||||
/{" "}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{"/ "}
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{
|
||||
roomIndex: roomIndexes.map((idx) => idx + 1).join(" & "),
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { PAYMENT_METHOD_TITLES ,type PaymentMethodEnum } from "@/constants/booking"
|
||||
import {
|
||||
PAYMENT_METHOD_TITLES,
|
||||
type PaymentMethodEnum,
|
||||
} from "@/constants/booking"
|
||||
|
||||
import PaymentOption from "../PaymentOption"
|
||||
|
||||
@@ -20,7 +23,11 @@ export default function MySavedCards({ savedCreditCards }: MySavedCardsProps) {
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h4>{intl.formatMessage({ id: "MY SAVED CARDS" })}</h4>
|
||||
<h4>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "MY SAVED CARDS",
|
||||
})}
|
||||
</h4>
|
||||
</Typography>
|
||||
<div className={styles.paymentOptionContainer}>
|
||||
{savedCreditCards?.map((savedCreditCard) => (
|
||||
|
||||
@@ -34,11 +34,12 @@ function useBookingErrorAlert() {
|
||||
switch (errorCode) {
|
||||
case BookingErrorCodeEnum.TransactionCancelled:
|
||||
return intl.formatMessage({
|
||||
id: "You have now cancelled your payment.",
|
||||
defaultMessage: "You have now cancelled your payment.",
|
||||
})
|
||||
default:
|
||||
return intl.formatMessage({
|
||||
id: "We had an issue processing your booking. Please try again. No charges have been made.",
|
||||
defaultMessage:
|
||||
"We had an issue processing your booking. Please try again. No charges have been made.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,15 @@ export default function TimeoutSpinner() {
|
||||
<div className={styles.container}>
|
||||
<LoadingSpinner />
|
||||
<Subtitle className={styles.heading}>
|
||||
{intl.formatMessage({ id: "Taking longer than usual" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Taking longer than usual",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Body textAlign="center" className={styles.messageContainer}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "We are still confirming your booking. This is usually a matter of minutes and we do apologise for the wait. Please check your inbox for a booking confirmation email and if you still haven't received it by end of day, please contact our <link>customer support</link>.",
|
||||
defaultMessage:
|
||||
"We are still confirming your booking. This is usually a matter of minutes and we do apologise for the wait. Please check your inbox for a booking confirmation email and if you still haven't received it by end of day, please contact our <link>customer support</link>.",
|
||||
},
|
||||
{
|
||||
link: (text) => (
|
||||
|
||||
@@ -433,13 +433,13 @@ export default function PaymentClient({
|
||||
}
|
||||
|
||||
const paymentGuarantee = intl.formatMessage({
|
||||
id: "Payment Guarantee",
|
||||
defaultMessage: "Payment Guarantee",
|
||||
})
|
||||
const payment = intl.formatMessage({
|
||||
id: "Payment",
|
||||
defaultMessage: "Payment",
|
||||
})
|
||||
const confirm = intl.formatMessage({
|
||||
id: "Confirm booking",
|
||||
defaultMessage: "Confirm booking",
|
||||
})
|
||||
|
||||
return (
|
||||
@@ -472,7 +472,8 @@ export default function PaymentClient({
|
||||
<section className={styles.section}>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.",
|
||||
defaultMessage:
|
||||
"To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.",
|
||||
})}
|
||||
</Body>
|
||||
<GuaranteeDetails />
|
||||
@@ -482,7 +483,8 @@ export default function PaymentClient({
|
||||
{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.",
|
||||
defaultMessage:
|
||||
"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}
|
||||
@@ -496,14 +498,18 @@ export default function PaymentClient({
|
||||
<section className={styles.section}>
|
||||
{savedCreditCards?.length ? (
|
||||
<Body color="uiTextHighContrast" textTransform="bold">
|
||||
{intl.formatMessage({ id: "OTHER PAYMENT METHODS" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "OTHER PAYMENT METHODS",
|
||||
})}
|
||||
</Body>
|
||||
) : null}
|
||||
<div className={styles.paymentOptionContainer}>
|
||||
<PaymentOption
|
||||
name="paymentMethod"
|
||||
value={PaymentMethodEnum.card}
|
||||
label={intl.formatMessage({ id: "Credit card" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Credit card",
|
||||
})}
|
||||
/>
|
||||
{!hasMixedRates &&
|
||||
availablePaymentOptions.map((paymentMethod) => (
|
||||
@@ -542,7 +548,9 @@ export default function PaymentClient({
|
||||
!methods.formState.isValid || methods.formState.isSubmitting
|
||||
}
|
||||
>
|
||||
{intl.formatMessage({ id: "Complete booking" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Complete booking",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -39,7 +39,10 @@ export default function PaymentOption({
|
||||
<Body>{label}</Body>
|
||||
</div>
|
||||
{cardNumber ? (
|
||||
<Caption color="uiTextMediumContrast">•••• {cardNumber}</Caption>
|
||||
<>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Caption color="uiTextMediumContrast">•••• {cardNumber}</Caption>
|
||||
</>
|
||||
) : (
|
||||
<Image
|
||||
className={styles.paymentOptionIcon}
|
||||
|
||||
@@ -21,7 +21,8 @@ export default function TermsAndConditions() {
|
||||
<Caption>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "By paying with any of the payment methods available, I accept the terms for this booking and the general <termsAndConditionsLink>Terms & Conditions</termsAndConditionsLink>, and understand that Scandic will process my personal data for this booking in accordance with <privacyPolicyLink>Scandic's Privacy policy</privacyPolicyLink>. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.",
|
||||
defaultMessage:
|
||||
"By paying with any of the payment methods available, I accept the terms for this booking and the general <termsAndConditionsLink>Terms & Conditions</termsAndConditionsLink>, and understand that Scandic will process my personal data for this booking in accordance with <privacyPolicyLink>Scandic's Privacy policy</privacyPolicyLink>. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.",
|
||||
},
|
||||
{
|
||||
termsAndConditionsLink: (str) => (
|
||||
@@ -54,14 +55,15 @@ export default function TermsAndConditions() {
|
||||
<Checkbox name="termsAndConditions">
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
id: "I accept the terms and conditions",
|
||||
defaultMessage: "I accept the terms and conditions",
|
||||
})}
|
||||
</Caption>
|
||||
</Checkbox>
|
||||
<Checkbox name="smsConfirmation">
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
id: "I would like to get my booking confirmation via sms",
|
||||
defaultMessage:
|
||||
"I would like to get my booking confirmation via sms",
|
||||
})}
|
||||
</Caption>
|
||||
</Checkbox>
|
||||
|
||||
@@ -50,7 +50,9 @@ export default function PriceChangeSummary({
|
||||
wrapping
|
||||
onClick={() => toggleOpen((isOpen) => !isOpen)}
|
||||
>
|
||||
{intl.formatMessage({ id: "See price details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See price details",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Button>
|
||||
<ModalOverlay isOpen={isOpen} onOpenChange={toggleOpen}>
|
||||
@@ -60,7 +62,9 @@ export default function PriceChangeSummary({
|
||||
<div className={styles.content}>
|
||||
<header className={styles.header}>
|
||||
<Subtitle>
|
||||
{intl.formatMessage({ id: "Price details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price details",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Button
|
||||
onPress={close}
|
||||
@@ -82,15 +86,21 @@ export default function PriceChangeSummary({
|
||||
<Body textTransform="bold">
|
||||
{rooms.length > 1
|
||||
? intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: roomNumber }
|
||||
)
|
||||
: intl.formatMessage({ id: "Room" })}
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Room",
|
||||
})}
|
||||
</Body>
|
||||
<Body>{room.roomType}</Body>
|
||||
<div className={styles.priceRow}>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Room charge" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Room charge",
|
||||
})}
|
||||
</Caption>
|
||||
{newPrice ? (
|
||||
<div className={styles.updatedPrice}>
|
||||
@@ -126,7 +136,7 @@ export default function PriceChangeSummary({
|
||||
<div className={styles.priceRow}>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({
|
||||
id: "Breakfast charge",
|
||||
defaultMessage: "Breakfast charge",
|
||||
})}
|
||||
</Caption>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
@@ -164,10 +174,16 @@ export default function PriceChangeSummary({
|
||||
})}
|
||||
</div>
|
||||
<div className={styles.rowContainer}>
|
||||
<Body>{intl.formatMessage({ id: "Total" })}</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
</Body>
|
||||
<div className={styles.priceRow}>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Price including VAT" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})}
|
||||
</Body>
|
||||
<Body textTransform="bold">
|
||||
{formatPrice(
|
||||
@@ -181,10 +197,14 @@ export default function PriceChangeSummary({
|
||||
</section>
|
||||
<footer className={styles.footer}>
|
||||
<Button intent="secondary" onClick={onCancel}>
|
||||
{intl.formatMessage({ id: "Back to select room" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Back to select room",
|
||||
})}
|
||||
</Button>
|
||||
<Button onClick={onAccept}>
|
||||
{intl.formatMessage({ id: "Continue with new price" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Continue with new price",
|
||||
})}
|
||||
</Button>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,9 @@ export default function PriceChangeDialog({
|
||||
onAccept,
|
||||
}: PriceChangeDialogProps) {
|
||||
const intl = useIntl()
|
||||
const title = intl.formatMessage({ id: "Price change" })
|
||||
const title = intl.formatMessage({
|
||||
defaultMessage: "Price change",
|
||||
})
|
||||
const rooms = useEnterDetailsStore((state) => state.rooms)
|
||||
|
||||
const { newTotalPrice, roomPrices } = rooms.reduce<PriceDetailsState>(
|
||||
@@ -66,6 +68,25 @@ export default function PriceChangeDialog({
|
||||
{ newTotalPrice: 0, roomPrices: [] }
|
||||
)
|
||||
|
||||
const roomSelectionMsg = intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{totalRooms, plural, one {room} other {rooms}}",
|
||||
},
|
||||
{
|
||||
totalRooms: rooms.length,
|
||||
}
|
||||
)
|
||||
|
||||
const newRoomSelectionMsg = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalRooms, plural, one {a new room} other {new rooms}}",
|
||||
},
|
||||
{
|
||||
totalRooms: rooms.length,
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<ModalOverlay
|
||||
className={styles.overlay}
|
||||
@@ -93,14 +114,21 @@ export default function PriceChangeDialog({
|
||||
<Body textAlign="center">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "Prices have increased since you selected your {totalRooms, plural, one {room} other {rooms}}.{br} To continue your booking, accept the updated price,{br} or go back to select {totalRooms, plural, one {a new room} other {new rooms}}.",
|
||||
defaultMessage:
|
||||
"Prices have increased since you selected your {roomSelection}.{linebreak} To continue your booking, accept the updated price,{linebreak} or go back to select {newRoomSelection}.",
|
||||
},
|
||||
{ totalRooms: rooms.length, br: <br /> }
|
||||
{
|
||||
roomSelection: roomSelectionMsg,
|
||||
newRoomSelection: newRoomSelectionMsg,
|
||||
linebreak: <br />,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
<div>
|
||||
<Subtitle textAlign="center" color="burgundy">
|
||||
{intl.formatMessage({ id: "New total" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "New total",
|
||||
})}
|
||||
</Subtitle>
|
||||
<div className={styles.prices}>
|
||||
<Caption striked>
|
||||
@@ -121,10 +149,14 @@ export default function PriceChangeDialog({
|
||||
</header>
|
||||
<footer className={styles.footer}>
|
||||
<Button intent="secondary" onClick={onCancel}>
|
||||
{intl.formatMessage({ id: "Back to select room" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Back to select room",
|
||||
})}
|
||||
</Button>
|
||||
<Button onClick={onAccept}>
|
||||
{intl.formatMessage({ id: "Continue with new price" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Continue with new price",
|
||||
})}
|
||||
</Button>
|
||||
</footer>
|
||||
</Dialog>
|
||||
|
||||
@@ -46,7 +46,9 @@ export default function Multiroom() {
|
||||
<Header>
|
||||
<Title level="h2" as="h4">
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{
|
||||
roomIndex: roomNr,
|
||||
}
|
||||
@@ -58,8 +60,12 @@ export default function Multiroom() {
|
||||
|
||||
{room.bedTypes ? (
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Select bed" })}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
header={intl.formatMessage({
|
||||
defaultMessage: "Select bed",
|
||||
})}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Request bedtype",
|
||||
})}
|
||||
step={StepEnum.selectBed}
|
||||
disabled={!arePreviousRoomsValid}
|
||||
>
|
||||
@@ -69,9 +75,11 @@ export default function Multiroom() {
|
||||
|
||||
{showBreakfastStep ? (
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Food options" })}
|
||||
header={intl.formatMessage({
|
||||
defaultMessage: "Food options",
|
||||
})}
|
||||
label={intl.formatMessage({
|
||||
id: "Select breakfast options",
|
||||
defaultMessage: "Select breakfast options",
|
||||
})}
|
||||
step={StepEnum.breakfast}
|
||||
disabled={isBreakfastDisabled}
|
||||
@@ -81,9 +89,13 @@ export default function Multiroom() {
|
||||
) : null}
|
||||
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Details" })}
|
||||
header={intl.formatMessage({
|
||||
defaultMessage: "Details",
|
||||
})}
|
||||
step={StepEnum.details}
|
||||
label={intl.formatMessage({ id: "Enter your details" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Enter your details",
|
||||
})}
|
||||
disabled={isDetailsDisabled}
|
||||
>
|
||||
<Details />
|
||||
|
||||
@@ -31,7 +31,9 @@ export default function RoomOne({ user }: { user: SafeUser }) {
|
||||
<Header>
|
||||
<Title level="h2" as="h4">
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{
|
||||
roomIndex: 1,
|
||||
}
|
||||
@@ -44,8 +46,12 @@ export default function RoomOne({ user }: { user: SafeUser }) {
|
||||
|
||||
{room.bedTypes ? (
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Select bed" })}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
header={intl.formatMessage({
|
||||
defaultMessage: "Select bed",
|
||||
})}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Request bedtype",
|
||||
})}
|
||||
step={StepEnum.selectBed}
|
||||
>
|
||||
<BedType />
|
||||
@@ -54,9 +60,11 @@ export default function RoomOne({ user }: { user: SafeUser }) {
|
||||
|
||||
{showBreakfastStep ? (
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Food options" })}
|
||||
header={intl.formatMessage({
|
||||
defaultMessage: "Food options",
|
||||
})}
|
||||
label={intl.formatMessage({
|
||||
id: "Select breakfast options",
|
||||
defaultMessage: "Select breakfast options",
|
||||
})}
|
||||
step={StepEnum.breakfast}
|
||||
disabled={!steps[StepEnum.selectBed].isValid}
|
||||
@@ -66,9 +74,13 @@ export default function RoomOne({ user }: { user: SafeUser }) {
|
||||
) : null}
|
||||
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Details" })}
|
||||
header={intl.formatMessage({
|
||||
defaultMessage: "Details",
|
||||
})}
|
||||
step={StepEnum.details}
|
||||
label={intl.formatMessage({ id: "Enter your details" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Enter your details",
|
||||
})}
|
||||
disabled={
|
||||
!(
|
||||
steps[StepEnum.selectBed].isValid &&
|
||||
|
||||
@@ -26,8 +26,12 @@ export default function Section({
|
||||
|
||||
const [title, setTitle] = useState(label)
|
||||
|
||||
const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" })
|
||||
const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" })
|
||||
const noBreakfastTitle = intl.formatMessage({
|
||||
defaultMessage: "No breakfast",
|
||||
})
|
||||
const breakfastTitle = intl.formatMessage({
|
||||
defaultMessage: "Breakfast buffet",
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (step === StepEnum.selectBed && bedType) {
|
||||
|
||||
@@ -31,7 +31,11 @@ export default function ToggleSidePeek({
|
||||
intent={intent}
|
||||
wrapping
|
||||
>
|
||||
{title ? title : intl.formatMessage({ id: "See room details" })}
|
||||
{title
|
||||
? title
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "See room details",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={14} color="CurrentColor" />
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -51,7 +51,11 @@ export default function SelectedRoom() {
|
||||
type="label"
|
||||
color="uiTextHighContrast"
|
||||
>
|
||||
<h2>{intl.formatMessage({ id: "Your room" })}</h2>
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Your room",
|
||||
})}
|
||||
</h2>
|
||||
</Footnote>
|
||||
<Subtitle
|
||||
type="two"
|
||||
@@ -59,7 +63,9 @@ export default function SelectedRoom() {
|
||||
color="uiTextHighContrast"
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "{roomType} <rate>{rateDescription}</rate>" },
|
||||
{
|
||||
defaultMessage: "{roomType} <rate>{rateDescription}</rate>",
|
||||
},
|
||||
{
|
||||
roomType: room.roomType,
|
||||
rateDescription: room.cancellationText,
|
||||
@@ -78,7 +84,9 @@ export default function SelectedRoom() {
|
||||
>
|
||||
<MaterialIcon icon="edit_square" color="CurrentColor" />
|
||||
<Caption color="burgundy" type="bold">
|
||||
{intl.formatMessage({ id: "Change room" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Change room",
|
||||
})}
|
||||
</Caption>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -55,7 +55,11 @@ export default function SummaryBottomSheet({ children }: PropsWithChildren) {
|
||||
onClick={toggleSummaryOpen}
|
||||
className={styles.priceDetailsButton}
|
||||
>
|
||||
<Caption>{intl.formatMessage({ id: "Total price" })}</Caption>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total price",
|
||||
})}
|
||||
</Caption>
|
||||
<Subtitle>
|
||||
{formatPrice(
|
||||
intl,
|
||||
@@ -66,7 +70,9 @@ export default function SummaryBottomSheet({ children }: PropsWithChildren) {
|
||||
)}
|
||||
</Subtitle>
|
||||
<Caption color="baseTextHighContrast" type="underline">
|
||||
{intl.formatMessage({ id: "See details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See details",
|
||||
})}
|
||||
</Caption>
|
||||
</button>
|
||||
<Button
|
||||
@@ -77,7 +83,9 @@ export default function SummaryBottomSheet({ children }: PropsWithChildren) {
|
||||
disabled={isSubmittingDisabled}
|
||||
form={formId}
|
||||
>
|
||||
{intl.formatMessage({ id: "Complete booking" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Complete booking",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -99,7 +99,9 @@ export default function PriceDetailsTable({
|
||||
|
||||
const diff = dt(toDate).diff(fromDate, "days")
|
||||
const nights = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights: diff }
|
||||
)
|
||||
const vatPercentage = vat / 100
|
||||
@@ -152,7 +154,14 @@ export default function PriceDetailsTable({
|
||||
<tr>
|
||||
<th colSpan={2}>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Room" })} {idx + 1}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Room",
|
||||
})}
|
||||
{
|
||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||
" "
|
||||
}
|
||||
{idx + 1}
|
||||
</Body>
|
||||
</th>
|
||||
</tr>
|
||||
@@ -162,7 +171,7 @@ export default function PriceDetailsTable({
|
||||
<>
|
||||
<Row
|
||||
label={intl.formatMessage({
|
||||
id: "Average price per night",
|
||||
defaultMessage: "Average price per night",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
@@ -191,7 +200,9 @@ export default function PriceDetailsTable({
|
||||
) : null}
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({ id: "Room charge" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Room charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
price.localPrice.pricePerStay,
|
||||
@@ -203,7 +214,9 @@ export default function PriceDetailsTable({
|
||||
{voucherPrice && (
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({ id: "Room charge" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Room charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
voucherPrice.numberOfVouchers,
|
||||
@@ -214,7 +227,9 @@ export default function PriceDetailsTable({
|
||||
{chequePrice && (
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({ id: "Room charge" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Room charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
chequePrice.localPrice.numberOfCheques,
|
||||
@@ -227,7 +242,9 @@ export default function PriceDetailsTable({
|
||||
{redemptionPrice && (
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({ id: "Room charge" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Room charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
redemptionPrice.localPrice.pointsPerStay,
|
||||
@@ -244,7 +261,8 @@ export default function PriceDetailsTable({
|
||||
<Row
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
id: "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
|
||||
defaultMessage:
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
|
||||
},
|
||||
{ totalAdults: room.adults, totalBreakfasts: diff }
|
||||
)}
|
||||
@@ -258,7 +276,8 @@ export default function PriceDetailsTable({
|
||||
<Row
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
id: "Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
||||
defaultMessage:
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
||||
},
|
||||
{
|
||||
totalChildren: room.childrenInRoom.length,
|
||||
@@ -275,7 +294,7 @@ export default function PriceDetailsTable({
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({
|
||||
id: "Breakfast charge",
|
||||
defaultMessage: "Breakfast charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
@@ -289,15 +308,26 @@ export default function PriceDetailsTable({
|
||||
)
|
||||
})}
|
||||
<TableSection>
|
||||
<TableSectionHeader title={intl.formatMessage({ id: "Total" })} />
|
||||
<TableSectionHeader
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
/>
|
||||
{!noVatCurrencies.includes(totalPrice.local.currency) ? (
|
||||
<>
|
||||
<Row
|
||||
label={intl.formatMessage({ id: "Price excluding VAT" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Price excluding VAT",
|
||||
})}
|
||||
value={formatPrice(intl, priceExclVat, totalPrice.local.currency)}
|
||||
/>
|
||||
<Row
|
||||
label={intl.formatMessage({ id: "VAT {vat}%" }, { vat })}
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "VAT {vat}%",
|
||||
},
|
||||
{ vat }
|
||||
)}
|
||||
value={formatPrice(intl, vatAmount, totalPrice.local.currency)}
|
||||
/>
|
||||
</>
|
||||
@@ -305,7 +335,9 @@ export default function PriceDetailsTable({
|
||||
<tr className={styles.row}>
|
||||
<td>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Price including VAT" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})}
|
||||
</Body>
|
||||
</td>
|
||||
<td className={styles.price}>
|
||||
@@ -343,7 +375,9 @@ export default function PriceDetailsTable({
|
||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "<strong>Booking code</strong>: {value}" },
|
||||
{
|
||||
defaultMessage: "<strong>Booking code</strong>: {value}",
|
||||
},
|
||||
{
|
||||
value: bookingCode,
|
||||
strong: (text) => (
|
||||
|
||||
@@ -51,7 +51,9 @@ export default function SummaryUI({
|
||||
const diff = dt(booking.toDate).diff(booking.fromDate, "days")
|
||||
|
||||
const nights = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights: diff }
|
||||
)
|
||||
|
||||
@@ -97,7 +99,9 @@ export default function SummaryUI({
|
||||
<section className={styles.summary}>
|
||||
<header className={styles.header}>
|
||||
<Subtitle className={styles.title} type="two">
|
||||
{intl.formatMessage({ id: "Booking summary" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Booking summary",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Body className={styles.date} color="baseTextMediumContrast">
|
||||
{dt(booking.fromDate).locale(lang).format("ddd, D MMM")}
|
||||
@@ -106,6 +110,7 @@ export default function SummaryUI({
|
||||
color="Icon/Interactive/Secondary"
|
||||
size={15}
|
||||
/>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{dt(booking.toDate).locale(lang).format("ddd, D MMM")} ({nights})
|
||||
</Body>
|
||||
<Button
|
||||
@@ -156,7 +161,10 @@ export default function SummaryUI({
|
||||
const showMemberPrice = !!(isOrWillBecomeMember && memberPrice)
|
||||
|
||||
const adultsMsg = intl.formatMessage(
|
||||
{ id: "{totalAdults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{ totalAdults: adults }
|
||||
)
|
||||
|
||||
@@ -164,7 +172,8 @@ export default function SummaryUI({
|
||||
if (childrenInRoom?.length) {
|
||||
const childrenMsg = intl.formatMessage(
|
||||
{
|
||||
id: "{totalChildren, plural, one {# child} other {# children}}",
|
||||
defaultMessage:
|
||||
"{totalChildren, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{ totalChildren: childrenInRoom.length }
|
||||
)
|
||||
@@ -185,7 +194,9 @@ export default function SummaryUI({
|
||||
{rooms.length > 1 ? (
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{
|
||||
roomIndex: roomNumber,
|
||||
}
|
||||
@@ -223,7 +234,9 @@ export default function SummaryUI({
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
wrapping={false}
|
||||
>
|
||||
{intl.formatMessage({ id: "Rate details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Rate details",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon="chevron_right"
|
||||
size={20}
|
||||
@@ -296,12 +309,16 @@ export default function SummaryUI({
|
||||
<div>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Crib (child) × {count}" },
|
||||
{
|
||||
defaultMessage: "Crib (child) × {count}",
|
||||
},
|
||||
{ count: childBedCrib }
|
||||
)}
|
||||
</Body>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Based on availability" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Based on availability",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
<Body color="uiTextHighContrast">
|
||||
@@ -318,7 +335,9 @@ export default function SummaryUI({
|
||||
<div>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Extra bed (child) × {count}" },
|
||||
{
|
||||
defaultMessage: "Extra bed (child) × {count}",
|
||||
},
|
||||
{
|
||||
count: childBedExtraBed,
|
||||
}
|
||||
@@ -337,13 +356,17 @@ export default function SummaryUI({
|
||||
{room.breakfastIncluded ? (
|
||||
<div className={styles.entry}>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Breakfast included" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Breakfast included",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
) : room.breakfast === false ? (
|
||||
<div className={styles.entry}>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "No breakfast" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "No breakfast",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{formatPrice(
|
||||
@@ -357,13 +380,16 @@ export default function SummaryUI({
|
||||
{room.breakfast ? (
|
||||
<div>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Breakfast buffet" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Breakfast buffet",
|
||||
})}
|
||||
</Body>
|
||||
<div className={styles.entry}>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
defaultMessage:
|
||||
"{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{ totalAdults: adults }
|
||||
)}
|
||||
@@ -381,7 +407,8 @@ export default function SummaryUI({
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "{totalChildren, plural, one {# child} other {# children}}",
|
||||
defaultMessage:
|
||||
"{totalChildren, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{ totalChildren: childrenInRoom.length }
|
||||
)}
|
||||
@@ -407,7 +434,9 @@ export default function SummaryUI({
|
||||
<div>
|
||||
<Body>
|
||||
{intl.formatMessage(
|
||||
{ id: "<b>Total price</b> (incl VAT)" },
|
||||
{
|
||||
defaultMessage: "<b>Total price</b> (incl VAT)",
|
||||
},
|
||||
{ b: (str) => <b>{str}</b> }
|
||||
)}
|
||||
</Body>
|
||||
@@ -445,7 +474,9 @@ export default function SummaryUI({
|
||||
{totalPrice.requested && !isSpecialRate && !isSameCurrency && (
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Approx. {value}" },
|
||||
{
|
||||
defaultMessage: "Approx. {value}",
|
||||
},
|
||||
{
|
||||
value: formatPrice(
|
||||
intl,
|
||||
@@ -465,7 +496,9 @@ export default function SummaryUI({
|
||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "<strong>Booking code</strong>: {value}" },
|
||||
{
|
||||
defaultMessage: "<strong>Booking code</strong>: {value}",
|
||||
},
|
||||
{
|
||||
value: booking.bookingCode,
|
||||
strong: (text) => (
|
||||
|
||||
@@ -50,24 +50,29 @@ export default function AdditionalInfoForm({
|
||||
<div>
|
||||
<Title level="h2" as="h3">
|
||||
{intl.formatMessage({
|
||||
id: "One last step",
|
||||
defaultMessage: "One last step",
|
||||
})}
|
||||
</Title>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "We need some more details to confirm your identity.",
|
||||
defaultMessage:
|
||||
"We need some more details to confirm your identity.",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
<div className={styles.inputs}>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "First name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "First name",
|
||||
})}
|
||||
name="firstName"
|
||||
placeholder="Anna"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Email" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Email",
|
||||
})}
|
||||
name="email"
|
||||
placeholder="anna@scandichotels.com"
|
||||
registerOptions={{ required: true }}
|
||||
@@ -80,7 +85,9 @@ export default function AdditionalInfoForm({
|
||||
theme="base"
|
||||
disabled={form.formState.isSubmitting}
|
||||
>
|
||||
{intl.formatMessage({ id: "Confirm" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Confirm",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -50,7 +50,7 @@ export default function FindMyBooking() {
|
||||
console.error("Failed to create ref id", error)
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Failed to submit form, please try again later.",
|
||||
defaultMessage: "Failed to submit form, please try again later.",
|
||||
})
|
||||
)
|
||||
},
|
||||
@@ -68,35 +68,46 @@ export default function FindMyBooking() {
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className={styles.form}>
|
||||
<div>
|
||||
<Title level="h2" as="h3">
|
||||
{intl.formatMessage({ id: "Find your stay" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Find your stay",
|
||||
})}
|
||||
</Title>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "View and manage your stay made on Scandic's website",
|
||||
defaultMessage:
|
||||
"View and manage your stay made on Scandic's website",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
<div className={[styles.inputs, styles.grid].join(" ")}>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Booking number" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Booking number",
|
||||
})}
|
||||
name="confirmationNumber"
|
||||
placeholder="XXXXXX"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "First name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "First name",
|
||||
})}
|
||||
name="firstName"
|
||||
placeholder="Anna"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Last name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Last name",
|
||||
})}
|
||||
name="lastName"
|
||||
placeholder="Andersson"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Email" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Email",
|
||||
})}
|
||||
name="email"
|
||||
placeholder="anna@scandichotels.com"
|
||||
registerOptions={{ required: true }}
|
||||
@@ -105,11 +116,16 @@ export default function FindMyBooking() {
|
||||
<div className={styles.buttons}>
|
||||
<div className={styles.footnote}>
|
||||
<Caption type="bold">
|
||||
{intl.formatMessage({ id: "Can't find your stay?" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Can't find your stay?",
|
||||
})}
|
||||
</Caption>
|
||||
<Caption>
|
||||
{intl.formatMessage(
|
||||
{ id: "Please contact <link>customer service</link>." },
|
||||
{
|
||||
defaultMessage:
|
||||
"Please contact <link>customer service</link>.",
|
||||
},
|
||||
{
|
||||
link: (str) => (
|
||||
<Link
|
||||
@@ -132,7 +148,9 @@ export default function FindMyBooking() {
|
||||
theme="base"
|
||||
disabled={form.formState.isSubmitting || update.isPending}
|
||||
>
|
||||
{intl.formatMessage({ id: "Find" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Find",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -17,14 +17,16 @@ export default function HotelChequeCard({
|
||||
return (
|
||||
<div className={styles.chequeCard}>
|
||||
<div className={styles.chequeRow}>
|
||||
<Caption>{intl.formatMessage({ id: "From" })}</Caption>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "From",
|
||||
})}
|
||||
</Caption>
|
||||
<div className={styles.cheque}>
|
||||
<Subtitle type="two" color="uiTextHighContrast">
|
||||
{productTypeCheque.localPrice.numberOfCheques}
|
||||
</Subtitle>
|
||||
<Caption color="uiTextHighContrast" className={styles.currency}>
|
||||
{CurrencyEnum.CC}
|
||||
</Caption>
|
||||
<Caption color="uiTextHighContrast">{CurrencyEnum.CC}</Caption>
|
||||
{productTypeCheque.localPrice.additionalPricePerStay && (
|
||||
<>
|
||||
{"+"}
|
||||
@@ -41,15 +43,18 @@ export default function HotelChequeCard({
|
||||
{productTypeCheque.requestedPrice ? (
|
||||
<div className={styles.chequeRow}>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Approx." })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Approx.",
|
||||
})}
|
||||
</Caption>
|
||||
<Caption color={"uiTextMediumContrast"}>
|
||||
{productTypeCheque.requestedPrice.numberOfCheques} {CurrencyEnum.CC}
|
||||
{productTypeCheque.requestedPrice.additionalPricePerStay
|
||||
? " + "
|
||||
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
" + "
|
||||
: ""}
|
||||
{productTypeCheque.requestedPrice.additionalPricePerStay}{" "}
|
||||
{productTypeCheque.requestedPrice.currency}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${productTypeCheque.requestedPrice.additionalPricePerStay} ${productTypeCheque.requestedPrice.currency}`}
|
||||
</Caption>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -20,11 +20,13 @@ export default function HotelPointsRow({
|
||||
{pointsPerStay}
|
||||
</Subtitle>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Points" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})}
|
||||
</Caption>
|
||||
{additionalPricePerStay ? (
|
||||
<>
|
||||
+
|
||||
{"+"}
|
||||
<Subtitle type="two" color="uiTextHighContrast">
|
||||
{additionalPricePerStay}
|
||||
</Subtitle>
|
||||
|
||||
@@ -26,7 +26,9 @@ export default function HotelPriceCard({
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color="red">
|
||||
{intl.formatMessage({ id: "Member price" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Member price",
|
||||
})}
|
||||
</Caption>
|
||||
</dt>
|
||||
</div>
|
||||
@@ -34,7 +36,9 @@ export default function HotelPriceCard({
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Standard price" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Standard price",
|
||||
})}
|
||||
</Caption>
|
||||
</dt>
|
||||
</div>
|
||||
@@ -45,7 +49,9 @@ export default function HotelPriceCard({
|
||||
type="bold"
|
||||
color={isMemberPrice ? "red" : "uiTextHighContrast"}
|
||||
>
|
||||
{intl.formatMessage({ id: "From" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "From",
|
||||
})}
|
||||
</Caption>
|
||||
</dt>
|
||||
<dd>
|
||||
@@ -61,8 +67,12 @@ export default function HotelPriceCard({
|
||||
textTransform="bold"
|
||||
>
|
||||
{productTypePrices.localPrice.currency}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span className={styles.perNight}>
|
||||
/{intl.formatMessage({ id: "night" })}
|
||||
/
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "night",
|
||||
})}
|
||||
</span>
|
||||
</Body>
|
||||
</div>
|
||||
@@ -72,12 +82,15 @@ export default function HotelPriceCard({
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Approx." })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Approx.",
|
||||
})}
|
||||
</Caption>
|
||||
</dt>
|
||||
<dd>
|
||||
<Caption color={"uiTextMediumContrast"}>
|
||||
{productTypePrices.requestedPrice.pricePerNight}{" "}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${productTypePrices.requestedPrice.pricePerNight} `}
|
||||
{productTypePrices.requestedPrice.currency}
|
||||
</Caption>
|
||||
</dd>
|
||||
@@ -92,12 +105,15 @@ export default function HotelPriceCard({
|
||||
<div className={styles.priceRow}>
|
||||
<dt>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Total" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
</Caption>
|
||||
</dt>
|
||||
<dd>
|
||||
<Caption color={"uiTextMediumContrast"}>
|
||||
{productTypePrices.localPrice.pricePerStay}{" "}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${productTypePrices.localPrice.pricePerStay} `}
|
||||
{productTypePrices.localPrice.currency}
|
||||
</Caption>
|
||||
</dd>
|
||||
|
||||
@@ -17,7 +17,11 @@ export default function HotelVoucherCard({
|
||||
return (
|
||||
<div className={styles.voucherCard}>
|
||||
<div className={styles.voucherRow}>
|
||||
<Caption>{intl.formatMessage({ id: "From" })}</Caption>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "From",
|
||||
})}
|
||||
</Caption>
|
||||
<div className={styles.voucher}>
|
||||
<Subtitle type="two" color="uiTextHighContrast">
|
||||
{productTypeVoucher.numberOfVouchers}
|
||||
|
||||
@@ -16,7 +16,8 @@ export default function NoPriceAvailableCard() {
|
||||
</div>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({
|
||||
id: "There are no rooms available that match your request.",
|
||||
defaultMessage:
|
||||
"There are no rooms available that match your request.",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
|
||||
@@ -88,7 +88,9 @@ function HotelCard({
|
||||
const hasInsufficientPoints = !price?.redemptions?.some(
|
||||
(r) => r.hasEnoughPoints
|
||||
)
|
||||
const notEnoughPointsLabel = intl.formatMessage({ id: "Not enough points" })
|
||||
const notEnoughPointsLabel = intl.formatMessage({
|
||||
defaultMessage: "Not enough points",
|
||||
})
|
||||
|
||||
return (
|
||||
<article
|
||||
@@ -129,7 +131,7 @@ function HotelCard({
|
||||
href={selectHotelMap(lang)}
|
||||
keepSearchParams
|
||||
aria-label={intl.formatMessage({
|
||||
id: "See on map",
|
||||
defaultMessage: "See on map",
|
||||
})}
|
||||
>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
@@ -144,7 +146,9 @@ function HotelCard({
|
||||
</div>
|
||||
<Caption color="uiTextPlaceholder">
|
||||
{intl.formatMessage(
|
||||
{ id: "{number} km to city center" },
|
||||
{
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
number: getSingleDecimal(
|
||||
hotel.location.distanceToCentre / 1000
|
||||
@@ -173,7 +177,9 @@ function HotelCard({
|
||||
})}
|
||||
</div>
|
||||
<ReadMore
|
||||
label={intl.formatMessage({ id: "See hotel details" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
hotelId={hotel.operaId}
|
||||
hotel={hotel}
|
||||
showCTA={true}
|
||||
@@ -192,7 +198,10 @@ function HotelCard({
|
||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "<strong>Booking code</strong>: {value}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"<strong>Booking code</strong>: {value}",
|
||||
},
|
||||
{
|
||||
value: bookingCode,
|
||||
strong: (text) => (
|
||||
@@ -227,7 +236,9 @@ function HotelCard({
|
||||
{price?.redemptions?.length ? (
|
||||
<div className={styles.pointsCard}>
|
||||
<Caption>
|
||||
{intl.formatMessage({ id: "Available rates" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Available rates",
|
||||
})}
|
||||
</Caption>
|
||||
{price.redemptions.map((redemption) => (
|
||||
<HotelPointsRow
|
||||
@@ -272,7 +283,9 @@ function HotelCard({
|
||||
color="none"
|
||||
keepSearchParams
|
||||
>
|
||||
{intl.formatMessage({ id: "See rooms" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See rooms",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -93,11 +93,15 @@ export default function ListingHotelCardDialog({
|
||||
<div className={styles.pricesContainer}>
|
||||
{redemptionPrice ? (
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Available rates" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Available rates",
|
||||
})}
|
||||
</Caption>
|
||||
) : (
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Per night from" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Per night from",
|
||||
})}
|
||||
</Caption>
|
||||
)}
|
||||
<div className={styles.listingPrices}>
|
||||
@@ -106,13 +110,16 @@ export default function ListingHotelCardDialog({
|
||||
<Subtitle type="two">
|
||||
{publicPrice} {currency}
|
||||
</Subtitle>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{memberPrice && <Caption>/</Caption>}
|
||||
</>
|
||||
)}
|
||||
{memberPrice && (
|
||||
<Subtitle type="two" color="red" className={styles.memberPrice}>
|
||||
{intl.formatMessage(
|
||||
{ id: "{price} {currency}" },
|
||||
{
|
||||
defaultMessage: "{price} {currency}",
|
||||
},
|
||||
{
|
||||
price: memberPrice,
|
||||
currency,
|
||||
@@ -131,7 +138,9 @@ export default function ListingHotelCardDialog({
|
||||
color="none"
|
||||
keepSearchParams
|
||||
>
|
||||
{intl.formatMessage({ id: "See rooms" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See rooms",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -92,24 +92,36 @@ export default function StandaloneHotelCardDialog({
|
||||
<div className={styles.priceCard}>
|
||||
{redemptionPrice ? (
|
||||
<Caption>
|
||||
{intl.formatMessage({ id: "Available rates" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Available rates",
|
||||
})}
|
||||
</Caption>
|
||||
) : (
|
||||
<Caption type="bold">
|
||||
{intl.formatMessage({ id: "From" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "From",
|
||||
})}
|
||||
</Caption>
|
||||
)}
|
||||
{publicPrice && !isUserLoggedIn && (
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage(
|
||||
{ id: "{price} {currency}" },
|
||||
{
|
||||
defaultMessage: "{price} {currency}",
|
||||
},
|
||||
{
|
||||
price: publicPrice,
|
||||
currency,
|
||||
}
|
||||
)}
|
||||
<Body asChild>
|
||||
<span>/{intl.formatMessage({ id: "night" })}</span>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span>
|
||||
/
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "night",
|
||||
})}
|
||||
</span>
|
||||
</Body>
|
||||
</Subtitle>
|
||||
)}
|
||||
@@ -120,14 +132,22 @@ export default function StandaloneHotelCardDialog({
|
||||
className={styles.memberPrice}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "{price} {currency}" },
|
||||
{
|
||||
defaultMessage: "{price} {currency}",
|
||||
},
|
||||
{
|
||||
price: memberPrice,
|
||||
currency,
|
||||
}
|
||||
)}
|
||||
<Body asChild color="red">
|
||||
<span>/{intl.formatMessage({ id: "night" })}</span>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span>
|
||||
/
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "night",
|
||||
})}
|
||||
</span>
|
||||
</Body>
|
||||
</Subtitle>
|
||||
)}
|
||||
@@ -146,7 +166,9 @@ export default function StandaloneHotelCardDialog({
|
||||
color="none"
|
||||
keepSearchParams
|
||||
>
|
||||
{intl.formatMessage({ id: "See rooms" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See rooms",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
</>
|
||||
|
||||
@@ -23,7 +23,9 @@ export default function HotelCardDialogListing({
|
||||
(hotel) => hotel.availability.productType?.redemptions?.length
|
||||
)
|
||||
const currencyValue = isRedemption
|
||||
? intl.formatMessage({ id: "Points" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})
|
||||
: undefined
|
||||
const hotelsPinData = hotels ? getHotelPins(hotels, currencyValue) : []
|
||||
const activeCardRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
@@ -151,9 +151,12 @@ export default function HotelCardListing({
|
||||
{!hotels?.length && activeFilters ? (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({ id: "No hotels match your filters" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "No hotels match your filters",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
defaultMessage:
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
@@ -50,14 +50,18 @@ export function getSortedHotels({
|
||||
if (bookingCode) {
|
||||
const bookingCodeRateHotels = availableHotels.filter(
|
||||
(hotel) =>
|
||||
(hotel.availability.productType?.public?.rateType !== RateTypeEnum.Regular &&
|
||||
hotel.availability.productType?.member?.rateType !== RateTypeEnum.Regular) &&
|
||||
hotel.availability.productType?.public?.rateType !==
|
||||
RateTypeEnum.Regular &&
|
||||
hotel.availability.productType?.member?.rateType !==
|
||||
RateTypeEnum.Regular &&
|
||||
!!hotel.availability.productType
|
||||
)
|
||||
const regularRateHotels = availableHotels.filter(
|
||||
(hotel) =>
|
||||
hotel.availability.productType?.public?.rateType === RateTypeEnum.Regular ||
|
||||
hotel?.availability.productType?.member?.rateType === RateTypeEnum.Regular
|
||||
hotel.availability.productType?.public?.rateType ===
|
||||
RateTypeEnum.Regular ||
|
||||
hotel?.availability.productType?.member?.rateType ===
|
||||
RateTypeEnum.Regular
|
||||
)
|
||||
|
||||
return bookingCodeRateHotels
|
||||
|
||||
@@ -43,8 +43,12 @@ export default function ActionButtons({
|
||||
|
||||
const intl = useIntl()
|
||||
const isConfirmStep = currentStep === AncillaryStepEnum.confirmation
|
||||
const confirmLabel = intl.formatMessage({ id: "Confirm" })
|
||||
const continueLabel = intl.formatMessage({ id: "Continue" })
|
||||
const confirmLabel = intl.formatMessage({
|
||||
defaultMessage: "Confirm",
|
||||
})
|
||||
const continueLabel = intl.formatMessage({
|
||||
defaultMessage: "Continue",
|
||||
})
|
||||
const quantityWithCard = useWatch<AncillaryQuantityFormData>({
|
||||
name: "quantityWithCard",
|
||||
})
|
||||
@@ -87,7 +91,9 @@ export default function ActionButtons({
|
||||
onPress={togglePriceDetails}
|
||||
className={styles.priceButton}
|
||||
>
|
||||
{intl.formatMessage({ id: "Price details" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price details",
|
||||
})}
|
||||
{isPriceDetailsOpen ? (
|
||||
<MaterialIcon
|
||||
icon="keyboard_arrow_up"
|
||||
@@ -112,7 +118,9 @@ export default function ActionButtons({
|
||||
color="Primary"
|
||||
onPress={prevStep}
|
||||
>
|
||||
{intl.formatMessage({ id: "Back" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</Button>
|
||||
{isConfirmStep && (
|
||||
<Button
|
||||
|
||||
@@ -22,7 +22,8 @@ export default function PriceRow({
|
||||
<h2>{title}</h2>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{`X${quantity}`}</p>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<p>{`×${quantity}`}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
|
||||
@@ -35,7 +35,11 @@ export default function PriceSummary({
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<h2>{intl.formatMessage({ id: "Summary" })}</h2>
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Summary",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
<Divider color="subtle" />
|
||||
|
||||
@@ -45,7 +49,9 @@ export default function PriceSummary({
|
||||
<PriceRow
|
||||
title={item.title}
|
||||
quantity={item.quantityWithCard}
|
||||
label={intl.formatMessage({ id: "Price including VAT" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})}
|
||||
value={formatPrice(intl, item.totalPrice, item.currency)}
|
||||
/>
|
||||
)}
|
||||
@@ -53,8 +59,12 @@ export default function PriceSummary({
|
||||
<PriceRow
|
||||
title={item.title}
|
||||
quantity={item.quantityWithPoints}
|
||||
label={intl.formatMessage({ id: "Points" })}
|
||||
value={`${item.points} ${intl.formatMessage({ id: "points" })}`}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})}
|
||||
value={`${item.points} ${intl.formatMessage({
|
||||
defaultMessage: "points",
|
||||
})}`}
|
||||
/>
|
||||
)}
|
||||
<Divider color="subtle" />
|
||||
@@ -65,19 +75,29 @@ export default function PriceSummary({
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{hasTotalPrice
|
||||
? intl.formatMessage({ id: "Total price including VAT" })
|
||||
: intl.formatMessage({ id: "Total points" })}
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Total price including VAT",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Total points",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<div className={styles.totalPrice}>
|
||||
{(hasTotalPoints || hasTotalPrice) && (
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{hasTotalPrice &&
|
||||
formatPrice(intl, totalPrice, items[0]?.currency)}
|
||||
{hasTotalPoints && hasTotalPrice && " + "}
|
||||
{hasTotalPoints &&
|
||||
`${totalPoints} ${intl.formatMessage({ id: "points" })}`}
|
||||
{hasTotalPrice
|
||||
? formatPrice(intl, totalPrice, items[0]?.currency)
|
||||
: null}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{hasTotalPoints && hasTotalPrice ? " + " : null}
|
||||
{hasTotalPoints
|
||||
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`${totalPoints} ${intl.formatMessage({
|
||||
defaultMessage: "points",
|
||||
})}`
|
||||
: null}
|
||||
</p>
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
@@ -74,7 +74,9 @@ export default function PriceDetails({
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: `${selectedAncillary.title} / ${intl.formatMessage({ id: "Adult" })}`,
|
||||
title: `${selectedAncillary.title} / ${intl.formatMessage({
|
||||
defaultMessage: "Adult",
|
||||
})}`,
|
||||
totalPrice: breakfastData.priceAdult,
|
||||
currency: breakfastData.currency,
|
||||
quantityWithCard: breakfastData.nrOfAdults * breakfastData.nrOfNights,
|
||||
@@ -83,7 +85,9 @@ export default function PriceDetails({
|
||||
|
||||
if (breakfastData.nrOfPayingChildren > 0) {
|
||||
items.push({
|
||||
title: `${selectedAncillary.title} / ${intl.formatMessage({ id: "Children" })} 4-12`,
|
||||
title: `${selectedAncillary.title} / ${intl.formatMessage({
|
||||
defaultMessage: "Children",
|
||||
})} 4-12`,
|
||||
totalPrice: breakfastData.priceChild,
|
||||
currency: breakfastData.currency,
|
||||
quantityWithCard:
|
||||
@@ -93,7 +97,12 @@ export default function PriceDetails({
|
||||
|
||||
if (breakfastData.nrOfFreeChildren > 0) {
|
||||
items.push({
|
||||
title: `${selectedAncillary.title} / ${intl.formatMessage({ id: "Children under {age}" }, { age: 4 })}`,
|
||||
title: `${selectedAncillary.title} / ${intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Children under {age}",
|
||||
},
|
||||
{ age: 4 }
|
||||
)}`,
|
||||
totalPrice: 0,
|
||||
currency: breakfastData.currency,
|
||||
quantityWithCard:
|
||||
@@ -122,12 +131,19 @@ export default function PriceDetails({
|
||||
<div className={styles.totalPrice}>
|
||||
<div className={styles.totalPriceInclVAT}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "Total" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
{totalPrice && (
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.vatText}>
|
||||
({intl.formatMessage({ id: "Incl. VAT" })})
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`(${intl.formatMessage({
|
||||
defaultMessage: "Incl. VAT",
|
||||
})})`}
|
||||
</p>
|
||||
</Typography>
|
||||
)}
|
||||
@@ -154,7 +170,14 @@ export default function PriceDetails({
|
||||
</div>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{totalPoints} {intl.formatMessage({ id: "points" })}
|
||||
{totalPoints}
|
||||
{
|
||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||
" "
|
||||
}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "points",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -54,7 +54,8 @@ export default function ConfirmationStep({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "All ancillaries are fully refundable until {date}. Time selection and special requests are also modifiable.",
|
||||
defaultMessage:
|
||||
"All ancillaries are fully refundable until {date}. Time selection and special requests are also modifiable.",
|
||||
},
|
||||
{ date: refundableDate }
|
||||
)}
|
||||
@@ -65,7 +66,7 @@ export default function ConfirmationStep({
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
id: "Points to be deducted now",
|
||||
defaultMessage: "Points to be deducted now",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
@@ -75,7 +76,9 @@ export default function ConfirmationStep({
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h2>
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} points" },
|
||||
{
|
||||
defaultMessage: "{amount} points",
|
||||
},
|
||||
{ amount: totalPoints }
|
||||
)}
|
||||
</h2>
|
||||
@@ -84,7 +87,9 @@ export default function ConfirmationStep({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} points available" },
|
||||
{
|
||||
defaultMessage: "{amount} points available",
|
||||
},
|
||||
{ amount: currentPoints }
|
||||
)}
|
||||
</p>
|
||||
@@ -98,7 +103,7 @@ export default function ConfirmationStep({
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
id: "Reserve with Card",
|
||||
defaultMessage: "Reserve with Card",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
@@ -106,7 +111,8 @@ export default function ConfirmationStep({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "Payment will be made on check-in. The card will be only used to guarantee the ancillary in case of no-show.",
|
||||
defaultMessage:
|
||||
"Payment will be made on check-in. The card will be only used to guarantee the ancillary in case of no-show.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -115,14 +121,17 @@ export default function ConfirmationStep({
|
||||
name="paymentMethod"
|
||||
value={PaymentMethodEnum.card}
|
||||
cardNumber={guaranteeInfo.maskedCard.slice(-4)}
|
||||
label={intl.formatMessage({ id: "Credit card" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Credit card",
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
text={intl.formatMessage({
|
||||
id: "By adding a card you also guarantee your room booking for late arrival.",
|
||||
defaultMessage:
|
||||
"By adding a card you also guarantee your room booking for late arrival.",
|
||||
})}
|
||||
/>
|
||||
{savedCreditCards?.length && (
|
||||
@@ -131,13 +140,19 @@ export default function ConfirmationStep({
|
||||
<>
|
||||
{savedCreditCards?.length && (
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h4>{intl.formatMessage({ id: "OTHER" })}</h4>
|
||||
<h4>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "OTHER",
|
||||
})}
|
||||
</h4>
|
||||
</Typography>
|
||||
)}
|
||||
<PaymentOption
|
||||
name="paymentMethod"
|
||||
value={PaymentMethodEnum.card}
|
||||
label={intl.formatMessage({ id: "Credit card" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Credit card",
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
</>
|
||||
@@ -150,7 +165,8 @@ export default function ConfirmationStep({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "Yes, I accept the general <termsAndConditionsLink>Terms & Conditions</termsAndConditionsLink>, and understand that Scandic will process my personal data in accordance with <privacyPolicyLink>Scandic's Privacy policy</privacyPolicyLink>. There you can learn more about what data we process, your rights and where to turn if you have questions.",
|
||||
defaultMessage:
|
||||
"Yes, I accept the general <termsAndConditionsLink>Terms & Conditions</termsAndConditionsLink>, and understand that Scandic will process my personal data in accordance with <privacyPolicyLink>Scandic's Privacy policy</privacyPolicyLink>. There you can learn more about what data we process, your rights and where to turn if you have questions.",
|
||||
},
|
||||
{
|
||||
termsAndConditionsLink: (str) => (
|
||||
@@ -185,7 +201,7 @@ export default function ConfirmationStep({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: "I accept the terms and conditions",
|
||||
defaultMessage: "I accept the terms and conditions",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
@@ -17,7 +17,9 @@ export default function DeliveryMethodStep() {
|
||||
<div className={styles.selectContainer}>
|
||||
<div className={styles.select}>
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage({ id: "Delivered at:" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Delivered at:",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Select
|
||||
name="deliveryTime"
|
||||
@@ -28,18 +30,21 @@ export default function DeliveryMethodStep() {
|
||||
/>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "All add-ons are delivered at the same time. Changes to delivery times will affect earlier add-ons.",
|
||||
defaultMessage:
|
||||
"All add-ons are delivered at the same time. Changes to delivery times will affect earlier add-ons.",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
<div className={styles.select}>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Other Requests" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Other Requests",
|
||||
})}
|
||||
name="optionalText"
|
||||
/>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
id: "Optional",
|
||||
defaultMessage: "Optional",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
|
||||
@@ -34,7 +34,9 @@ export default function SelectAncillaryStep() {
|
||||
<p>
|
||||
{categoryName
|
||||
? categoryName
|
||||
: intl.formatMessage({ id: "Other" })}
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Other",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</button>
|
||||
|
||||
@@ -51,21 +51,33 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
||||
const insufficientPoints = currentPoints < pointsCost || currentPoints === 0
|
||||
|
||||
const pointsLabel = insufficientPoints
|
||||
? intl.formatMessage({ id: "Insufficient points" })
|
||||
: intl.formatMessage({ id: "Select quantity" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Insufficient points",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Select quantity",
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={styles.selectContainer}>
|
||||
{selectedAncillary?.points && user && (
|
||||
<div className={styles.select}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>{intl.formatMessage({ id: "Pay with points" })}</h2>
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Pay with points",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
<div className={styles.totalPointsContainer}>
|
||||
<div className={styles.totalPoints}>
|
||||
<MaterialIcon icon="diamond" />
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h2>{intl.formatMessage({ id: "Total points" })}</h2>
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total points",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
</div>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
@@ -83,11 +95,21 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
||||
)}
|
||||
<div className={styles.select}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2> {intl.formatMessage({ id: "Pay with Card" })}</h2>
|
||||
<h2>
|
||||
{
|
||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||
" "
|
||||
}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Pay with Card",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
<Select
|
||||
name="quantityWithCard"
|
||||
label={intl.formatMessage({ id: "Select quantity" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Select quantity",
|
||||
})}
|
||||
items={cardQuantityOptions}
|
||||
isNestedInModal
|
||||
/>
|
||||
@@ -107,7 +129,7 @@ function BreakfastInfo() {
|
||||
|
||||
if (!breakfastData) {
|
||||
return intl.formatMessage({
|
||||
id: "Can not show breakfast prices.",
|
||||
defaultMessage: "Can not show breakfast prices.",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -116,7 +138,8 @@ function BreakfastInfo() {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
text={intl.formatMessage({
|
||||
id: "Breakfast can only be added for the entire duration of the stay and for all guests.",
|
||||
defaultMessage:
|
||||
"Breakfast can only be added for the entire duration of the stay and for all guests.",
|
||||
})}
|
||||
/>
|
||||
{(breakfastData.nrOfPayingChildren > 0 ||
|
||||
@@ -126,10 +149,14 @@ function BreakfastInfo() {
|
||||
<MaterialIcon icon="check_circle" className={styles.icon} />
|
||||
<div>
|
||||
<dt>
|
||||
{`${breakfastData.nrOfAdults} X ${intl.formatMessage({ id: "Adults" })}`}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${breakfastData.nrOfAdults} × ${intl.formatMessage({
|
||||
defaultMessage: "Adults",
|
||||
})}`}
|
||||
</dt>
|
||||
<dd>
|
||||
<Body>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${breakfastData.priceAdult} ${breakfastData.currency}`}
|
||||
</Body>
|
||||
</dd>
|
||||
@@ -141,10 +168,14 @@ function BreakfastInfo() {
|
||||
<MaterialIcon icon="check_circle" className={styles.icon} />
|
||||
<div>
|
||||
<dt>
|
||||
{`${breakfastData.nrOfPayingChildren} X ${intl.formatMessage({ id: "ages" })} 4-12`}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${breakfastData.nrOfPayingChildren} × ${intl.formatMessage({
|
||||
defaultMessage: "ages",
|
||||
})} 4-12`}
|
||||
</dt>
|
||||
<dd>
|
||||
<Body>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${breakfastData.priceChild} ${breakfastData.currency}`}
|
||||
</Body>
|
||||
</dd>
|
||||
@@ -157,10 +188,17 @@ function BreakfastInfo() {
|
||||
<MaterialIcon icon="check_circle" className={styles.icon} />
|
||||
<div>
|
||||
<dt>
|
||||
{`${breakfastData.nrOfFreeChildren} X ${intl.formatMessage({ id: "under" })} 4`}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${breakfastData.nrOfFreeChildren} × ${intl.formatMessage({
|
||||
defaultMessage: "under",
|
||||
})} 4`}
|
||||
</dt>
|
||||
<dd>
|
||||
<Body>{intl.formatMessage({ id: "Free" })}</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Free",
|
||||
})}
|
||||
</Body>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -110,7 +110,8 @@ export default function AddAncillaryFlowModal({
|
||||
|
||||
const ancillaryErrorMessage = intl.formatMessage(
|
||||
{
|
||||
id: "Something went wrong. {ancillary} could not be added to your booking!",
|
||||
defaultMessage:
|
||||
"Something went wrong. {ancillary} could not be added to your booking!",
|
||||
},
|
||||
{ ancillary: selectedAncillary?.title }
|
||||
)
|
||||
@@ -170,7 +171,9 @@ export default function AddAncillaryFlowModal({
|
||||
)
|
||||
toast.success(
|
||||
intl.formatMessage(
|
||||
{ id: "{ancillary} added to your booking!" },
|
||||
{
|
||||
defaultMessage: "{ancillary} added to your booking!",
|
||||
},
|
||||
{ ancillary: selectedAncillary?.title }
|
||||
)
|
||||
)
|
||||
@@ -261,7 +264,11 @@ export default function AddAncillaryFlowModal({
|
||||
: []
|
||||
|
||||
if (isBreakfast && !breakfastData) {
|
||||
toast.error(intl.formatMessage({ id: "Something went wrong!" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Something went wrong!",
|
||||
})
|
||||
)
|
||||
return
|
||||
}
|
||||
const shouldSkipGuarantee =
|
||||
@@ -329,7 +336,9 @@ export default function AddAncillaryFlowModal({
|
||||
|
||||
const modalTitle =
|
||||
currentStep === AncillaryStepEnum.selectAncillary
|
||||
? intl.formatMessage({ id: "Upgrade your stay" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Upgrade your stay",
|
||||
})
|
||||
: selectedAncillary?.title
|
||||
return (
|
||||
<Modal isOpen={true} onToggle={closeModal} title={modalTitle}>
|
||||
@@ -375,7 +384,9 @@ export default function AddAncillaryFlowModal({
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ id: "{value} points" },
|
||||
{
|
||||
defaultMessage: "{value} points",
|
||||
},
|
||||
{
|
||||
value: selectedAncillary.points,
|
||||
}
|
||||
@@ -431,7 +442,7 @@ function BreakfastPriceList() {
|
||||
|
||||
if (!breakfastData) {
|
||||
return intl.formatMessage({
|
||||
id: "Can not show breakfast prices.",
|
||||
defaultMessage: "Can not show breakfast prices.",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -439,7 +450,12 @@ function BreakfastPriceList() {
|
||||
<div>
|
||||
<div className={styles.breakfastPriceList}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<span>{`${breakfastData.priceAdult} ${breakfastData.currency} / ${intl.formatMessage({ id: "Adult" })}`}</span>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span>{`${breakfastData.priceAdult} ${breakfastData.currency} / ${intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Adult",
|
||||
}
|
||||
)}`}</span>
|
||||
</Typography>
|
||||
|
||||
{breakfastData.nrOfPayingChildren > 0 && (
|
||||
@@ -449,7 +465,12 @@ function BreakfastPriceList() {
|
||||
</div>
|
||||
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<span>{`${breakfastData.priceChild} ${breakfastData.currency} / ${intl.formatMessage({ id: "Years" })} 4-12`}</span>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span>{`${breakfastData.priceChild} ${breakfastData.currency} / ${intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Years",
|
||||
}
|
||||
)} 4-12`}</span>
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
@@ -461,7 +482,15 @@ function BreakfastPriceList() {
|
||||
</div>
|
||||
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<span>{`${intl.formatMessage({ id: "Free" })} / ${intl.formatMessage({ id: "Under {age} years" }, { age: 4 })}`}</span>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span>{`${intl.formatMessage({
|
||||
defaultMessage: "Free",
|
||||
})} / ${intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Under {age} years",
|
||||
},
|
||||
{ age: 4 }
|
||||
)}`}</span>
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -27,16 +27,24 @@ export default function RemoveButton({
|
||||
return (
|
||||
<Dialog
|
||||
bodyText={intl.formatMessage({
|
||||
id: "Are you sure you want to remove this product?",
|
||||
defaultMessage: "Are you sure you want to remove this product?",
|
||||
})}
|
||||
proceedText={intl.formatMessage({
|
||||
defaultMessage: "Remove",
|
||||
})}
|
||||
proceedText={intl.formatMessage({ id: "Remove" })}
|
||||
proceedIsPending={removePackage.isPending}
|
||||
cancelButtonText={intl.formatMessage({ id: "Cancel" })}
|
||||
titleText={`${intl.formatMessage({ id: "Remove" })} ${title}`}
|
||||
cancelButtonText={intl.formatMessage({
|
||||
defaultMessage: "Cancel",
|
||||
})}
|
||||
titleText={`${intl.formatMessage({
|
||||
defaultMessage: "Remove",
|
||||
})} ${title}`}
|
||||
trigger={
|
||||
<Button intent="text" size="small" variant="icon" theme="base">
|
||||
<MaterialIcon icon="delete" color="CurrentColor" />
|
||||
{intl.formatMessage({ id: "Remove" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Remove",
|
||||
})}
|
||||
</Button>
|
||||
}
|
||||
proceedOnClick={(close) => {
|
||||
@@ -56,7 +64,11 @@ export default function RemoveButton({
|
||||
onSuccess()
|
||||
},
|
||||
onError: () => {
|
||||
toast.error(intl.formatMessage({ id: "Something went wrong!" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Something went wrong!",
|
||||
})
|
||||
)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -42,12 +42,18 @@ export function AddedAncillaries({
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
<Subtitle>{intl.formatMessage({ id: "My Add-on's" })}</Subtitle>
|
||||
<Subtitle>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "My Add-on's",
|
||||
})}
|
||||
</Subtitle>
|
||||
|
||||
{booking.ancillary?.deliveryTime && (
|
||||
<div className={styles.deliveryTime}>
|
||||
<Body color="baseTextHighContrast" textTransform="bold">
|
||||
{intl.formatMessage({ id: "Delivered at:" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Delivered at:",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="baseTextHighContrast" textTransform="bold">
|
||||
{booking.ancillary?.deliveryTime}
|
||||
@@ -59,7 +65,9 @@ export function AddedAncillaries({
|
||||
{addedAncillaries.map((ancillary) => {
|
||||
const ancillaryTitle =
|
||||
ancillary.code === BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST
|
||||
? intl.formatMessage({ id: "Breakfast" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Breakfast",
|
||||
})
|
||||
: (ancillaries?.find(
|
||||
(a) =>
|
||||
a.id === ancillary.code || a.loyaltyCode === ancillary.code
|
||||
@@ -82,7 +90,11 @@ export function AddedAncillaries({
|
||||
<>
|
||||
<div className={styles.commentMobile}>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Other requests" })}:
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Other requests",
|
||||
})}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{":"}
|
||||
</Body>
|
||||
<Body color="uiTextMediumContrast">
|
||||
{ancillary.comment}
|
||||
@@ -92,11 +104,19 @@ export function AddedAncillaries({
|
||||
)}
|
||||
<div className={styles.paymentMobileWrapper}>
|
||||
<div className={styles.paymentMobile}>
|
||||
<Body>{intl.formatMessage({ id: "Total" })}</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
</Body>
|
||||
<Body textTransform="bold">
|
||||
{ancillary.currency.toLowerCase() === "points"
|
||||
? `${ancillary.totalPrice} ${intl.formatMessage({ id: "Points" })}`
|
||||
: `${ancillary.totalPrice} ${ancillary.currency}`}
|
||||
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`${ancillary.totalPrice} ${intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})}`
|
||||
: // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`${ancillary.totalPrice} ${ancillary.currency}`}
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
@@ -129,14 +149,23 @@ export function AddedAncillaries({
|
||||
color="Icon/Feedback/Success"
|
||||
/>
|
||||
<Body textTransform="bold">{ancillaryTitle}</Body>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Body textTransform="bold">{`X${ancillary.totalUnit}`}</Body>
|
||||
</div>
|
||||
<div className={styles.payment}>
|
||||
<Body>{intl.formatMessage({ id: "Total" })}</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
</Body>
|
||||
<Body textTransform="bold">
|
||||
{ancillary.currency.toLowerCase() === "points"
|
||||
? `${ancillary.totalPrice} ${intl.formatMessage({ id: "Points" })}`
|
||||
: `${ancillary.totalPrice} ${ancillary.currency}`}
|
||||
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`${ancillary.totalPrice} ${intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})}`
|
||||
: // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`${ancillary.totalPrice} ${ancillary.currency}`}
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
@@ -148,7 +177,11 @@ export function AddedAncillaries({
|
||||
{ancillary.comment && (
|
||||
<>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Other requests" })}:
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Other requests",
|
||||
})}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{":"}
|
||||
</Body>
|
||||
<Body>{ancillary.comment}</Body>
|
||||
</>
|
||||
|
||||
@@ -17,7 +17,9 @@ export default function ViewAllAncillaries() {
|
||||
size="small"
|
||||
onClick={openModal}
|
||||
>
|
||||
{intl.formatMessage({ id: "View all" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "View all",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -113,9 +113,13 @@ export function Ancillaries({
|
||||
|
||||
const breakfastAncillary: SelectedAncillary | undefined = breakfastPackage
|
||||
? {
|
||||
description: intl.formatMessage({ id: "Buffet" }),
|
||||
description: intl.formatMessage({
|
||||
defaultMessage: "Buffet",
|
||||
}),
|
||||
id: breakfastPackage.code,
|
||||
title: intl.formatMessage({ id: "Breakfast" }),
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Breakfast",
|
||||
}),
|
||||
price: {
|
||||
currency: breakfastPackage.localPrice.currency,
|
||||
total: breakfastPackage.localPrice.totalPrice,
|
||||
@@ -172,7 +176,9 @@ export function Ancillaries({
|
||||
<>
|
||||
<div className={styles.title}>
|
||||
<Title as="h5">
|
||||
{intl.formatMessage({ id: "Upgrade your stay" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Upgrade your stay",
|
||||
})}
|
||||
</Title>
|
||||
<ViewAllAncillaries />
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,9 @@ export default function BookingSummary({ hotel }: BookingSummaryProps) {
|
||||
<div className={styles.bookingSummary}>
|
||||
<Typography variant="Title/sm">
|
||||
<h2 className={styles.title}>
|
||||
{intl.formatMessage({ id: "Practical information" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Practical information",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
<div className={styles.bookingSummaryContent}>
|
||||
@@ -46,7 +48,9 @@ export default function BookingSummary({ hotel }: BookingSummaryProps) {
|
||||
`${hotel.address.zipCode} ${hotel.address.city}`,
|
||||
]}
|
||||
supportingText={intl.formatMessage(
|
||||
{ id: "Long {long} ∙ Lat {lat}" },
|
||||
{
|
||||
defaultMessage: "Long {long} ∙ Lat {lat}",
|
||||
},
|
||||
{
|
||||
lat: hotel.location.latitude,
|
||||
long: hotel.location.longitude,
|
||||
@@ -55,7 +59,9 @@ export default function BookingSummary({ hotel }: BookingSummaryProps) {
|
||||
links={[
|
||||
{
|
||||
href: directionsUrl,
|
||||
text: intl.formatMessage({ id: "Directions" }),
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "Directions",
|
||||
}),
|
||||
icon: (
|
||||
<MaterialIcon
|
||||
icon="directions"
|
||||
@@ -67,7 +73,9 @@ export default function BookingSummary({ hotel }: BookingSummaryProps) {
|
||||
},
|
||||
{
|
||||
href: `mailto:${hotel.contactInformation.email}`,
|
||||
text: intl.formatMessage({ id: "Email" }),
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "Email",
|
||||
}),
|
||||
icon: (
|
||||
<MaterialIcon
|
||||
icon="mail"
|
||||
@@ -79,7 +87,9 @@ export default function BookingSummary({ hotel }: BookingSummaryProps) {
|
||||
},
|
||||
{
|
||||
href: hotel.contactInformation.websiteUrl,
|
||||
text: intl.formatMessage({ id: "Homepage" }),
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "Homepage",
|
||||
}),
|
||||
icon: (
|
||||
<MaterialIcon
|
||||
icon="link"
|
||||
|
||||
@@ -107,7 +107,7 @@ export default function GuaranteeLateArrival({
|
||||
handleGuaranteeError("No confirmation number")
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong!",
|
||||
defaultMessage: "Something went wrong!",
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -116,39 +116,48 @@ export default function GuaranteeLateArrival({
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<ModalContentWithActions
|
||||
title={intl.formatMessage({ id: "Guarantee late arrival" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Guarantee late arrival",
|
||||
})}
|
||||
onClose={handleCloseModal}
|
||||
content={
|
||||
<>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
id: "Planning to arrive after 18.00? Secure your room by guaranteeing it with a credit card. Without the guarantee and in case of no-show, the room might be reallocated after 18:00.",
|
||||
defaultMessage:
|
||||
"Planning to arrive after 18.00? Secure your room by guaranteeing it with a credit card. Without the guarantee and in case of no-show, the room might be reallocated after 18:00.",
|
||||
})}
|
||||
</Caption>
|
||||
<Caption type="bold">
|
||||
{intl.formatMessage({
|
||||
id: "In case of no-show you will be charged for the first night.",
|
||||
defaultMessage:
|
||||
"In case of no-show you will be charged for the first night.",
|
||||
})}
|
||||
</Caption>
|
||||
{savedCreditCards?.length ? (
|
||||
<>
|
||||
<MySavedCards savedCreditCards={savedCreditCards} />
|
||||
<Body color="uiTextHighContrast" textTransform="bold">
|
||||
{intl.formatMessage({ id: "OTHER" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "OTHER",
|
||||
})}
|
||||
</Body>
|
||||
</>
|
||||
) : null}
|
||||
<PaymentOption
|
||||
name="paymentMethod"
|
||||
value={PaymentMethodEnum.card}
|
||||
label={intl.formatMessage({ id: "Credit card" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Credit card",
|
||||
})}
|
||||
/>
|
||||
<div className={styles.termsAndConditions}>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "By guaranteeing with any of the payment methods available, I accept the terms for this stay and the general <termsAndConditionsLink>Terms & Conditions</termsAndConditionsLink>, and understand Scandic will process my personal data for this stay in accordance with <privacyPolicyLink>Scandic’s Privacy Policy</privacyPolicyLink>. I accept Scandic requiring a valid credit card during my visit in case anything is left unpaid.",
|
||||
defaultMessage:
|
||||
"By guaranteeing with any of the payment methods available, I accept the terms for this stay and the general <termsAndConditionsLink>Terms & Conditions</termsAndConditionsLink>, and understand Scandic will process my personal data for this stay in accordance with <privacyPolicyLink>Scandic’s Privacy Policy</privacyPolicyLink>. I accept Scandic requiring a valid credit card during my visit in case anything is left unpaid.",
|
||||
},
|
||||
{
|
||||
termsAndConditionsLink: (str) => (
|
||||
@@ -179,7 +188,7 @@ export default function GuaranteeLateArrival({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: "I accept the terms and conditions",
|
||||
defaultMessage: "I accept the terms and conditions",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
@@ -188,11 +197,14 @@ export default function GuaranteeLateArrival({
|
||||
<div className={styles.guaranteeCost}>
|
||||
<div className={styles.guaranteeCostText}>
|
||||
<Caption type="bold">
|
||||
{intl.formatMessage({ id: "Guarantee cost" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Guarantee cost",
|
||||
})}
|
||||
</Caption>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({
|
||||
id: "Your card will only be used for authorisation",
|
||||
defaultMessage:
|
||||
"Your card will only be used for authorisation",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
@@ -204,12 +216,16 @@ export default function GuaranteeLateArrival({
|
||||
</>
|
||||
}
|
||||
primaryAction={{
|
||||
label: intl.formatMessage({ id: "Guarantee" }),
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Guarantee",
|
||||
}),
|
||||
onClick: methods.handleSubmit(handleGuaranteeLateArrival),
|
||||
intent: "primary",
|
||||
}}
|
||||
secondaryAction={{
|
||||
label: intl.formatMessage({ id: "Back" }),
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
}),
|
||||
onClick: handleCloseView,
|
||||
intent: "text",
|
||||
}}
|
||||
|
||||
@@ -71,7 +71,9 @@ export default function GuestDetails({
|
||||
onSuccess: (data) => {
|
||||
if (!data) {
|
||||
toast.error(
|
||||
intl.formatMessage({ id: "Failed to update guest details" })
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to update guest details",
|
||||
})
|
||||
)
|
||||
|
||||
return
|
||||
@@ -86,12 +88,20 @@ export default function GuestDetails({
|
||||
},
|
||||
})
|
||||
|
||||
toast.success(intl.formatMessage({ id: "Guest details updated" }))
|
||||
toast.success(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Guest details updated",
|
||||
})
|
||||
)
|
||||
setIsModifyGuestDetailsOpen(false)
|
||||
setCurrentStep(MODAL_STEPS.INITIAL)
|
||||
},
|
||||
onError: () => {
|
||||
toast.error(intl.formatMessage({ id: "Failed to update guest details" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to update guest details",
|
||||
})
|
||||
)
|
||||
},
|
||||
onSettled: () => {
|
||||
setIsLoading(false)
|
||||
@@ -127,7 +137,11 @@ export default function GuestDetails({
|
||||
<div className={styles.userDetails}>
|
||||
<div className={styles.userDetailsTitle}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Your member tier" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Your member tier",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.memberLevel}>
|
||||
@@ -143,7 +157,11 @@ export default function GuestDetails({
|
||||
<MaterialIcon icon="diamond" color="Icon/Intense" />
|
||||
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Total points" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total points",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -163,7 +181,9 @@ export default function GuestDetails({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.memberNumber}>
|
||||
{intl.formatMessage(
|
||||
{ id: "Member no. {nr}" },
|
||||
{
|
||||
defaultMessage: "Member no. {nr}",
|
||||
},
|
||||
{
|
||||
nr: user.membership.membershipNumber,
|
||||
}
|
||||
@@ -203,7 +223,11 @@ export default function GuestDetails({
|
||||
size={20}
|
||||
/>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<span>{intl.formatMessage({ id: "Modify guest details" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Modify guest details",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
</Button>
|
||||
) : (
|
||||
@@ -228,7 +252,11 @@ export default function GuestDetails({
|
||||
size={20}
|
||||
/>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<span>{intl.formatMessage({ id: "Modify guest details" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Modify guest details",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
</Button>
|
||||
{isModifyGuestDetailsOpen && (
|
||||
@@ -239,12 +267,16 @@ export default function GuestDetails({
|
||||
onToggle={setIsModifyGuestDetailsOpen}
|
||||
>
|
||||
<Dialog
|
||||
aria-label={intl.formatMessage({ id: "Modify guest details" })}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Modify guest details",
|
||||
})}
|
||||
>
|
||||
{({ close }) => (
|
||||
<FormProvider {...form}>
|
||||
<ModalContentWithActions
|
||||
title={intl.formatMessage({ id: "Modify guest details" })}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Modify guest details",
|
||||
})}
|
||||
onClose={() => setIsModifyGuestDetailsOpen(false)}
|
||||
content={
|
||||
booking.guest && (
|
||||
@@ -256,8 +288,12 @@ export default function GuestDetails({
|
||||
}
|
||||
primaryAction={{
|
||||
label: isFirstStep
|
||||
? intl.formatMessage({ id: "Save updates" })
|
||||
: intl.formatMessage({ id: "Confirm" }),
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Save updates",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Confirm",
|
||||
}),
|
||||
onClick: isFirstStep
|
||||
? () => setCurrentStep(MODAL_STEPS.CONFIRMATION)
|
||||
: () => form.handleSubmit(onSubmit)(),
|
||||
@@ -266,8 +302,12 @@ export default function GuestDetails({
|
||||
}}
|
||||
secondaryAction={{
|
||||
label: isFirstStep
|
||||
? intl.formatMessage({ id: "Back" })
|
||||
: intl.formatMessage({ id: "Cancel" }),
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Cancel",
|
||||
}),
|
||||
onClick: () => {
|
||||
close()
|
||||
setCurrentStep(MODAL_STEPS.INITIAL)
|
||||
|
||||
@@ -12,7 +12,13 @@ export async function Header({ hotel }: Pick<BookingConfirmation, "hotel">) {
|
||||
<header>
|
||||
<Title as="h2" color="white" className={styles.title} textAlign="center">
|
||||
<BiroScript type="two" tilted="medium">
|
||||
{intl.formatMessage({ id: "My stay at" })}{" "}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "My stay at",
|
||||
})}
|
||||
{
|
||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||
" "
|
||||
}
|
||||
</BiroScript>
|
||||
<span className={styles.hotelName}>{hotel.name}</span>
|
||||
{hotel.cityName}
|
||||
|
||||
@@ -31,7 +31,9 @@ export default function AddToCalendarButton({
|
||||
onPress={handleAddToCalendar}
|
||||
disabled={disabled}
|
||||
>
|
||||
{intl.formatMessage({ id: "Add to calendar" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Add to calendar",
|
||||
})}
|
||||
<MaterialIcon icon="calendar_add_on" color="CurrentColor" />
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -26,7 +26,9 @@ export default function CancelStayPriceContainer({
|
||||
|
||||
return (
|
||||
<PriceContainer
|
||||
text={intl.formatMessage({ id: "Cancellation cost" })}
|
||||
text={intl.formatMessage({
|
||||
defaultMessage: "Cancellation cost",
|
||||
})}
|
||||
price={0}
|
||||
currencyCode={roomDetails.currencyCode}
|
||||
nightsText={stayDetails.nightsText}
|
||||
|
||||
@@ -37,7 +37,8 @@ export function CancelStayConfirmation({
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "Are you sure you want to cancel your stay at {hotel} from {checkInDate} to {checkOutDate}? This can't be reversed.",
|
||||
defaultMessage:
|
||||
"Are you sure you want to cancel your stay at {hotel} from {checkInDate} to {checkOutDate}? This can't be reversed.",
|
||||
},
|
||||
{
|
||||
hotel: hotel.name,
|
||||
@@ -47,13 +48,17 @@ export function CancelStayConfirmation({
|
||||
)}
|
||||
</Body>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "No charges were made." })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "No charges were made.",
|
||||
})}
|
||||
</Caption>
|
||||
</div>
|
||||
{multiRoom && (
|
||||
<>
|
||||
<Body color="uiTextHighContrast" textTransform="bold">
|
||||
{intl.formatMessage({ id: "Select rooms" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Select rooms",
|
||||
})}
|
||||
</Body>
|
||||
|
||||
<div className={styles.rooms}>
|
||||
@@ -80,7 +85,9 @@ export function CancelStayConfirmation({
|
||||
<div className={styles.roomInfo}>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{
|
||||
roomIndex: index + 1,
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ export function FinalConfirmation({ stayDetails }: FinalConfirmationProps) {
|
||||
<div className={styles.modalText}>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage({
|
||||
id: "Are you sure you want to continue with the cancellation?",
|
||||
defaultMessage:
|
||||
"Are you sure you want to continue with the cancellation?",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@ export default function useCancelStay({
|
||||
if (!bookedRoom.confirmationNumber) {
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
defaultMessage: "Something went wrong. Please try again later.",
|
||||
})
|
||||
)
|
||||
return
|
||||
@@ -136,7 +136,8 @@ export default function useCancelStay({
|
||||
toast.success(
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: "Your stay was cancelled. Cancellation cost: 0 {currency}. We're sorry to see that the plans didn't work out",
|
||||
defaultMessage:
|
||||
"Your stay was cancelled. Cancellation cost: 0 {currency}. We're sorry to see that the plans didn't work out",
|
||||
},
|
||||
{ currency: bookedRoom.currencyCode }
|
||||
)
|
||||
@@ -145,14 +146,15 @@ export default function useCancelStay({
|
||||
// Some rooms cancelled, some failed
|
||||
toast.warning(
|
||||
intl.formatMessage({
|
||||
id: "Some rooms were cancelled successfully, but we encountered issues with others. Please contact customer service for assistance.",
|
||||
defaultMessage:
|
||||
"Some rooms were cancelled successfully, but we encountered issues with others. Please contact customer service for assistance.",
|
||||
})
|
||||
)
|
||||
} else {
|
||||
// No rooms cancelled successfully
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
defaultMessage: "Something went wrong. Please try again later.",
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -162,7 +164,7 @@ export default function useCancelStay({
|
||||
console.error("Error in handleCancelStay:", error)
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
defaultMessage: "Something went wrong. Please try again later.",
|
||||
})
|
||||
)
|
||||
} finally {
|
||||
|
||||
@@ -59,15 +59,27 @@ export default function CancelStay({ hotel }: CancelStayProps) {
|
||||
function getModalCopy() {
|
||||
if (isFirstStep) {
|
||||
return {
|
||||
title: intl.formatMessage({ id: "Cancel stay" }),
|
||||
primaryLabel: intl.formatMessage({ id: "Cancel stay" }),
|
||||
secondaryLabel: intl.formatMessage({ id: "Back" }),
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Cancel stay",
|
||||
}),
|
||||
primaryLabel: intl.formatMessage({
|
||||
defaultMessage: "Cancel stay",
|
||||
}),
|
||||
secondaryLabel: intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
title: intl.formatMessage({ id: "Confirm cancellation" }),
|
||||
primaryLabel: intl.formatMessage({ id: "Confirm cancellation" }),
|
||||
secondaryLabel: intl.formatMessage({ id: "Don't cancel" }),
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Confirm cancellation",
|
||||
}),
|
||||
primaryLabel: intl.formatMessage({
|
||||
defaultMessage: "Confirm cancellation",
|
||||
}),
|
||||
secondaryLabel: intl.formatMessage({
|
||||
defaultMessage: "Don't cancel",
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,10 +96,11 @@ export default function CancelStay({ hotel }: CancelStayProps) {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "Contact the person who booked the stay",
|
||||
defaultMessage: "Contact the person who booked the stay",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "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.",
|
||||
defaultMessage:
|
||||
"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.",
|
||||
})}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -62,15 +62,22 @@ export function formatStayDetails({
|
||||
.diff(dt(checkInDate).startOf("day"), "days")
|
||||
|
||||
const nightsText = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights: diff }
|
||||
)
|
||||
const adultsText = intl.formatMessage(
|
||||
{ id: "{totalAdults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{ totalAdults: totalAdults }
|
||||
)
|
||||
const childrenText = intl.formatMessage(
|
||||
{ id: "{totalChildren, plural, one {# child} other {# children}}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalChildren, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{ totalChildren: totalChildren }
|
||||
)
|
||||
|
||||
@@ -138,11 +145,16 @@ export const useCheckedRoomsCounts = (
|
||||
const { totalAdults, totalChildren } = calculateTotals(matchedRooms)
|
||||
|
||||
const adultsText = intl.formatMessage(
|
||||
{ id: "{totalAdults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{ totalAdults: totalAdults }
|
||||
)
|
||||
const childrenText = intl.formatMessage(
|
||||
{ id: "{totalChildren, plural, one {# child} other {# children}}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalChildren, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{ totalChildren: totalChildren }
|
||||
)
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ export default function Confirmation({
|
||||
.diff(dt(newCheckIn).startOf("day"), "days")
|
||||
|
||||
const nightsText = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights: diff }
|
||||
)
|
||||
|
||||
@@ -69,7 +71,9 @@ export default function Confirmation({
|
||||
type="bold"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
{intl.formatMessage({ id: "Old dates" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Old dates",
|
||||
})}
|
||||
</Caption>
|
||||
<Body color="uiTextMediumContrast">
|
||||
{oldPrice} {currencyCode}
|
||||
@@ -82,7 +86,9 @@ export default function Confirmation({
|
||||
type="bold"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
{intl.formatMessage({ id: "Check-in" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-in",
|
||||
})}
|
||||
</Caption>
|
||||
<Body color="uiTextMediumContrast">{originalCheckIn}</Body>
|
||||
</div>
|
||||
@@ -92,7 +98,9 @@ export default function Confirmation({
|
||||
type="bold"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
{intl.formatMessage({ id: "Check-out" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-out",
|
||||
})}
|
||||
</Caption>
|
||||
<Body color="uiTextMediumContrast">{originalCheckOut}</Body>
|
||||
</div>
|
||||
@@ -104,7 +112,9 @@ export default function Confirmation({
|
||||
<div className={styles.dateGroup}>
|
||||
<div className={styles.dateHeader}>
|
||||
<Caption color="red" type="bold" textTransform="uppercase">
|
||||
{intl.formatMessage({ id: "New dates" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "New dates",
|
||||
})}
|
||||
</Caption>
|
||||
<Body color="red">
|
||||
{newPrice} {currencyCode}
|
||||
@@ -117,7 +127,9 @@ export default function Confirmation({
|
||||
type="bold"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
{intl.formatMessage({ id: "Check-in" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-in",
|
||||
})}
|
||||
</Caption>
|
||||
<Body color="uiTextMediumContrast">{newCheckIn}</Body>
|
||||
</div>
|
||||
@@ -127,7 +139,9 @@ export default function Confirmation({
|
||||
type="bold"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
{intl.formatMessage({ id: "Check-out" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-out",
|
||||
})}
|
||||
</Caption>
|
||||
<Body color="uiTextMediumContrast">{newCheckOut}</Body>
|
||||
</div>
|
||||
@@ -136,7 +150,9 @@ export default function Confirmation({
|
||||
</div>
|
||||
|
||||
<PriceContainer
|
||||
text={intl.formatMessage({ id: "To be paid" })}
|
||||
text={intl.formatMessage({
|
||||
defaultMessage: "To be paid",
|
||||
})}
|
||||
price={newPrice}
|
||||
currencyCode={currencyCode}
|
||||
nightsText={nightsText}
|
||||
|
||||
@@ -131,25 +131,31 @@ export default function NewDates({
|
||||
{noAvailability && (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({ id: "No availability" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "No availability",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "No single rooms are available on these dates",
|
||||
defaultMessage: "No single rooms are available on these dates",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{error && (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Alarm}
|
||||
heading={intl.formatMessage({ id: "Error" })}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "Error",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "Something went wrong!",
|
||||
defaultMessage: "Something went wrong!",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.container}>
|
||||
<div className={styles.checkInDate}>
|
||||
<Caption color="uiTextHighContrast" type="bold">
|
||||
{intl.formatMessage({ id: "Check-in" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-in",
|
||||
})}
|
||||
</Caption>
|
||||
|
||||
<CalendarButton
|
||||
@@ -161,7 +167,9 @@ export default function NewDates({
|
||||
</div>
|
||||
<div className={styles.checkOutDate}>
|
||||
<Caption color="uiTextHighContrast" type="bold">
|
||||
{intl.formatMessage({ id: "Check-out" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-out",
|
||||
})}
|
||||
</Caption>
|
||||
|
||||
<CalendarButton
|
||||
|
||||
@@ -40,7 +40,11 @@ export default function useModifyStay({
|
||||
onMutate: () => setIsLoading(true),
|
||||
onSuccess: (updatedBooking) => {
|
||||
if (!updatedBooking) {
|
||||
toast.error(intl.formatMessage({ id: "Failed to update your stay" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to update your stay",
|
||||
})
|
||||
)
|
||||
return
|
||||
}
|
||||
// Update room details with server response data
|
||||
@@ -50,11 +54,19 @@ export default function useModifyStay({
|
||||
checkOutDate: updatedBooking.checkOutDate,
|
||||
})
|
||||
|
||||
toast.success(intl.formatMessage({ id: "Your stay was updated" }))
|
||||
toast.success(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Your stay was updated",
|
||||
})
|
||||
)
|
||||
handleCloseModal()
|
||||
},
|
||||
onError: () => {
|
||||
toast.error(intl.formatMessage({ id: "Failed to update your stay" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Failed to update your stay",
|
||||
})
|
||||
)
|
||||
},
|
||||
onSettled: () => {
|
||||
setIsLoading(false)
|
||||
@@ -65,7 +77,11 @@ export default function useModifyStay({
|
||||
const formValues = getFormValues()
|
||||
|
||||
if (!formValues.checkInDate || !formValues.checkOutDate) {
|
||||
toast.error(intl.formatMessage({ id: "Please select dates" }))
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Please select dates",
|
||||
})
|
||||
)
|
||||
return { success: false }
|
||||
}
|
||||
|
||||
@@ -146,7 +162,7 @@ export default function useModifyStay({
|
||||
console.error("Error modifying stay:", error)
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Failed to update your stay. Please try again later.",
|
||||
defaultMessage: "Failed to update your stay. Please try again later.",
|
||||
})
|
||||
)
|
||||
setIsLoading(false)
|
||||
|
||||
@@ -98,10 +98,11 @@ export default function ModifyStay({ isLoggedIn }: ModifyStayProps) {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "Contact customer service",
|
||||
defaultMessage: "Contact customer service",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "As this is a multiroom stay, any dates changes are applicable to all rooms. Please contact customer service to update the dates.",
|
||||
defaultMessage:
|
||||
"As this is a multiroom stay, any dates changes are applicable to all rooms. Please contact customer service to update the dates.",
|
||||
})}
|
||||
/>
|
||||
)
|
||||
@@ -111,10 +112,11 @@ export default function ModifyStay({ isLoggedIn }: ModifyStayProps) {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "Contact customer service",
|
||||
defaultMessage: "Contact customer service",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "Please contact customer service to update the dates.",
|
||||
defaultMessage:
|
||||
"Please contact customer service to update the dates.",
|
||||
})}
|
||||
/>
|
||||
)
|
||||
@@ -142,10 +144,11 @@ export default function ModifyStay({ isLoggedIn }: ModifyStayProps) {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "Contact the person who booked the stay",
|
||||
defaultMessage: "Contact the person who booked the stay",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "As this is a multiroom stay, any dates changes are applicable to all rooms. Please ask the person who booked the stay to contact customer service.",
|
||||
defaultMessage:
|
||||
"As this is a multiroom stay, any dates changes are applicable to all rooms. Please ask the person who booked the stay to contact customer service.",
|
||||
})}
|
||||
/>
|
||||
)
|
||||
@@ -156,8 +159,12 @@ export default function ModifyStay({ isLoggedIn }: ModifyStayProps) {
|
||||
<ModalContentWithActions
|
||||
title={
|
||||
isFirstStep
|
||||
? intl.formatMessage({ id: "New dates for the stay" })
|
||||
: intl.formatMessage({ id: "Confirm date change" })
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "New dates for the stay",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Confirm date change",
|
||||
})
|
||||
}
|
||||
content={getModalContent()}
|
||||
onClose={handleCloseModal}
|
||||
@@ -165,8 +172,12 @@ export default function ModifyStay({ isLoggedIn }: ModifyStayProps) {
|
||||
mainRoom && !multiRoom && canChangeDate
|
||||
? {
|
||||
label: isFirstStep
|
||||
? intl.formatMessage({ id: "Check availability" })
|
||||
: intl.formatMessage({ id: "Confirm" }),
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Check availability",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Confirm",
|
||||
}),
|
||||
onClick: isFirstStep ? onCheckAvailability : handleModifyStay,
|
||||
intent: isFirstStep ? "secondary" : "primary",
|
||||
isLoading: isLoading,
|
||||
@@ -176,8 +187,12 @@ export default function ModifyStay({ isLoggedIn }: ModifyStayProps) {
|
||||
}
|
||||
secondaryAction={{
|
||||
label: isFirstStep
|
||||
? intl.formatMessage({ id: "Back" })
|
||||
: intl.formatMessage({ id: "Cancel" }),
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Cancel",
|
||||
}),
|
||||
onClick: isFirstStep ? handleCloseView : handleCloseModal,
|
||||
intent: "text",
|
||||
}}
|
||||
|
||||
@@ -29,7 +29,9 @@ export default function PriceContainer({
|
||||
{text}
|
||||
</Caption>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{nightsText}, {adultsText}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{totalChildren > 0 ? `, ${childrenText}` : ""}
|
||||
</Caption>
|
||||
</div>
|
||||
|
||||
@@ -139,7 +139,9 @@ export default function ActionPanel({ hotel }: ActionPanelProps) {
|
||||
className={styles.button}
|
||||
disabled={!isDateModifyable}
|
||||
>
|
||||
{intl.formatMessage({ id: "Modify dates" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Modify dates",
|
||||
})}
|
||||
<MaterialIcon icon="calendar_month" color="CurrentColor" />
|
||||
</Button>
|
||||
|
||||
@@ -150,7 +152,9 @@ export default function ActionPanel({ hotel }: ActionPanelProps) {
|
||||
className={styles.button}
|
||||
disabled={!isGuaranteeable}
|
||||
>
|
||||
{intl.formatMessage({ id: "Guarantee late arrival" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Guarantee late arrival",
|
||||
})}
|
||||
<MaterialIcon icon="credit_card" color="CurrentColor" />
|
||||
</Button>
|
||||
|
||||
@@ -173,13 +177,19 @@ export default function ActionPanel({ hotel }: ActionPanelProps) {
|
||||
className={styles.actionLink}
|
||||
onClick={handleDownloadInvoice}
|
||||
>
|
||||
{intl.formatMessage({ id: "Download invoice" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Download invoice",
|
||||
})}
|
||||
<MaterialIcon icon="download" color="CurrentColor" />
|
||||
</Link>
|
||||
) : (
|
||||
<div className={styles.disabledLink}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "Download invoice" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Download invoice",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
<MaterialIcon icon="download" color="CurrentColor" />
|
||||
@@ -193,14 +203,18 @@ export default function ActionPanel({ hotel }: ActionPanelProps) {
|
||||
className={styles.button}
|
||||
disabled={!isCancelable}
|
||||
>
|
||||
{intl.formatMessage({ id: "Cancel stay" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Cancel stay",
|
||||
})}
|
||||
<MaterialIcon icon="cancel" color="CurrentColor" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className={styles.info}>
|
||||
<div>
|
||||
<span className={styles.tag}>
|
||||
{intl.formatMessage({ id: "Reference number" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Reference number",
|
||||
})}
|
||||
</span>
|
||||
<Subtitle color="burgundy" textAlign="right">
|
||||
{confirmationNumber}
|
||||
@@ -229,7 +243,9 @@ export default function ActionPanel({ hotel }: ActionPanelProps) {
|
||||
onClick={handleCustomerSupport}
|
||||
>
|
||||
<Caption color="burgundy">
|
||||
{intl.formatMessage({ id: "Customer support" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Customer support",
|
||||
})}
|
||||
</Caption>
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Link>
|
||||
|
||||
@@ -77,7 +77,9 @@ export default function ManageStay({
|
||||
disabled={allRoomsCancelled}
|
||||
className={styles.manageStayButton}
|
||||
>
|
||||
{intl.formatMessage({ id: "Manage stay" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Manage stay",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon="keyboard_arrow_down"
|
||||
color={
|
||||
|
||||
@@ -38,13 +38,17 @@ export default function ModifyContact({
|
||||
<div className={styles.container}>
|
||||
<div className={`${styles.row} ${styles.gridEqual}`}>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "First name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "First name",
|
||||
})}
|
||||
maxLength={30}
|
||||
name="firstName"
|
||||
disabled={!!guest.firstName}
|
||||
/>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Last name" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Last name",
|
||||
})}
|
||||
maxLength={30}
|
||||
name="lastName"
|
||||
disabled={!!guest.lastName}
|
||||
@@ -52,13 +56,17 @@ export default function ModifyContact({
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<CountrySelect
|
||||
label={intl.formatMessage({ id: "Country" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country",
|
||||
})}
|
||||
name="countryCode"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<Input
|
||||
label={intl.formatMessage({ id: "Email" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Email",
|
||||
})}
|
||||
name="email"
|
||||
type="email"
|
||||
registerOptions={{ required: true }}
|
||||
@@ -66,7 +74,9 @@ export default function ModifyContact({
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<Phone
|
||||
label={intl.formatMessage({ id: "Phone number" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Phone number",
|
||||
})}
|
||||
name="phoneNumber"
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
@@ -76,7 +86,8 @@ export default function ModifyContact({
|
||||
<>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage({
|
||||
id: "Are you sure you want to change your guest details?",
|
||||
defaultMessage:
|
||||
"Are you sure you want to change your guest details?",
|
||||
})}
|
||||
</Body>
|
||||
<div className={styles.container}>
|
||||
|
||||
@@ -135,7 +135,9 @@ export default function MultiRoom({
|
||||
const fromDate = dt(checkInDate).locale(lang)
|
||||
|
||||
const adultsMsg = intl.formatMessage(
|
||||
{ id: "{adults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{
|
||||
adults: adults,
|
||||
}
|
||||
@@ -143,7 +145,7 @@ export default function MultiRoom({
|
||||
|
||||
const childrenMsg = intl.formatMessage(
|
||||
{
|
||||
id: "{children, plural, one {# child} other {# children}}",
|
||||
defaultMessage: "{children, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{
|
||||
children: childrenAges.length,
|
||||
@@ -171,16 +173,25 @@ export default function MultiRoom({
|
||||
}
|
||||
>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span>{intl.formatMessage({ id: "Cancelled" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Cancelled",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
</IconChip>
|
||||
) : (
|
||||
<div className={styles.chip}>
|
||||
<Typography variant="Tag/sm">
|
||||
<span>
|
||||
{intl.formatMessage({ id: "Room" }) +
|
||||
" " +
|
||||
(index !== undefined ? index + 2 : 1)}
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{
|
||||
roomIndex: index !== undefined ? index + 2 : 1,
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -188,9 +199,21 @@ export default function MultiRoom({
|
||||
<div className={styles.reference}>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
{isCancelled ? (
|
||||
<span>{intl.formatMessage({ id: "Cancellation no" })}:</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Cancellation no",
|
||||
})}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{":"}
|
||||
</span>
|
||||
) : (
|
||||
<span>{intl.formatMessage({ id: "Reference" })}:</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Reference",
|
||||
})}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{":"}
|
||||
</span>
|
||||
)}
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
@@ -250,7 +273,11 @@ export default function MultiRoom({
|
||||
<div className={styles.details}>
|
||||
<div className={styles.row}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "Guests" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Guests",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
@@ -260,7 +287,11 @@ export default function MultiRoom({
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "Terms" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Terms",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{rateDefinition.cancellationText}</p>
|
||||
@@ -269,10 +300,15 @@ export default function MultiRoom({
|
||||
{hasModifiableRate(rateDefinition.cancellationRule) && (
|
||||
<div className={styles.row}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "Modify By" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Modify By",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<p color="uiTextHighContrast">
|
||||
18:00, {fromDate.format("dddd D MMM")}
|
||||
</p>
|
||||
@@ -281,7 +317,11 @@ export default function MultiRoom({
|
||||
)}
|
||||
<div className={styles.row}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{intl.formatMessage({ id: "Breakfast" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Breakfast",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
@@ -291,15 +331,23 @@ export default function MultiRoom({
|
||||
code: pkg.code,
|
||||
})) ?? []
|
||||
)
|
||||
? intl.formatMessage({ id: "Included" })
|
||||
: intl.formatMessage({ id: "Not included" })}
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Included",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Not included",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<Divider color="subtle" />
|
||||
<div className={styles.row}>
|
||||
<Typography variant="Body/Lead text">
|
||||
<p>{intl.formatMessage({ id: "Room total" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Room total",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
{priceType === "points" ? (
|
||||
<Points points={roomPoints} variant="Body/Paragraph/mdBold" />
|
||||
@@ -307,7 +355,9 @@ export default function MultiRoom({
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ id: "{count} voucher" },
|
||||
{
|
||||
defaultMessage: "{count} voucher",
|
||||
},
|
||||
{ count: vouchers }
|
||||
)}
|
||||
</p>
|
||||
|
||||
@@ -24,7 +24,14 @@ export default function Points({
|
||||
return (
|
||||
<Typography variant={variant}>
|
||||
<p>
|
||||
{intl.formatNumber(points)} {intl.formatMessage({ id: "Points" })}
|
||||
{intl.formatNumber(points)}
|
||||
{
|
||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||
" "
|
||||
}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
)
|
||||
|
||||
@@ -130,7 +130,9 @@ export default function PriceDetailsTable({
|
||||
|
||||
const diff = dt(toDate).diff(fromDate, "days")
|
||||
const nights = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{ totalNights: diff }
|
||||
)
|
||||
const vatPercentage = vat / 100
|
||||
@@ -145,6 +147,31 @@ export default function PriceDetailsTable({
|
||||
return (
|
||||
<table className={styles.priceDetailsTable}>
|
||||
{rooms.map((room, idx) => {
|
||||
const totalAdultsMsg = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalAdults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{
|
||||
totalAdults: room.adults,
|
||||
}
|
||||
)
|
||||
|
||||
const totalChildrenMsg = intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalChildren, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{
|
||||
totalChildren: room.childrenInRoom.length,
|
||||
}
|
||||
)
|
||||
|
||||
const guestsCountMsg = [totalAdultsMsg]
|
||||
if (room.childrenInRoom.length) {
|
||||
guestsCountMsg.push(totalChildrenMsg)
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment key={idx}>
|
||||
<TableSection>
|
||||
@@ -154,7 +181,9 @@ export default function PriceDetailsTable({
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{ id: "Room {roomIndex}" },
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: idx + 1 }
|
||||
)}
|
||||
</span>
|
||||
@@ -164,7 +193,9 @@ export default function PriceDetailsTable({
|
||||
)}
|
||||
<TableSectionHeader title={room.roomName} subtitle={duration} />
|
||||
<Row
|
||||
label={intl.formatMessage({ id: "Average price per night" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Average price per night",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
room.roomPrice.perNight.local.price,
|
||||
@@ -186,7 +217,9 @@ export default function PriceDetailsTable({
|
||||
: null}
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({ id: "Room charge" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Room charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
room.roomPrice.perStay.local.price,
|
||||
@@ -199,11 +232,11 @@ export default function PriceDetailsTable({
|
||||
<Row
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
id: "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}{totalChildren, plural, =0 {} one {, # child} other {, # children}}) x {totalBreakfasts}",
|
||||
defaultMessage:
|
||||
"Breakfast ({guestsCount}) x {totalBreakfasts}",
|
||||
},
|
||||
{
|
||||
totalAdults: room.adults,
|
||||
totalChildren: room.childrenInRoom.length,
|
||||
guestsCount: guestsCountMsg.join(", "),
|
||||
totalBreakfasts: diff,
|
||||
}
|
||||
)}
|
||||
@@ -216,7 +249,7 @@ export default function PriceDetailsTable({
|
||||
<Row
|
||||
bold
|
||||
label={intl.formatMessage({
|
||||
id: "Breakfast charge",
|
||||
defaultMessage: "Breakfast charge",
|
||||
})}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
@@ -230,19 +263,32 @@ export default function PriceDetailsTable({
|
||||
)
|
||||
})}
|
||||
<TableSection>
|
||||
<TableSectionHeader title={intl.formatMessage({ id: "Total" })} />
|
||||
<TableSectionHeader
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
/>
|
||||
<Row
|
||||
label={intl.formatMessage({ id: "Price excluding VAT" })}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Price excluding VAT",
|
||||
})}
|
||||
value={formatPrice(intl, priceExclVat, totalPrice.local.currency)}
|
||||
/>
|
||||
<Row
|
||||
label={intl.formatMessage({ id: "VAT {vat}%" }, { vat })}
|
||||
label={intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "VAT {vat}%",
|
||||
},
|
||||
{ vat }
|
||||
)}
|
||||
value={formatPrice(intl, vatAmount, totalPrice.local.currency)}
|
||||
/>
|
||||
<tr className={styles.row}>
|
||||
<td>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Price including VAT" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})}
|
||||
</Body>
|
||||
</td>
|
||||
<td className={styles.price}>
|
||||
|
||||
@@ -24,7 +24,11 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
<div>
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Reference number" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Reference number",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>{booking.confirmationNumber}</dd>
|
||||
@@ -33,7 +37,11 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Room" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Room",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>{room?.name}</dd>
|
||||
@@ -42,7 +50,11 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Rate" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Rate",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>{booking.rateDefinition.title}</dd>
|
||||
@@ -51,7 +63,11 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Check-in" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-in",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>
|
||||
@@ -62,7 +78,11 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Check-out" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-out",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>
|
||||
@@ -75,7 +95,11 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
<div className={styles.rightColumn}>
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Number of nights" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Number of nights",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>
|
||||
@@ -86,12 +110,19 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Number of guests" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Number of guests",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>
|
||||
{intl.formatMessage(
|
||||
{ id: "{adults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage:
|
||||
"{adults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{ adults: booking.adults }
|
||||
)}
|
||||
{booking.childrenAges.length > 0 && (
|
||||
@@ -99,7 +130,8 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
{", "}
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "{children, plural, one {# child} other {# children}}",
|
||||
defaultMessage:
|
||||
"{children, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{ children: booking.childrenAges.length }
|
||||
)}
|
||||
@@ -111,7 +143,11 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Bed type" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Bed type",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>{room?.bedType.mainBed.description}</dd>
|
||||
@@ -121,23 +157,39 @@ export default async function Footer({ booking, room }: FooterProps) {
|
||||
{petRoomPackage && (
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Room classification" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Room classification",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>{intl.formatMessage({ id: "Pet-friendly" })}</dd>
|
||||
<dd>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Pet-friendly",
|
||||
})}
|
||||
</dd>
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Breakfast" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Breakfast",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>
|
||||
{booking.rateDefinition.breakfastIncluded
|
||||
? intl.formatMessage({ id: "Included" })
|
||||
: intl.formatMessage({ id: "Not included" })}
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Included",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Not included",
|
||||
})}
|
||||
</dd>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,9 @@ export default async function Specification({
|
||||
: ""
|
||||
const breakfastPointsString =
|
||||
breakfastTotalPriceInPoints > 0
|
||||
? `${breakfastTotalPriceInPoints} ${intl.formatMessage({ id: "Points" })}`
|
||||
? `${breakfastTotalPriceInPoints} ${intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})}`
|
||||
: ""
|
||||
const breakfastPlusString =
|
||||
breakfastMoneyString && breakfastPointsString ? " + " : ""
|
||||
@@ -59,23 +61,36 @@ export default async function Specification({
|
||||
{/****** The room ********/}
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span>
|
||||
{intl.formatMessage({ id: "Accommodation" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Accommodation",
|
||||
})}
|
||||
{!booking.rateDefinition.mustBeGuaranteed && (
|
||||
<>
|
||||
{" - "}
|
||||
{intl.formatMessage({ id: "Room is prepaid" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Room is prepaid",
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</Typography>
|
||||
<dl className={styles.dl}>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>{intl.formatMessage({ id: "Price including VAT" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>
|
||||
{!booking.rateDefinition.mustBeGuaranteed &&
|
||||
`(${intl.formatMessage({ id: "PREPAID" })}) `}
|
||||
{!booking.rateDefinition.mustBeGuaranteed
|
||||
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`(${intl.formatMessage({
|
||||
defaultMessage: "PREPAID",
|
||||
})}) `
|
||||
: null}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${booking.roomPrice} ${currency}`}
|
||||
</dd>
|
||||
</Typography>
|
||||
@@ -84,10 +99,13 @@ export default async function Specification({
|
||||
<>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>
|
||||
{intl.formatMessage({ id: "Pet room charge including VAT" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Pet room charge including VAT",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<dd>{`${petRoomPackage.totalPrice} ${petRoomPackage.currency}`}</dd>
|
||||
</Typography>
|
||||
</>
|
||||
@@ -95,24 +113,32 @@ export default async function Specification({
|
||||
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt className={styles.tertiary}>
|
||||
{intl.formatMessage({ id: "Price excluding VAT" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price excluding VAT",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd
|
||||
className={styles.tertiary}
|
||||
>{`${roomPriceExclVat.toFixed(2)} ${currency}`}</dd>
|
||||
<dd className={styles.tertiary}>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${roomPriceExclVat.toFixed(2)} ${currency}`}
|
||||
</dd>
|
||||
</Typography>
|
||||
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt className={styles.tertiary}>
|
||||
{intl.formatMessage({ id: "VAT" })} {booking.vatPercentage} %
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "VAT",
|
||||
})}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{` ${booking.vatPercentage} %`}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd
|
||||
className={styles.tertiary}
|
||||
>{`${roomPriceVat.toFixed(2)} ${currency}`}</dd>
|
||||
<dd className={styles.tertiary}>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${roomPriceVat.toFixed(2)} ${currency}`}
|
||||
</dd>
|
||||
</Typography>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -131,11 +157,17 @@ export default async function Specification({
|
||||
aa.id === ancillary.code ||
|
||||
aa.loyaltyCode === ancillary.code
|
||||
)
|
||||
)[0]?.title ?? intl.formatMessage({ id: "Unknown item" })}
|
||||
)[0]?.title ??
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Unknown item",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span>{`x ${ancillary.unit}`}</span>
|
||||
<span>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`× ${ancillary.unit}`}
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -143,12 +175,19 @@ export default async function Specification({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>
|
||||
{ancillary.currency !== CurrencyEnum.POINTS
|
||||
? intl.formatMessage({ id: "Price including VAT" })
|
||||
: intl.formatMessage({ id: "Price" })}
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Price",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>{`${ancillary.totalPrice} ${ancillary.currency}`}</dd>
|
||||
<dd>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${ancillary.totalPrice} ${ancillary.currency}`}
|
||||
</dd>
|
||||
</Typography>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -162,10 +201,15 @@ export default async function Specification({
|
||||
<div>
|
||||
<div className={styles.quantifyingHeader}>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span>{intl.formatMessage({ id: "Breakfast" })}</span>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Breakfast",
|
||||
})}
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span>{`x ${breakfastCount}`}</span>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<span>{`× ${breakfastCount}`}</span>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -173,12 +217,19 @@ export default async function Specification({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dt>
|
||||
{breakfastTotalPriceInMoney > 0
|
||||
? intl.formatMessage({ id: "Price including VAT" })
|
||||
: intl.formatMessage({ id: "Price" })}
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Price including VAT",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Price",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<dd>{`${breakfastMoneyString}${breakfastPlusString}${breakfastPointsString}`}</dd>
|
||||
<dd>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${breakfastMoneyString}${breakfastPlusString}${breakfastPointsString}`}
|
||||
</dd>
|
||||
</Typography>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,9 @@ export default async function Total({ booking, currency }: TotalProps) {
|
||||
totalPriceInMoney > 0 ? `${totalPriceInMoney} ${currency}` : ""
|
||||
const pointsString =
|
||||
totalPriceInPoints > 0
|
||||
? `${totalPriceInPoints} ${intl.formatMessage({ id: "Points" })}`
|
||||
? `${totalPriceInPoints} ${intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
})}`
|
||||
: ""
|
||||
const plusString = moneyString && pointsString ? " + " : ""
|
||||
|
||||
@@ -33,11 +35,14 @@ export default async function Total({ booking, currency }: TotalProps) {
|
||||
<Typography>
|
||||
<div>
|
||||
<span className={styles.title}>
|
||||
{intl.formatMessage({ id: "Preliminary receipt" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Preliminary receipt",
|
||||
})}
|
||||
</span>
|
||||
<span className={styles.titleSubtext}>
|
||||
{intl.formatMessage({
|
||||
id: "Final VAT breakdown will be provided at check-out.",
|
||||
defaultMessage:
|
||||
"Final VAT breakdown will be provided at check-out.",
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
@@ -46,9 +51,14 @@ export default async function Total({ booking, currency }: TotalProps) {
|
||||
<Divider color="subtle" />
|
||||
<dl className={styles.dl}>
|
||||
<Typography>
|
||||
<dt>{intl.formatMessage({ id: "Total including VAT" })}</dt>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total including VAT",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<dd>{`${moneyString}${plusString}${pointsString}`}</dd>
|
||||
</Typography>
|
||||
|
||||
@@ -56,13 +66,16 @@ export default async function Total({ booking, currency }: TotalProps) {
|
||||
<>
|
||||
<Typography>
|
||||
<dt className={styles.tertiary}>
|
||||
{intl.formatMessage({ id: "Total excluding VAT" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total excluding VAT",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography>
|
||||
<dd
|
||||
className={styles.tertiary}
|
||||
>{`${totalPriceInMoneyExclVat} ${currency}`}</dd>
|
||||
<dd className={styles.tertiary}>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${totalPriceInMoneyExclVat} ${currency}`}
|
||||
</dd>
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
@@ -71,11 +84,16 @@ export default async function Total({ booking, currency }: TotalProps) {
|
||||
<>
|
||||
<Typography>
|
||||
<dt className={styles.tertiary}>
|
||||
{intl.formatMessage({ id: "VAT" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "VAT",
|
||||
})}
|
||||
</dt>
|
||||
</Typography>
|
||||
<Typography>
|
||||
<dd className={styles.tertiary}>{`${totalVat} ${currency}`}</dd>
|
||||
<dd className={styles.tertiary}>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${totalVat} ${currency}`}
|
||||
</dd>
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -72,6 +72,7 @@ export async function Receipt({ refId }: { refId: string }) {
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<div>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${hotel.address.streetAddress}, ${hotel.address.zipCode} ${hotel.address.city}`}
|
||||
</div>
|
||||
</Typography>
|
||||
@@ -88,11 +89,15 @@ export async function Receipt({ refId }: { refId: string }) {
|
||||
</div>
|
||||
<div className={styles.rightColumn}>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<div>{`${booking.guest.firstName} ${booking.guest.lastName}`}</div>
|
||||
</Typography>
|
||||
{booking.guest.membershipNumber && (
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<div>{`${intl.formatMessage({ id: "Member" })} ${booking.guest.membershipNumber}`}</div>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<div>{`${intl.formatMessage({
|
||||
defaultMessage: "Member",
|
||||
})} ${booking.guest.membershipNumber}`}</div>
|
||||
</Typography>
|
||||
)}
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
@@ -142,14 +147,15 @@ export async function Receipt({ refId }: { refId: string }) {
|
||||
<Typography variant="Title/md">
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
id: "You need to be logged in to view your booking",
|
||||
defaultMessage: "You need to be logged in to view your booking",
|
||||
})}
|
||||
</h1>
|
||||
</Typography>
|
||||
<Typography variant="Body/Lead text">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "And you need to be logged in with the same member account that made the booking.",
|
||||
defaultMessage:
|
||||
"And you need to be logged in with the same member account that made the booking.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
@@ -120,7 +120,9 @@ export function ReferenceCard({
|
||||
const allRoomsCancelled = allRooms.every((room) => room.isCancelled)
|
||||
|
||||
const adultsMsg = intl.formatMessage(
|
||||
{ id: "{adults, plural, one {# adult} other {# adults}}" },
|
||||
{
|
||||
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
|
||||
},
|
||||
{
|
||||
adults: adults,
|
||||
}
|
||||
@@ -128,7 +130,7 @@ export function ReferenceCard({
|
||||
|
||||
const childrenMsg = intl.formatMessage(
|
||||
{
|
||||
id: "{children, plural, one {# child} other {# children}}",
|
||||
defaultMessage: "{children, plural, one {# child} other {# children}}",
|
||||
},
|
||||
{
|
||||
children: children,
|
||||
@@ -136,16 +138,22 @@ export function ReferenceCard({
|
||||
)
|
||||
|
||||
const cancelledRoomsMsg = intl.formatMessage(
|
||||
{ id: "{rooms, plural, one {# room} other {# rooms}}" },
|
||||
{
|
||||
defaultMessage: "{rooms, plural, one {# room} other {# rooms}}",
|
||||
},
|
||||
{
|
||||
rooms: cancelledRooms,
|
||||
}
|
||||
)
|
||||
|
||||
const roomCancelledRoomsMsg = intl.formatMessage({ id: "Room cancelled" })
|
||||
const roomCancelledRoomsMsg = intl.formatMessage({
|
||||
defaultMessage: "Room cancelled",
|
||||
})
|
||||
|
||||
const roomsMsg = intl.formatMessage(
|
||||
{ id: "{rooms, plural, one {# room} other {# rooms}}" },
|
||||
{
|
||||
defaultMessage: "{rooms, plural, one {# room} other {# rooms}}",
|
||||
},
|
||||
{
|
||||
rooms: allRooms.filter((room) => !room.isCancelled).length,
|
||||
}
|
||||
@@ -163,15 +171,21 @@ export function ReferenceCard({
|
||||
<>
|
||||
<div className={styles.referenceRow}>
|
||||
<Subtitle color="uiTextHighContrast" className={styles.titleMobile}>
|
||||
{intl.formatMessage({ id: "Reference" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Reference",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Subtitle
|
||||
color="uiTextHighContrast"
|
||||
className={styles.titleDesktop}
|
||||
>
|
||||
{isCancelled && !isMultiRoom
|
||||
? intl.formatMessage({ id: "Cancellation number" })
|
||||
: intl.formatMessage({ id: "Reference number" })}
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Cancellation number",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Reference number",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Subtitle color="uiTextHighContrast">
|
||||
{isCancelled && !isMultiRoom
|
||||
@@ -187,7 +201,11 @@ export function ReferenceCard({
|
||||
{!allRoomsCancelled && (
|
||||
<div className={styles.referenceRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Guests" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Guests",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
@@ -205,12 +223,19 @@ export function ReferenceCard({
|
||||
{allRooms.some((room) => room.isCancelled) && (
|
||||
<div className={styles.referenceRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Cancellation" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Cancellation",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p className={styles.cancelledRooms}>
|
||||
{isMultiRoom
|
||||
? `${cancelledRoomsMsg} ${intl.formatMessage({ id: "cancelled" })}`
|
||||
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
`${cancelledRoomsMsg} ${intl.formatMessage({
|
||||
defaultMessage: "cancelled",
|
||||
})}`
|
||||
: roomCancelledRoomsMsg}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -220,21 +245,39 @@ export function ReferenceCard({
|
||||
<>
|
||||
<div className={styles.referenceRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Check-in" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-in",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{`${dt(checkInDate).locale(lang).format("dddd, D MMMM")} ${intl.formatMessage({ id: "from" })} ${hotel.hotelFacts.checkin.checkInTime}`}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${dt(checkInDate).locale(lang).format("dddd, D MMMM")} ${intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "from",
|
||||
}
|
||||
)} ${hotel.hotelFacts.checkin.checkInTime}`}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.referenceRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Check-out" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Check-out",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{`${dt(checkOutDate).locale(lang).format("dddd, D MMMM")} ${intl.formatMessage({ id: "until" })} ${hotel.hotelFacts.checkin.checkOutTime}`}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${dt(checkOutDate).locale(lang).format("dddd, D MMMM")} ${intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "until",
|
||||
}
|
||||
)} ${hotel.hotelFacts.checkin.checkOutTime}`}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -252,10 +295,15 @@ export function ReferenceCard({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p className={styles.guaranteedText}>
|
||||
<strong>
|
||||
{intl.formatMessage({ id: "Booking guaranteed." })}
|
||||
</strong>{" "}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Booking guaranteed.",
|
||||
})}
|
||||
</strong>
|
||||
{/* eslint-disable formatjs/no-literal-string-in-jsx */}{" "}
|
||||
{/* eslint-enable formatjs/no-literal-string-in-jsx */}
|
||||
{intl.formatMessage({
|
||||
id: "Your stay remains available for check-in after 18:00.",
|
||||
defaultMessage:
|
||||
"Your stay remains available for check-in after 18:00.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -266,14 +314,22 @@ export function ReferenceCard({
|
||||
|
||||
<div className={styles.referenceRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Total" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Total",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<TotalPrice variant="Title/Subtitle/md" type={priceType} />
|
||||
</div>
|
||||
{bookingCode && (
|
||||
<div className={styles.referenceRow}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<p>{intl.formatMessage({ id: "Booking code" })}</p>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Booking code",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<IconChip
|
||||
@@ -281,11 +337,14 @@ export function ReferenceCard({
|
||||
icon={<DiscountIcon color="Icon/Feedback/Information" />}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{ id: "<strong>Booking code</strong>: {value}" },
|
||||
{
|
||||
defaultMessage: "<strong>Booking code</strong>: {value}",
|
||||
},
|
||||
{
|
||||
value: bookingCode,
|
||||
strong: (text) => (
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<strong>{text}</strong>
|
||||
</Typography>
|
||||
),
|
||||
@@ -304,14 +363,18 @@ export function ReferenceCard({
|
||||
/>
|
||||
<Button fullWidth intent="secondary" asChild size="small">
|
||||
<Link href={directionsUrl} target="_blank">
|
||||
{intl.formatMessage({ id: "Get directions" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Get directions",
|
||||
})}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
{isMultiRoom && (
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<p className={styles.note}>
|
||||
{intl.formatMessage({ id: "Multi-room stay" })}
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Multi-room stay",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
)}
|
||||
@@ -323,6 +386,7 @@ export function ReferenceCard({
|
||||
{rateDefinition.generalTerms.map((term) => (
|
||||
<span key={term}>
|
||||
{term}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{term.endsWith(".") ? " " : ". "}
|
||||
</span>
|
||||
))}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user