Merged in fix/BOOK-529-my-stay-guarantee (pull request #3282)
fix(BOOK-529): add card icon to payment cards, show scrollbar, add missing text * fix(BOOK-529): add card icon to payment cards, show scrollbar, add missing text * fix(BOOK-529): refactor savdecard * fix(BOOK-529): fix lokaliseid * fix(BOOK-529): paymentmethods Approved-by: Joakim Jäderberg
This commit is contained in:
@@ -20,6 +20,14 @@
|
|||||||
padding: var(--Space-x2);
|
padding: var(--Space-x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.refundPolicy {
|
||||||
|
color: var(--Text-Secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pointsAvailable {
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
|
||||||
.paymentInfo {
|
.paymentInfo {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--Space-x1);
|
gap: var(--Space-x1);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { useWatch } from "react-hook-form"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
|
||||||
import AccordionItem from "@scandic-hotels/design-system/Accordion/AccordionItem"
|
import AccordionItem from "@scandic-hotels/design-system/Accordion/AccordionItem"
|
||||||
import { Alert } from "@scandic-hotels/design-system/Alert"
|
import { Alert } from "@scandic-hotels/design-system/Alert"
|
||||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||||
@@ -15,7 +14,6 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
|||||||
import { useAddAncillaryStore } from "@/stores/my-stay/add-ancillary-flow"
|
import { useAddAncillaryStore } from "@/stores/my-stay/add-ancillary-flow"
|
||||||
|
|
||||||
import TermsAndConditions from "@/components/HotelReservation/MyStay/TermsAndConditions"
|
import TermsAndConditions from "@/components/HotelReservation/MyStay/TermsAndConditions"
|
||||||
import useLang from "@/hooks/useLang"
|
|
||||||
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||||
|
|
||||||
import Summary from "../Summary"
|
import Summary from "../Summary"
|
||||||
@@ -30,19 +28,15 @@ export default function ConfirmationStep({
|
|||||||
error,
|
error,
|
||||||
}: ConfirmationStepProps) {
|
}: ConfirmationStepProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const lang = useLang()
|
|
||||||
|
|
||||||
const { checkInDate, guaranteeInfo, selectedAncillary, booking } =
|
const { guaranteeInfo, selectedAncillary, booking } = useAddAncillaryStore(
|
||||||
useAddAncillaryStore((state) => ({
|
(state) => ({
|
||||||
checkInDate: state.booking.checkInDate,
|
checkInDate: state.booking.checkInDate,
|
||||||
guaranteeInfo: state.booking.guaranteeInfo,
|
guaranteeInfo: state.booking.guaranteeInfo,
|
||||||
selectedAncillary: state.selectedAncillary,
|
selectedAncillary: state.selectedAncillary,
|
||||||
booking: state.booking,
|
booking: state.booking,
|
||||||
}))
|
})
|
||||||
const refundableDate = dt(checkInDate)
|
)
|
||||||
.subtract(1, "day")
|
|
||||||
.locale(lang)
|
|
||||||
.format("23:59, dddd, D MMMM YYYY")
|
|
||||||
|
|
||||||
const mustBeGuaranteed = !guaranteeInfo && booking.isGuaranteeable
|
const mustBeGuaranteed = !guaranteeInfo && booking.isGuaranteeable
|
||||||
const quantityWithCard = useWatch({ name: "quantityWithCard" })
|
const quantityWithCard = useWatch({ name: "quantityWithCard" })
|
||||||
@@ -99,7 +93,7 @@ export default function ConfirmationStep({
|
|||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<Typography variant="Body/Paragraph/mdRegular">
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
<p>
|
<p className={styles.pointsAvailable}>
|
||||||
{intl.formatMessage(
|
{intl.formatMessage(
|
||||||
{
|
{
|
||||||
id: "addAncillary.confirmationStep.pointsAvailable",
|
id: "addAncillary.confirmationStep.pointsAvailable",
|
||||||
@@ -112,7 +106,7 @@ export default function ConfirmationStep({
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!!quantityWithCard && (
|
{!!quantityWithCard ? (
|
||||||
<>
|
<>
|
||||||
<Typography variant="Title/Subtitle/md">
|
<Typography variant="Title/Subtitle/md">
|
||||||
<h2>
|
<h2>
|
||||||
@@ -123,15 +117,12 @@ export default function ConfirmationStep({
|
|||||||
</h2>
|
</h2>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="Body/Paragraph/mdRegular">
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
<p>
|
<p className={styles.refundPolicy}>
|
||||||
{intl.formatMessage(
|
{intl.formatMessage({
|
||||||
{
|
id: "addAncillary.confirmationStep.refundPolicyNightBefore",
|
||||||
id: "addAncillary.confirmationStep.refundPolicy",
|
defaultMessage:
|
||||||
defaultMessage:
|
"All extras can be cancelled until 23:59 the night before arrival. Time selection and special requests can also be modified.",
|
||||||
"All ancillaries are fully refundable until {date}. Time selection and special requests are also modifiable.",
|
})}
|
||||||
},
|
|
||||||
{ date: refundableDate }
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
<div className={styles.guarantee}>
|
<div className={styles.guarantee}>
|
||||||
@@ -171,6 +162,7 @@ export default function ConfirmationStep({
|
|||||||
<PaymentOptionsGroup name="paymentMethod">
|
<PaymentOptionsGroup name="paymentMethod">
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
value={PaymentMethodEnum.card}
|
value={PaymentMethodEnum.card}
|
||||||
|
type={PaymentMethodEnum.card}
|
||||||
cardNumber={guaranteeInfo.maskedCard.slice(-4)}
|
cardNumber={guaranteeInfo.maskedCard.slice(-4)}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: "common.card",
|
id: "common.card",
|
||||||
@@ -209,7 +201,7 @@ export default function ConfirmationStep({
|
|||||||
</Typography>
|
</Typography>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
)}
|
)}
|
||||||
{savedCreditCards && <Divider />}
|
{!!savedCreditCards?.length && <Divider />}
|
||||||
<SelectPaymentMethod
|
<SelectPaymentMethod
|
||||||
paymentMethods={(savedCreditCards ?? []).map((card) => ({
|
paymentMethods={(savedCreditCards ?? []).map((card) => ({
|
||||||
...card,
|
...card,
|
||||||
@@ -224,6 +216,16 @@ export default function ConfirmationStep({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
) : (
|
||||||
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
|
<p className={styles.refundPolicy}>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: "addAncillary.confirmationStep.refundPolicyNightBefore",
|
||||||
|
defaultMessage:
|
||||||
|
"All extras can be cancelled until 23:59 the night before arrival. Time selection and special requests can also be modified.",
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<TermsAndConditions />
|
<TermsAndConditions />
|
||||||
<Summary isConfirmation />
|
<Summary isConfirmation />
|
||||||
|
|||||||
@@ -5,10 +5,6 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modalScrollable {
|
.modalScrollable {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -110,6 +110,18 @@ export function calculateTotalPrice(rooms: Room[], currency: CurrencyEnum) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case PriceTypeEnum.money:
|
||||||
|
{
|
||||||
|
if (room.totalPoints) {
|
||||||
|
total.local.additionalPrice =
|
||||||
|
(total.local.additionalPrice || 0) + room.totalPoints
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!total.local.additionalPriceCurrency) {
|
||||||
|
total.local.additionalPriceCurrency = CurrencyEnum.POINTS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return total
|
return total
|
||||||
|
|||||||
@@ -64,8 +64,9 @@ export function ConfirmBookingPaymentOptions({
|
|||||||
|
|
||||||
{savedCreditCards.map((savedCreditCard) => (
|
{savedCreditCards.map((savedCreditCard) => (
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
|
type={savedCreditCard.cardType as PaymentMethodEnum}
|
||||||
key={savedCreditCard.id}
|
key={savedCreditCard.id}
|
||||||
value={savedCreditCard.id as PaymentMethodEnum}
|
value={savedCreditCard.id}
|
||||||
label={
|
label={
|
||||||
PAYMENT_METHOD_TITLES[
|
PAYMENT_METHOD_TITLES[
|
||||||
savedCreditCard.cardType as PaymentMethodEnum
|
savedCreditCard.cardType as PaymentMethodEnum
|
||||||
@@ -86,6 +87,7 @@ export function ConfirmBookingPaymentOptions({
|
|||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
|
type={PaymentMethodEnum.card}
|
||||||
value={PaymentMethodEnum.card}
|
value={PaymentMethodEnum.card}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: "common.creditCard",
|
id: "common.creditCard",
|
||||||
@@ -96,6 +98,7 @@ export function ConfirmBookingPaymentOptions({
|
|||||||
{!hasMixedRates
|
{!hasMixedRates
|
||||||
? availablePaymentOptions.map((paymentMethod) => (
|
? availablePaymentOptions.map((paymentMethod) => (
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
|
type={paymentMethod}
|
||||||
key={paymentMethod}
|
key={paymentMethod}
|
||||||
value={paymentMethod}
|
value={paymentMethod}
|
||||||
label={PAYMENT_METHOD_TITLES[paymentMethod]}
|
label={PAYMENT_METHOD_TITLES[paymentMethod]}
|
||||||
|
|||||||
@@ -9,14 +9,16 @@ import { PaymentMethodIcon } from '../../Payment/PaymentMethodIcon'
|
|||||||
import { Typography } from '../../Typography'
|
import { Typography } from '../../Typography'
|
||||||
|
|
||||||
export type PaymentOptionProps = {
|
export type PaymentOptionProps = {
|
||||||
value: PaymentMethodEnum
|
value: string
|
||||||
label: string
|
label: string
|
||||||
|
type: PaymentMethodEnum
|
||||||
cardNumber?: string
|
cardNumber?: string
|
||||||
hideRadioButton?: boolean
|
hideRadioButton?: boolean
|
||||||
}
|
}
|
||||||
export function PaymentOption({
|
export function PaymentOption({
|
||||||
value,
|
value,
|
||||||
label,
|
label,
|
||||||
|
type,
|
||||||
cardNumber,
|
cardNumber,
|
||||||
hideRadioButton = false,
|
hideRadioButton = false,
|
||||||
}: PaymentOptionProps) {
|
}: PaymentOptionProps) {
|
||||||
@@ -40,16 +42,15 @@ export function PaymentOption({
|
|||||||
<Label>{label}</Label>
|
<Label>{label}</Label>
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
{cardNumber ? (
|
<div className={styles.cardContainer}>
|
||||||
<>
|
{cardNumber && (
|
||||||
<Typography variant={'Body/Supporting text (caption)/smRegular'}>
|
<Typography variant={'Body/Supporting text (caption)/smRegular'}>
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||||
<span>•••• {cardNumber}</span>
|
<span>•••• {cardNumber}</span>
|
||||||
</Typography>
|
</Typography>
|
||||||
</>
|
)}
|
||||||
) : (
|
<PaymentMethodIcon paymentMethod={type} alt={label} />
|
||||||
<PaymentMethodIcon paymentMethod={value} alt={label} />
|
</div>
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Radio>
|
</Radio>
|
||||||
|
|||||||
@@ -22,15 +22,21 @@ export const Default: Story = {
|
|||||||
onChange: fn(),
|
onChange: fn(),
|
||||||
children: (
|
children: (
|
||||||
<>
|
<>
|
||||||
<PaymentOption label="Visa" value={PaymentMethodEnum.visa} />
|
<PaymentOption
|
||||||
|
label="Visa"
|
||||||
|
value={PaymentMethodEnum.visa}
|
||||||
|
type={PaymentMethodEnum.visa}
|
||||||
|
/>
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
label="American Express"
|
label="American Express"
|
||||||
value={PaymentMethodEnum.americanExpress}
|
value={PaymentMethodEnum.americanExpress}
|
||||||
|
type={PaymentMethodEnum.americanExpress}
|
||||||
/>
|
/>
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
label="MasterCard"
|
label="MasterCard"
|
||||||
value={PaymentMethodEnum.masterCard}
|
value={PaymentMethodEnum.masterCard}
|
||||||
cardNumber="1234"
|
cardNumber="1234"
|
||||||
|
type={PaymentMethodEnum.masterCard}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,6 +11,12 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cardContainer {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--Space-x15);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.paymentOption.focused {
|
.paymentOption.focused {
|
||||||
outline: 2px solid var(--UI-Input-Controls-Border-Focus);
|
outline: 2px solid var(--UI-Input-Controls-Border-Focus);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import styles from './selectPaymentMethod.module.css'
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
PAYMENT_METHOD_TITLES,
|
PAYMENT_METHOD_TITLES,
|
||||||
type PaymentMethodEnum,
|
PaymentMethodEnum,
|
||||||
} from '@scandic-hotels/common/constants/paymentMethod'
|
} from '@scandic-hotels/common/constants/paymentMethod'
|
||||||
|
|
||||||
type PaymentMethod = {
|
type PaymentMethod = {
|
||||||
@@ -79,8 +79,9 @@ export function SelectPaymentMethod({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
|
type={paymentMethods.cardType}
|
||||||
key={paymentMethods.id}
|
key={paymentMethods.id}
|
||||||
value={paymentMethods.id as PaymentMethodEnum}
|
value={paymentMethods.id}
|
||||||
label={label}
|
label={label}
|
||||||
cardNumber={paymentMethods.truncatedNumber}
|
cardNumber={paymentMethods.truncatedNumber}
|
||||||
/>
|
/>
|
||||||
@@ -90,7 +91,8 @@ export function SelectPaymentMethod({
|
|||||||
<span>{otherCardLabel}</span>
|
<span>{otherCardLabel}</span>
|
||||||
</Typography>
|
</Typography>
|
||||||
<PaymentOption
|
<PaymentOption
|
||||||
value={PAYMENT_METHOD_TITLES.card as PaymentMethodEnum}
|
value={PaymentMethodEnum.card}
|
||||||
|
type={PaymentMethodEnum.card}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: 'common.creditCard',
|
id: 'common.creditCard',
|
||||||
defaultMessage: 'Credit card',
|
defaultMessage: 'Credit card',
|
||||||
|
|||||||
Reference in New Issue
Block a user