Merged in SW-3396-move-my-saved-cards-to-design-system (pull request #2762)
SW-3396 move my saved cards to design system * Move PaymentOption, PaymentOptionsGroup, PaymentIcons and MySavedCards (renamed SelectPaymentMethod) to design-system * Remove unused svg payment icons * cleanu * cleanup * trackUpdatePaymentMethod: remove hotelId argument that was never passed Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -13,13 +13,13 @@ import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMetho
|
||||
import useSetOverflowVisibleOnRA from "@scandic-hotels/common/hooks/useSetOverflowVisibleOnRA"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||
import { PaymentOption } from "@scandic-hotels/design-system/Form/PaymentOption"
|
||||
import { PaymentOptionsGroup } from "@scandic-hotels/design-system/Form/PaymentOptionsGroup"
|
||||
import { SelectPaymentMethod } from "@scandic-hotels/design-system/Form/SelectPaymentMethod"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import MySavedCards from "@/components/HotelReservation/MySavedCards"
|
||||
import PaymentOption from "@/components/HotelReservation/PaymentOption"
|
||||
|
||||
import PaymentOptionsGroup from "../../Payment/PaymentOptionsGroup"
|
||||
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||
|
||||
import styles from "./guarantee.module.css"
|
||||
|
||||
@@ -105,11 +105,19 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
|
||||
</div>
|
||||
</Checkbox>
|
||||
{savedCreditCards?.length && guarantee ? (
|
||||
<MySavedCards savedCreditCards={savedCreditCards} />
|
||||
<SelectPaymentMethod
|
||||
formName="paymentMethod"
|
||||
onChange={(method) => trackUpdatePaymentMethod({ method })}
|
||||
paymentMethods={savedCreditCards.map((x) => ({
|
||||
...x,
|
||||
cardType: x.cardType as PaymentMethodEnum,
|
||||
}))}
|
||||
/>
|
||||
) : null}
|
||||
{guarantee ? (
|
||||
<PaymentOptionsGroup
|
||||
name="paymentMethod"
|
||||
onChange={(method) => trackUpdatePaymentMethod({ method })}
|
||||
label={
|
||||
savedCreditCards?.length
|
||||
? intl.formatMessage({
|
||||
|
||||
@@ -8,7 +8,10 @@ import { Label } from "react-aria-components"
|
||||
import { FormProvider, useForm } from "react-hook-form"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||
import {
|
||||
PAYMENT_METHOD_TITLES,
|
||||
PaymentMethodEnum,
|
||||
} from "@scandic-hotels/common/constants/paymentMethod"
|
||||
import {
|
||||
bookingConfirmation,
|
||||
selectRate,
|
||||
@@ -20,6 +23,8 @@ import { formatPhoneNumber } from "@scandic-hotels/common/utils/phone"
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||
import { PaymentOption } from "@scandic-hotels/design-system/Form/PaymentOption"
|
||||
import { PaymentOptionsGroup } from "@scandic-hotels/design-system/Form/PaymentOptionsGroup"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { trpc } from "@scandic-hotels/trpc/client"
|
||||
import { bedTypeMap } from "@scandic-hotels/trpc/constants/bedTypeMap"
|
||||
@@ -27,15 +32,13 @@ import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
|
||||
import { BookingStatusEnum } from "@scandic-hotels/trpc/enums/bookingStatus"
|
||||
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
|
||||
import { PAYMENT_METHOD_TITLES } from "@/constants/booking"
|
||||
import { env } from "@/env/client"
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
|
||||
import PaymentOption from "@/components/HotelReservation/PaymentOption"
|
||||
import { useAvailablePaymentOptions } from "@/hooks/booking/useAvailablePaymentOptions"
|
||||
import { useHandleBookingStatus } from "@/hooks/booking/useHandleBookingStatus"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { trackPaymentEvent } from "@/utils/tracking"
|
||||
import { trackPaymentEvent, trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||
import { trackGlaSaveCardAttempt } from "@/utils/tracking/myStay"
|
||||
|
||||
import ConfirmBooking, { ConfirmBookingRedemption } from "../Confirm"
|
||||
@@ -50,7 +53,6 @@ import {
|
||||
writePaymentInfoToSessionStorage,
|
||||
} from "./helpers"
|
||||
import MixedRatePaymentBreakdown from "./MixedRatePaymentBreakdown"
|
||||
import PaymentOptionsGroup from "./PaymentOptionsGroup"
|
||||
import { type PaymentFormData, paymentSchema } from "./schema"
|
||||
import TermsAndConditions from "./TermsAndConditions"
|
||||
|
||||
@@ -551,6 +553,7 @@ export default function PaymentClient({
|
||||
<PaymentOptionsGroup
|
||||
name="paymentMethod"
|
||||
className={styles.paymentOptionContainer}
|
||||
onChange={(method) => trackUpdatePaymentMethod({ method })}
|
||||
>
|
||||
<Label className="sr-only">
|
||||
{intl.formatMessage({
|
||||
@@ -571,7 +574,7 @@ export default function PaymentClient({
|
||||
{savedCreditCards.map((savedCreditCard) => (
|
||||
<PaymentOption
|
||||
key={savedCreditCard.id}
|
||||
value={savedCreditCard.id}
|
||||
value={savedCreditCard.id as PaymentMethodEnum}
|
||||
label={
|
||||
PAYMENT_METHOD_TITLES[
|
||||
savedCreditCard.cardType as PaymentMethodEnum
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Label, RadioGroup } from "react-aria-components"
|
||||
import { useController, useFormContext } from "react-hook-form"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||
|
||||
import type { ReactNode } from "react"
|
||||
|
||||
interface PaymentOptionsGroupProps {
|
||||
name: string
|
||||
label?: string
|
||||
children: ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default function PaymentOptionsGroup({
|
||||
name,
|
||||
label,
|
||||
children,
|
||||
className,
|
||||
}: PaymentOptionsGroupProps) {
|
||||
const { control } = useFormContext()
|
||||
|
||||
const {
|
||||
field: { value, onChange },
|
||||
} = useController({
|
||||
name,
|
||||
control,
|
||||
})
|
||||
|
||||
const handleChange = (newValue: string) => {
|
||||
onChange(newValue)
|
||||
trackUpdatePaymentMethod("", newValue)
|
||||
}
|
||||
|
||||
return (
|
||||
<RadioGroup value={value} onChange={handleChange} className={className}>
|
||||
{label ? (
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<Label>{label}</Label>
|
||||
</Typography>
|
||||
) : null}
|
||||
{children}
|
||||
</RadioGroup>
|
||||
)
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { PAYMENT_METHOD_TITLES } from "@/constants/booking"
|
||||
|
||||
import PaymentOptionsGroup from "../EnterDetails/Payment/PaymentOptionsGroup"
|
||||
import PaymentOption from "../PaymentOption"
|
||||
|
||||
import styles from "./mySavedCards.module.css"
|
||||
|
||||
import type { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
|
||||
|
||||
interface MySavedCardsProps {
|
||||
savedCreditCards: CreditCard[] | null
|
||||
}
|
||||
|
||||
export default function MySavedCards({ savedCreditCards }: MySavedCardsProps) {
|
||||
const intl = useIntl()
|
||||
const mySavedCardsLabel = intl.formatMessage({
|
||||
defaultMessage: "MY SAVED CARDS",
|
||||
})
|
||||
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<PaymentOptionsGroup
|
||||
name="paymentMethod"
|
||||
label={mySavedCardsLabel}
|
||||
className={styles.paymentOptionContainer}
|
||||
>
|
||||
{savedCreditCards?.map((savedCreditCard) => (
|
||||
<PaymentOption
|
||||
key={savedCreditCard.id}
|
||||
value={savedCreditCard.id}
|
||||
label={
|
||||
PAYMENT_METHOD_TITLES[
|
||||
savedCreditCard.cardType as PaymentMethodEnum
|
||||
]
|
||||
}
|
||||
cardNumber={savedCreditCard.truncatedNumber}
|
||||
/>
|
||||
))}
|
||||
</PaymentOptionsGroup>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
.paymentOptionContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMetho
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { Alert } from "@scandic-hotels/design-system/Alert"
|
||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||
import { PaymentOption } from "@scandic-hotels/design-system/Form/PaymentOption"
|
||||
import { PaymentOptionsGroup } from "@scandic-hotels/design-system/Form/PaymentOptionsGroup"
|
||||
import { SelectPaymentMethod } from "@scandic-hotels/design-system/Form/SelectPaymentMethod"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
@@ -13,10 +16,8 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { bookingTermsAndConditions, privacyPolicy } from "@/constants/webHrefs"
|
||||
import { useAddAncillaryStore } from "@/stores/my-stay/add-ancillary-flow"
|
||||
|
||||
import PaymentOptionsGroup from "@/components/HotelReservation/EnterDetails/Payment/PaymentOptionsGroup"
|
||||
import MySavedCards from "@/components/HotelReservation/MySavedCards"
|
||||
import PaymentOption from "@/components/HotelReservation/PaymentOption"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||
|
||||
import styles from "./confirmationStep.module.css"
|
||||
|
||||
@@ -134,7 +135,16 @@ export default function ConfirmationStep({
|
||||
})}
|
||||
/>
|
||||
{savedCreditCards?.length ? (
|
||||
<MySavedCards savedCreditCards={savedCreditCards} />
|
||||
<SelectPaymentMethod
|
||||
paymentMethods={savedCreditCards.map((x) => ({
|
||||
...x,
|
||||
cardType: x.cardType as PaymentMethodEnum,
|
||||
}))}
|
||||
onChange={(method) => {
|
||||
trackUpdatePaymentMethod({ method })
|
||||
}}
|
||||
formName={"paymentMethod"}
|
||||
/>
|
||||
) : null}
|
||||
<PaymentOptionsGroup
|
||||
name="paymentMethod"
|
||||
|
||||
@@ -8,6 +8,9 @@ import { guaranteeCallback } from "@scandic-hotels/common/constants/routes/hotel
|
||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||
import { PaymentOption } from "@scandic-hotels/design-system/Form/PaymentOption"
|
||||
import { PaymentOptionsGroup } from "@scandic-hotels/design-system/Form/PaymentOptionsGroup"
|
||||
import { SelectPaymentMethod } from "@scandic-hotels/design-system/Form/SelectPaymentMethod"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||
import { toast } from "@scandic-hotels/design-system/Toast"
|
||||
@@ -18,11 +21,9 @@ import { env } from "@/env/client"
|
||||
import { useMyStayStore } from "@/stores/my-stay"
|
||||
|
||||
import { writeGlaToSessionStorage } from "@/components/HotelReservation/EnterDetails/Payment/PaymentCallback/helpers"
|
||||
import PaymentOptionsGroup from "@/components/HotelReservation/EnterDetails/Payment/PaymentOptionsGroup"
|
||||
import MySavedCards from "@/components/HotelReservation/MySavedCards"
|
||||
import PaymentOption from "@/components/HotelReservation/PaymentOption"
|
||||
import { useGuaranteeBooking } from "@/hooks/booking/useGuaranteeBooking"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||
import { trackGlaSaveCardAttempt } from "@/utils/tracking/myStay"
|
||||
|
||||
import { type GuaranteeFormData, paymentSchema } from "./schema"
|
||||
@@ -144,7 +145,16 @@ export default function Form() {
|
||||
onSubmit={methods.handleSubmit(handleGuaranteeLateArrival)}
|
||||
>
|
||||
{savedCreditCards?.length ? (
|
||||
<MySavedCards savedCreditCards={savedCreditCards} />
|
||||
<SelectPaymentMethod
|
||||
formName="paymentMethod"
|
||||
paymentMethods={savedCreditCards.map((x) => ({
|
||||
...x,
|
||||
cardType: x.type as PaymentMethodEnum,
|
||||
}))}
|
||||
onChange={(method) => {
|
||||
trackUpdatePaymentMethod({ method })
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<PaymentOptionsGroup
|
||||
name="paymentMethod"
|
||||
@@ -155,6 +165,9 @@ export default function Form() {
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
onChange={(method) => {
|
||||
trackUpdatePaymentMethod({ method })
|
||||
}}
|
||||
>
|
||||
<PaymentOption
|
||||
value={PaymentMethodEnum.card}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import { cx } from "class-variance-authority"
|
||||
import Image from "next/image"
|
||||
import { Radio } from "react-aria-components"
|
||||
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import Caption from "@scandic-hotels/design-system/Caption"
|
||||
|
||||
import { PAYMENT_METHOD_ICONS } from "@/constants/booking"
|
||||
|
||||
import styles from "./paymentOption.module.css"
|
||||
|
||||
import type { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||
|
||||
import type { PaymentOptionProps } from "./paymentOption"
|
||||
|
||||
export default function PaymentOption({
|
||||
value,
|
||||
label,
|
||||
cardNumber,
|
||||
}: PaymentOptionProps) {
|
||||
return (
|
||||
<Radio
|
||||
value={value}
|
||||
className={({ isFocusVisible }) =>
|
||||
cx(styles.paymentOption, { [styles.focused]: isFocusVisible })
|
||||
}
|
||||
>
|
||||
{({ isSelected }) => (
|
||||
<>
|
||||
<div className={styles.titleContainer}>
|
||||
<span
|
||||
className={cx(styles.radio, { [styles.selected]: isSelected })}
|
||||
aria-hidden
|
||||
/>
|
||||
<Body>{label}</Body>
|
||||
</div>
|
||||
{cardNumber ? (
|
||||
<>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Caption color="uiTextMediumContrast">•••• {cardNumber}</Caption>
|
||||
</>
|
||||
) : (
|
||||
<Image
|
||||
className={styles.paymentOptionIcon}
|
||||
src={PAYMENT_METHOD_ICONS[value as PaymentMethodEnum]}
|
||||
alt={label}
|
||||
width={48}
|
||||
height={32}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Radio>
|
||||
)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
.paymentOption {
|
||||
position: relative;
|
||||
background-color: var(--UI-Input-Controls-Surface-Normal);
|
||||
padding: var(--Space-x15) var(--Space-x2);
|
||||
border: 1px solid var(--Base-Border-Normal);
|
||||
border-radius: var(--Corner-radius-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--Spacing-x2);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.paymentOption.focused {
|
||||
outline: 2px solid var(--UI-Input-Controls-Border-Focus);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.radio {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 1px solid var(--Base-Border-Normal);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.radio.selected {
|
||||
border: 8px solid var(--Surface-UI-Fill-Active);
|
||||
}
|
||||
|
||||
.titleContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.paymentOptionIcon {
|
||||
position: absolute;
|
||||
right: var(--Spacing-x3);
|
||||
top: calc(50% - 16px);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export interface PaymentOptionProps {
|
||||
value: string
|
||||
label: string
|
||||
cardNumber?: string
|
||||
}
|
||||
Reference in New Issue
Block a user