Files
web/apps/scandic-web/components/HotelReservation/MyStay/GuaranteeLateArrival/index.tsx
Pontus Dreij 74c5b47319 Merged in feat/SW-1737-design-mystay-multiroom (pull request #1565)
Feat/SW-1737 design mystay multiroom

* feat(SW-1737) Fixed member view of guest details

* feat(SW-1737) fix merge issues

* feat(SW-1737) Fixed price details

* feat(SW-1737) removed unused imports

* feat(SW-1737) removed true as statement

* feat(SW-1737) updated store handling

* feat(SW-1737) fixed bug showing double numbers

* feat(SW-1737) small design fixed

* feat(SW-1737) fixed rebase errors

* feat(SW-1737) fixed create booking error with dates

* feat(SW-1737) fixed view multiroom as singleroom

* feat(SW-1737) fixes for multiroom

* feat(SW-1737) fixed bookingsummary

* feat(SW-1737) dont hide modify dates

* feat(SW-1737) updated breakfast to handle number

* feat(SW-1737) Added red color if member rate

* feat(SW-1737) fix PR comments

* feat(SW-1737) updated member tiers svg

* feat(SW-1737) updated how to handle paymentMethodDescription

* feat(SW-1737) fixes after testing mystay

* feat(SW-1737) updated Room type to just use whats used

* feat(SW-1737) fixed access

* feat(SW-1737) refactor my stay after PR comments

* feat(SW-1737) fix roomNumber translation

* feat(SW-1737) removed log


Approved-by: Arvid Norlin
2025-03-24 09:30:10 +00:00

203 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useRouter } from "next/navigation"
import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { PaymentMethodEnum } from "@/constants/booking"
import {
bookingTermsAndConditions,
privacyPolicy,
} from "@/constants/currentWebHrefs"
import { guaranteeCallback } from "@/constants/routes/hotelReservation"
import { env } from "@/env/client"
import { useManageStayStore } from "@/stores/my-stay/manageStayStore"
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
import LoadingSpinner from "@/components/LoadingSpinner"
import { ModalContentWithActions } from "@/components/Modal/ModalContentWithActions"
import Divider from "@/components/TempDesignSystem/Divider"
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 { toast } from "@/components/TempDesignSystem/Toasts"
import { useGuaranteeBooking } from "@/hooks/booking/useGuaranteeBooking"
import useLang from "@/hooks/useLang"
import { formatPrice } from "@/utils/numberFormatting"
import MySavedCards from "../../EnterDetails/Payment/MySavedCards"
import PaymentOption from "../../EnterDetails/Payment/PaymentOption"
import { type GuaranteeFormData, paymentSchema } from "./schema"
import styles from "./guaranteeLateArrival.module.css"
import type { CreditCard } from "@/types/user"
export interface GuaranteeLateArrivalProps {
savedCreditCards: CreditCard[] | null
refId: string
}
export default function GuaranteeLateArrival({
savedCreditCards,
refId,
}: GuaranteeLateArrivalProps) {
const intl = useIntl()
const lang = useLang()
const router = useRouter()
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
const {
actions: { handleCloseView, handleCloseModal },
} = useManageStayStore()
const methods = useForm<GuaranteeFormData>({
defaultValues: {
paymentMethod: savedCreditCards?.length
? savedCreditCards[0].id
: PaymentMethodEnum.card,
termsAndConditions: false,
},
mode: "all",
reValidateMode: "onChange",
resolver: zodResolver(paymentSchema),
})
const guaranteeRedirectUrl = `${env.NEXT_PUBLIC_NODE_ENV === "development" ? `http://localhost:${env.NEXT_PUBLIC_PORT}` : ""}${guaranteeCallback(lang)}`
const { guaranteeBooking, isLoading } = useGuaranteeBooking({
confirmationNumber: bookedRoom.confirmationNumber,
handleBookingCompleted: router.refresh,
})
if (isLoading) {
return (
<div className={styles.loading}>
<LoadingSpinner />
</div>
)
}
const handleGuaranteeLateArrival = (data: GuaranteeFormData) => {
const savedCreditCard = savedCreditCards?.find(
(card) => card.id === data.paymentMethod
)
if (bookedRoom.confirmationNumber) {
const card = savedCreditCard
? {
alias: savedCreditCard.alias,
expiryDate: savedCreditCard.expirationDate,
cardType: savedCreditCard.cardType,
}
: undefined
guaranteeBooking.mutate({
confirmationNumber: bookedRoom.confirmationNumber,
language: lang,
...(card !== undefined && { card }),
success: `${guaranteeRedirectUrl}?status=success&RefId=${encodeURIComponent(refId)}`,
error: `${guaranteeRedirectUrl}?status=error&RefId=${encodeURIComponent(refId)}`,
cancel: `${guaranteeRedirectUrl}?status=cancel&RefId=${encodeURIComponent(refId)}`,
})
} else {
toast.error(
intl.formatMessage({
id: "Something went wrong!",
})
)
}
}
return (
<FormProvider {...methods}>
<ModalContentWithActions
title={intl.formatMessage({ id: "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.",
})}
</Caption>
<Caption type="bold">
{intl.formatMessage({
id: "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" })}
</Body>
</>
) : null}
<PaymentOption
name="paymentMethod"
value={PaymentMethodEnum.card}
label={intl.formatMessage({ id: "Credit card" })}
/>
<div className={styles.termsAndConditions}>
<Checkbox topAlign name={"termsAndConditions"}>
<Caption>
{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>Scandics Privacy Policy</privacyPolicyLink>. I accept Scandic requiring a valid credit card during my visit in case anything is left unpaid.",
},
{
termsAndConditionsLink: (str) => (
<Link
variant="underscored"
href={bookingTermsAndConditions[lang]}
target="_blank"
>
{str}
</Link>
),
privacyPolicyLink: (str) => (
<Link
variant="underscored"
href={privacyPolicy[lang]}
target="_blank"
>
{str}
</Link>
),
}
)}
</Caption>
</Checkbox>
</div>
<div className={styles.guaranteeCost}>
<div className={styles.guaranteeCostText}>
<Caption type="bold">
{intl.formatMessage({ id: "Guarantee cost" })}
</Caption>
<Caption color="uiTextHighContrast">
{intl.formatMessage({
id: "Your card will only be used for authorisation",
})}
</Caption>
</div>
<Divider variant="vertical" color="subtle" />
<Body textTransform="bold">
{formatPrice(intl, 0, bookedRoom.currencyCode)}
</Body>
</div>
</>
}
primaryAction={{
label: intl.formatMessage({ id: "Guarantee" }),
onClick: methods.handleSubmit(handleGuaranteeLateArrival),
intent: "primary",
}}
secondaryAction={{
label: intl.formatMessage({ id: "Back" }),
onClick: handleCloseView,
intent: "text",
}}
/>
</FormProvider>
)
}