Merged in feat/SW-1149-handle-status-polling (pull request #1562)

Feat/SW-1149 handle status polling

* feat(SW-1149): move terms and conditions sections to separate component and added copy

* feat(SW-1149): Added client component to handle success callback for payment flow

* fix: check for bookingCompleted status as well

* feat(SW-1587): use alert instead of toast for showing payment errors

* fix: added enum for payment callback status

* fix: proper way of checking for multiple statuses

* fix: update schema type

* fix: use localised link to customer service

* fix: update to use enum for status strings


Approved-by: Arvid Norlin
This commit is contained in:
Tobias Johansson
2025-03-20 07:38:29 +00:00
parent 200ed55a2c
commit ac493fe325
25 changed files with 384 additions and 155 deletions

View File

@@ -13,10 +13,6 @@ import {
PAYMENT_METHOD_TITLES,
PaymentMethodEnum,
} from "@/constants/booking"
import {
bookingTermsAndConditions,
privacyPolicy,
} from "@/constants/currentWebHrefs"
import {
bookingConfirmation,
selectRate,
@@ -27,15 +23,10 @@ import { useEnterDetailsStore } from "@/stores/enter-details"
import LoadingSpinner from "@/components/LoadingSpinner"
import Button from "@/components/TempDesignSystem/Button"
import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title"
import { toast } from "@/components/TempDesignSystem/Toasts"
import { useAvailablePaymentOptions } from "@/hooks/booking/useAvailablePaymentOptions"
import { useHandleBookingStatus } from "@/hooks/booking/useHandleBookingStatus"
import { usePaymentFailedToast } from "@/hooks/booking/usePaymentFailedToast"
import useLang from "@/hooks/useLang"
import { trackPaymentEvent } from "@/utils/tracking"
@@ -46,8 +37,10 @@ import GuaranteeDetails from "./GuaranteeDetails"
import { hasFlexibleRate, hasPrepaidRate, isPaymentMethodEnum } from "./helpers"
import MixedRatePaymentBreakdown from "./MixedRatePaymentBreakdown"
import MySavedCards from "./MySavedCards"
import PaymentAlert from "./PaymentAlert"
import PaymentOption from "./PaymentOption"
import { type PaymentFormData, paymentSchema } from "./schema"
import TermsAndConditions from "./TermsAndConditions"
import styles from "./payment.module.css"
@@ -74,6 +67,8 @@ export default function PaymentClient({
const intl = useIntl()
const searchParams = useSearchParams()
const [showPaymentAlert, setShowPaymentAlert] = useState(false)
const { booking, canProceedToPayment, rooms, totalPrice } =
useEnterDetailsStore((state) => ({
booking: state.booking,
@@ -109,8 +104,6 @@ export default function PaymentClient({
const hasFlexRates = rooms.some(hasFlexibleRate)
const hasMixedRates = hasPrepaidRates && hasFlexRates
usePaymentFailedToast()
const methods = useForm<PaymentFormData>({
defaultValues: {
paymentMethod: savedCreditCards?.length
@@ -181,7 +174,7 @@ export default function PaymentClient({
const bookingStatus = useHandleBookingStatus({
confirmationNumber: bookingNumber,
expectedStatus: BookingStatusEnum.BookingCompleted,
expectedStatuses: [BookingStatusEnum.BookingCompleted],
maxRetries,
retryInterval,
enabled: isPollingForBookingStatus,
@@ -189,11 +182,8 @@ export default function PaymentClient({
const handlePaymentError = useCallback(
(errorMessage: string) => {
toast.error(
intl.formatMessage({
id: "We had an issue processing your booking. Please try again. No charges have been made.",
})
)
setShowPaymentAlert(true)
const currentPaymentMethod = methods.getValues("paymentMethod")
const smsEnable = methods.getValues("smsConfirmation")
const isSavedCreditCard = savedCreditCards?.some(
@@ -210,7 +200,7 @@ export default function PaymentClient({
status: "failed",
})
},
[intl, methods, savedCreditCards, hotelId]
[methods, savedCreditCards, hotelId]
)
useEffect(() => {
@@ -396,6 +386,7 @@ export default function PaymentClient({
? confirm
: payment}
</Title>
<PaymentAlert isVisible={showPaymentAlert} />
</header>
<FormProvider {...methods}>
<form
@@ -466,49 +457,7 @@ export default function PaymentClient({
</section>
<section className={styles.section}>
<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.",
},
{
termsAndConditionsLink: (str) => (
<Link
className={styles.link}
variant="underscored"
href={bookingTermsAndConditions[lang]}
target="_blank"
>
{str}
</Link>
),
privacyPolicyLink: (str) => (
<Link
className={styles.link}
variant="underscored"
href={privacyPolicy[lang]}
target="_blank"
>
{str}
</Link>
),
}
)}
</Caption>
<Checkbox name="termsAndConditions">
<Caption>
{intl.formatMessage({
id: "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",
})}
</Caption>
</Checkbox>
<TermsAndConditions />
</section>
</>
)}