Merged in feat/BOOK-529-update-GLA-design-mystay (pull request #3230)
Feat/BOOK-529 update GLA design mystay * feat(BOOK-529): update gla design on my stay * feat(BOOK-529): open gla modal if error * feat(BOOK-529): add inline accordion to storybook * feat(529): move errormessage below message * feat(529): update infomodal * feat(BOOK-529): update infomodal * feat(BOOK-529): hide guarantee info for adding ancillaries if prepaid * feat(BOOK-529): update width on info dialog * feat(BOOK-529): fix alignment * feat(BOOK-529): check if member price * feat(BOOK-529): refactor msg * feat(BOOK-529): refactor terms and conditions to own component * feat(BOOK-529): clean up confirmation step Approved-by: Christel Westerberg
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
||||
|
||||
import Modal from "@/components/HotelReservation/MyStay/Modal"
|
||||
import { isAncillaryError } from "@/components/HotelReservation/MyStay/utils"
|
||||
|
||||
import GuaranteeDialog from "../ManageStay/Actions/GuaranteeLateArrival/GuaranteeDialog"
|
||||
|
||||
export default function GuaranteePaymentFailed() {
|
||||
const intl = useIntl()
|
||||
const searchParams = useSearchParams()
|
||||
const pathname = usePathname()
|
||||
const router = useRouter()
|
||||
|
||||
const [alert, setAlert] = useState<{
|
||||
type: AlertTypeEnum
|
||||
message: string
|
||||
} | null>(null)
|
||||
|
||||
const getErrorMessage = useCallback(
|
||||
(errorCode: string | null) => {
|
||||
switch (errorCode) {
|
||||
case BookingErrorCodeEnum.TransactionCancelled:
|
||||
return intl.formatMessage({
|
||||
id: "guaranteePayment.cancelled",
|
||||
defaultMessage:
|
||||
"You have cancelled the payment. Your booking is not guaranteed.",
|
||||
})
|
||||
default:
|
||||
return intl.formatMessage({
|
||||
id: "guaranteePayment.failed",
|
||||
defaultMessage:
|
||||
"We had an issue guaranteeing your booking. Please try again.",
|
||||
})
|
||||
}
|
||||
},
|
||||
[intl]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const errorCode = searchParams.get("errorCode")
|
||||
if (!errorCode) {
|
||||
return
|
||||
}
|
||||
|
||||
if (isAncillaryError(searchParams)) {
|
||||
return
|
||||
}
|
||||
|
||||
const message = getErrorMessage(errorCode)
|
||||
const type =
|
||||
errorCode === BookingErrorCodeEnum.TransactionCancelled
|
||||
? AlertTypeEnum.Warning
|
||||
: AlertTypeEnum.Alarm
|
||||
|
||||
setAlert({ type, message })
|
||||
|
||||
const newParams = new URLSearchParams(searchParams.toString())
|
||||
newParams.delete("errorCode")
|
||||
|
||||
router.replace(`${pathname}?${newParams.toString()}`)
|
||||
}, [searchParams, pathname, router, getErrorMessage])
|
||||
|
||||
if (!alert) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isOpen={!!alert} onOpenChange={() => setAlert(null)}>
|
||||
<GuaranteeDialog error={alert} />
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
@@ -13,13 +13,18 @@
|
||||
gap: var(--Space-x3);
|
||||
}
|
||||
|
||||
.termsAndConditions {
|
||||
color: var(--Text-Secondary);
|
||||
display: grid;
|
||||
.guarantee {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Space-x2);
|
||||
background-color: var(--Surface-Secondary-Default);
|
||||
border-radius: var(--Corner-radius-lg);
|
||||
padding: var(--Space-x2);
|
||||
}
|
||||
|
||||
.termsAndConditions .checkbox span {
|
||||
.paymentInfo {
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,13 @@ import { useIntl } from "react-intl"
|
||||
|
||||
import { writeGlaToSessionStorage } from "@scandic-hotels/booking-flow/components/EnterDetails/Payment/PaymentCallback/helpers"
|
||||
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||
import { bookingTermsAndConditionsRoutes } from "@scandic-hotels/common/constants/routes/bookingTermsAndConditionsRoutes"
|
||||
import { guaranteeCallback } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
||||
import { privacyPolicyRoutes } from "@scandic-hotels/common/constants/routes/privacyPolicyRoutes"
|
||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import { Alert } from "@scandic-hotels/design-system/Alert"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||
import { SelectPaymentMethod } from "@scandic-hotels/design-system/Form/SelectPaymentMethod"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import { toast } from "@scandic-hotels/design-system/Toast"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { trackGlaSaveCardAttempt } from "@scandic-hotels/tracking/payment"
|
||||
@@ -23,6 +21,7 @@ import { isWebview } from "@/constants/routes/webviews"
|
||||
import { env } from "@/env/client"
|
||||
import { useMyStayStore } from "@/stores/my-stay"
|
||||
|
||||
import TermsAndConditions from "@/components/HotelReservation/MyStay/TermsAndConditions"
|
||||
import { useGuaranteeBooking } from "@/hooks/booking/useGuaranteeBooking"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||
@@ -31,7 +30,12 @@ import { type GuaranteeFormData, paymentSchema } from "./schema"
|
||||
|
||||
import styles from "./form.module.css"
|
||||
|
||||
export default function Form() {
|
||||
import type { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||
|
||||
interface FormProps {
|
||||
error?: { type: AlertTypeEnum; message: string }
|
||||
}
|
||||
export default function Form({ error }: FormProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
const pathname = usePathname()
|
||||
@@ -114,38 +118,6 @@ export default function Form() {
|
||||
}
|
||||
}
|
||||
|
||||
const guaranteeMsg = intl.formatMessage(
|
||||
{
|
||||
id: "myStay.gla.termsAndConditionsMessage",
|
||||
defaultMessage:
|
||||
"I accept the terms for this stay and the general <termsAndConditionsLink>Booking & Cancellation Terms</termsAndConditionsLink>, and understand Scandic will process my personal data for this stay in accordance with <privacyPolicyLink>Scandic's Privacy Policy</privacyPolicyLink>.",
|
||||
},
|
||||
{
|
||||
termsAndConditionsLink: (str) => (
|
||||
<Link
|
||||
textDecoration="underline"
|
||||
color="Text/Interactive/Secondary"
|
||||
target="_blank"
|
||||
href={bookingTermsAndConditionsRoutes[lang]}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{str}
|
||||
</Link>
|
||||
),
|
||||
privacyPolicyLink: (str) => (
|
||||
<Link
|
||||
textDecoration="underline"
|
||||
color="Text/Interactive/Secondary"
|
||||
target="_blank"
|
||||
href={privacyPolicyRoutes[lang]}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{str}
|
||||
</Link>
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<form
|
||||
@@ -153,24 +125,56 @@ export default function Form() {
|
||||
id="guarantee"
|
||||
onSubmit={methods.handleSubmit(handleGuaranteeLateArrival)}
|
||||
>
|
||||
<SelectPaymentMethod
|
||||
paymentMethods={(savedCreditCards ?? []).map((card) => ({
|
||||
...card,
|
||||
cardType: card.cardType as PaymentMethodEnum,
|
||||
}))}
|
||||
onChange={(method) => {
|
||||
trackUpdatePaymentMethod({ method })
|
||||
}}
|
||||
formName="paymentMethod"
|
||||
/>
|
||||
|
||||
<div className={styles.termsAndConditions}>
|
||||
<Checkbox className={styles.checkbox} name="termsAndConditions">
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>{guaranteeMsg}</p>
|
||||
{error && <Alert type={error.type} text={error.message} />}
|
||||
<div className={styles.guarantee}>
|
||||
<div className={styles.paymentInfo}>
|
||||
<MaterialIcon icon="credit_card" size={24} color="CurrentColor" />
|
||||
<span>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.guarantee.headingText",
|
||||
defaultMessage: "Planning to arrive after 18.00?",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.guarantee.infoText",
|
||||
defaultMessage:
|
||||
"Guarantee with a credit card is required to secure your booking. Without this guarantee, your room may be released after 18:00 in case of no-show.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.paymentInfo}>
|
||||
<MaterialIcon icon="credit_score" size={24} color="CurrentColor" />
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.guarantee.headingText",
|
||||
defaultMessage:
|
||||
"Confirm and provide your payment card details in the next step",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</Checkbox>
|
||||
</div>
|
||||
{savedCreditCards && <Divider />}
|
||||
<SelectPaymentMethod
|
||||
paymentMethods={(savedCreditCards ?? []).map((card) => ({
|
||||
...card,
|
||||
cardType: card.cardType as PaymentMethodEnum,
|
||||
}))}
|
||||
onChange={(method) => {
|
||||
trackUpdatePaymentMethod({ method })
|
||||
}}
|
||||
formName="paymentMethod"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<TermsAndConditions />
|
||||
<div className={styles.guaranteeCost}>
|
||||
<div className={styles.guaranteeCostText}>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const paymentError = {
|
||||
TERMS_REQUIRED: "TERMS_REQUIRED",
|
||||
} as const
|
||||
|
||||
export const paymentSchema = z.object({
|
||||
paymentMethod: z.string().nullable(),
|
||||
termsAndConditions: z.boolean().refine((value) => value === true, {
|
||||
message: "You must accept the terms and conditions",
|
||||
}),
|
||||
termsAndConditions: z
|
||||
.boolean()
|
||||
.refine((value) => value === true, paymentError.TERMS_REQUIRED),
|
||||
})
|
||||
|
||||
export type GuaranteeFormData = z.output<typeof paymentSchema>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
.dialog {
|
||||
max-width: 690px;
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Dialog } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Modal from "@/components/HotelReservation/MyStay/Modal"
|
||||
|
||||
import Form from "../Form"
|
||||
|
||||
import styles from "./guaranteeDialog.module.css"
|
||||
|
||||
import type { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||
|
||||
interface GuaranteeDialogProps {
|
||||
error?: { type: AlertTypeEnum; message: string }
|
||||
}
|
||||
|
||||
export default function GuaranteeDialog({ error }: GuaranteeDialogProps) {
|
||||
const intl = useIntl()
|
||||
const text = intl.formatMessage({
|
||||
id: "myStay.gla.heading",
|
||||
defaultMessage: "Add late arrival guarantee",
|
||||
})
|
||||
return (
|
||||
<Dialog className={styles.dialog}>
|
||||
{({ close }) => (
|
||||
<Modal.Content>
|
||||
<Modal.Content.Header handleClose={close} title={text} />
|
||||
<Modal.Content.Body>
|
||||
<Form error={error} />
|
||||
</Modal.Content.Body>
|
||||
<Modal.Content.Footer>
|
||||
<Modal.Content.Footer.Secondary onClick={close}>
|
||||
{intl.formatMessage({
|
||||
id: "common.back",
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</Modal.Content.Footer.Secondary>
|
||||
<Modal.Content.Footer.Primary form="guarantee" type="submit">
|
||||
{intl.formatMessage({
|
||||
id: "common.confirm",
|
||||
defaultMessage: "Confirm",
|
||||
})}
|
||||
</Modal.Content.Footer.Primary>
|
||||
</Modal.Content.Footer>
|
||||
</Modal.Content>
|
||||
)}
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -1,18 +1,14 @@
|
||||
"use client"
|
||||
import { Dialog, DialogTrigger } from "react-aria-components"
|
||||
import { DialogTrigger } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { useMyStayStore } from "@/stores/my-stay"
|
||||
|
||||
import Modal from "@/components/HotelReservation/MyStay/Modal"
|
||||
import { trackMyStayPageLink } from "@/utils/tracking"
|
||||
|
||||
import ActionsButton from "../ActionsButton"
|
||||
import Form from "./Form"
|
||||
|
||||
import styles from "./guarantee.module.css"
|
||||
import GuaranteeDialog from "./GuaranteeDialog"
|
||||
|
||||
export default function GuaranteeLateArrival() {
|
||||
const intl = useIntl()
|
||||
@@ -29,14 +25,9 @@ export default function GuaranteeLateArrival() {
|
||||
trackMyStayPageLink("guarantee late arrival")
|
||||
}
|
||||
|
||||
const arriveLateMsg = intl.formatMessage({
|
||||
id: "myStay.gla.arriveLateMessage",
|
||||
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.",
|
||||
})
|
||||
const text = intl.formatMessage({
|
||||
id: "myStay.gla.heading",
|
||||
defaultMessage: "Guarantee late arrival",
|
||||
defaultMessage: "Add late arrival guarantee",
|
||||
})
|
||||
|
||||
return (
|
||||
@@ -47,34 +38,7 @@ export default function GuaranteeLateArrival() {
|
||||
icon="check"
|
||||
/>
|
||||
<Modal>
|
||||
<Dialog className={styles.dialog}>
|
||||
{({ close }) => (
|
||||
<Modal.Content>
|
||||
<Modal.Content.Header handleClose={close} title={text}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{arriveLateMsg}</p>
|
||||
</Typography>
|
||||
</Modal.Content.Header>
|
||||
<Modal.Content.Body>
|
||||
<Form />
|
||||
</Modal.Content.Body>
|
||||
<Modal.Content.Footer>
|
||||
<Modal.Content.Footer.Secondary onClick={close}>
|
||||
{intl.formatMessage({
|
||||
id: "common.back",
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</Modal.Content.Footer.Secondary>
|
||||
<Modal.Content.Footer.Primary form="guarantee" type="submit">
|
||||
{intl.formatMessage({
|
||||
id: "myStay.gla.guarantee",
|
||||
defaultMessage: "Guarantee",
|
||||
})}
|
||||
</Modal.Content.Footer.Primary>
|
||||
</Modal.Content.Footer>
|
||||
</Modal.Content>
|
||||
)}
|
||||
</Dialog>
|
||||
<GuaranteeDialog />
|
||||
</Modal>
|
||||
</DialogTrigger>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
align-content: start;
|
||||
margin-top: var(--Space-x2);
|
||||
}
|
||||
|
||||
.infoButton {
|
||||
background-color: transparent;
|
||||
border-width: 0;
|
||||
padding: var(--Space-x025);
|
||||
color: var(--Icon-Interactive-Default);
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
justify-self: stretch;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.content {
|
||||
max-width: 512px;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
justify-self: end;
|
||||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.textSecondary {
|
||||
color: var(--Text-Secondary);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import Modal from "@scandic-hotels/design-system/Modal"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import styles from "./guaranteeInfoModal.module.css"
|
||||
|
||||
export function GuaranteeInfoModal() {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<>
|
||||
<ButtonRAC
|
||||
type="button"
|
||||
className={styles.infoButton}
|
||||
onPress={() => setIsOpen(true)}
|
||||
>
|
||||
<MaterialIcon icon="info" size={20} color="CurrentColor" />
|
||||
</ButtonRAC>
|
||||
<Modal
|
||||
title={intl.formatMessage({
|
||||
id: "myStay.guaranteeInfoModal.heading",
|
||||
defaultMessage: "Your booking is guaranteed",
|
||||
})}
|
||||
isOpen={isOpen}
|
||||
onToggle={setIsOpen}
|
||||
>
|
||||
<div className={styles.content}>
|
||||
<Typography variant="Body/Lead text">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.guaranteeInfo.description",
|
||||
defaultMessage:
|
||||
"The hotel will hold your booking, even if you arrive after 18:00. In case of a no-show, you will be charged for the first night.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="Body/Paragraph/mdRegular"
|
||||
className={styles.textSecondary}
|
||||
>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.guaranteeInfoModal.ancillariesInfo",
|
||||
defaultMessage:
|
||||
"If you added extras, they'll be charged in case of a no-show, unless cancelled by 23:59 the night before.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
<Button
|
||||
className={styles.closeButton}
|
||||
variant="Secondary"
|
||||
color="Primary"
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
onPress={() => setIsOpen(false)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
}
|
||||
|
||||
.label {
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
@@ -13,3 +13,9 @@
|
||||
.textDefault {
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.guaranteeInfo {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--Space-x05);
|
||||
}
|
||||
|
||||
@@ -6,20 +6,20 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { useMyStayStore } from "@/stores/my-stay"
|
||||
|
||||
import { GuaranteeInfoModal } from "./GuaranteeInfoModal"
|
||||
|
||||
import styles from "./guaranteeInfo.module.css"
|
||||
|
||||
export default function GuaranteeInfo() {
|
||||
const intl = useIntl()
|
||||
const { allRoomsAreCancelled, guaranteeInfo, priceType } = useMyStayStore(
|
||||
(state) => ({
|
||||
allRoomsAreCancelled: state.allRoomsAreCancelled,
|
||||
const { isGuaranteeable, guaranteeInfo, allRoomsAreCancelled } =
|
||||
useMyStayStore((state) => ({
|
||||
isGuaranteeable: state.bookedRoom.isGuaranteeable,
|
||||
guaranteeInfo: state.bookedRoom.guaranteeInfo,
|
||||
priceType: state.bookedRoom.priceType,
|
||||
})
|
||||
)
|
||||
allRoomsAreCancelled: state.allRoomsAreCancelled,
|
||||
}))
|
||||
|
||||
const isRewardNight = priceType === "points"
|
||||
if (allRoomsAreCancelled || (!guaranteeInfo && !isRewardNight)) {
|
||||
if ((isGuaranteeable && !guaranteeInfo) || allRoomsAreCancelled) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -30,20 +30,23 @@ export default function GuaranteeInfo() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.textDefault}>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.lateArrival",
|
||||
defaultMessage: "Late arrival",
|
||||
id: "myStay.bookingGuaranteed",
|
||||
defaultMessage: "Booking guaranteed",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.guaranteeInfo}>
|
||||
<GuaranteeInfoModal />
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.roomHeldAfter18",
|
||||
defaultMessage: "Room held after 18:00",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myStay.checkInAfter18",
|
||||
defaultMessage: "Check-in after 18:00",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,9 +4,8 @@ import { useIntl } from "react-intl"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { useGuaranteePaymentFailedToast } from "@/hooks/booking/useGuaranteePaymentFailedToast"
|
||||
|
||||
import TotalPrice from "../Rooms/TotalPrice"
|
||||
import GuaranteePaymentFailed from "./Actions/Upcoming/GuaranteePaymentFailed"
|
||||
import Actions from "./Actions"
|
||||
import BookingCode from "./BookingCode"
|
||||
import Cancellations from "./Cancellations"
|
||||
@@ -20,7 +19,6 @@ import styles from "./referenceCard.module.css"
|
||||
|
||||
export function ReferenceCard() {
|
||||
const intl = useIntl()
|
||||
useGuaranteePaymentFailedToast()
|
||||
return (
|
||||
<div className={styles.referenceCard}>
|
||||
<Reference />
|
||||
@@ -44,6 +42,7 @@ export function ReferenceCard() {
|
||||
</div>
|
||||
<BookingCode />
|
||||
<Actions />
|
||||
<GuaranteePaymentFailed />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
}
|
||||
|
||||
.row {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: var(--Space-x1);
|
||||
gap: var(--Space-x2);
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user