Merged in chore/move-enter-details (pull request #2778)
Chore/move enter details Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
"use client"
|
||||
|
||||
import { usePathname, useSearchParams } from "next/navigation"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
||||
import useStickyPosition from "@scandic-hotels/common/hooks/useStickyPosition"
|
||||
import { Alert } from "@scandic-hotels/design-system/Alert"
|
||||
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
||||
|
||||
import useLang from "../../../../hooks/useLang"
|
||||
import { useEnterDetailsStore } from "../../../../stores/enter-details"
|
||||
|
||||
import styles from "./bookingAlert.module.css"
|
||||
|
||||
function useBookingErrorAlert() {
|
||||
const updateSearchParams = useEnterDetailsStore(
|
||||
(state) => state.actions.updateSeachParamString
|
||||
)
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
const searchParams = useSearchParams()
|
||||
const pathname = usePathname()
|
||||
|
||||
const errorCode = searchParams.get("errorCode")
|
||||
const errorMessage = getErrorMessage(errorCode)
|
||||
const severityLevel =
|
||||
errorCode === BookingErrorCodeEnum.TransactionCancelled
|
||||
? AlertTypeEnum.Warning
|
||||
: AlertTypeEnum.Alarm
|
||||
|
||||
const [showAlert, setShowAlert] = useState(!!errorCode)
|
||||
|
||||
const selectRateReturnUrl = getSelectRateReturnUrl()
|
||||
|
||||
useEffect(() => {
|
||||
setShowAlert(!!errorCode)
|
||||
}, [errorCode])
|
||||
|
||||
function getErrorMessage(errorCode: string | null) {
|
||||
switch (errorCode) {
|
||||
case BookingErrorCodeEnum.TransactionCancelled:
|
||||
return intl.formatMessage({
|
||||
defaultMessage: "You have now cancelled your payment.",
|
||||
})
|
||||
case BookingErrorCodeEnum.AvailabilityError:
|
||||
case BookingErrorCodeEnum.NoAvailabilityForRateAndRoomType:
|
||||
return intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Unfortunately, one of the rooms you selected is sold out. Please choose another room to proceed.",
|
||||
})
|
||||
default:
|
||||
return intl.formatMessage({
|
||||
defaultMessage:
|
||||
"We had an issue processing your booking. Please try again. No charges have been made.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function discardAlert() {
|
||||
setShowAlert(false)
|
||||
const queryParams = new URLSearchParams(searchParams.toString())
|
||||
queryParams.delete("errorCode")
|
||||
updateSearchParams(queryParams.toString())
|
||||
|
||||
window.history.replaceState({}, "", `${pathname}?${queryParams.toString()}`)
|
||||
}
|
||||
|
||||
function getSelectRateReturnUrl() {
|
||||
const queryParams = new URLSearchParams(searchParams.toString())
|
||||
queryParams.delete("errorCode")
|
||||
return `${selectRate(lang)}?${queryParams.toString()}`
|
||||
}
|
||||
|
||||
return {
|
||||
showAlert,
|
||||
errorCode,
|
||||
errorMessage,
|
||||
severityLevel,
|
||||
discardAlert,
|
||||
setShowAlert,
|
||||
selectRateReturnUrl,
|
||||
}
|
||||
}
|
||||
|
||||
interface BookingAlertProps {
|
||||
isVisible?: boolean
|
||||
}
|
||||
|
||||
export default function BookingAlert({ isVisible = false }: BookingAlertProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
const {
|
||||
showAlert,
|
||||
errorCode,
|
||||
errorMessage,
|
||||
severityLevel,
|
||||
discardAlert,
|
||||
setShowAlert,
|
||||
selectRateReturnUrl,
|
||||
} = useBookingErrorAlert()
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const { getTopOffset } = useStickyPosition()
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
setShowAlert(true)
|
||||
}
|
||||
}, [isVisible, setShowAlert])
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current
|
||||
|
||||
if (showAlert && el) {
|
||||
window.scrollTo({
|
||||
top: el.offsetTop - getTopOffset(),
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
}, [showAlert, getTopOffset])
|
||||
|
||||
if (!showAlert) return null
|
||||
|
||||
const isAvailabilityError =
|
||||
errorCode === BookingErrorCodeEnum.AvailabilityError ||
|
||||
errorCode === BookingErrorCodeEnum.NoAvailabilityForRateAndRoomType
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper} ref={ref}>
|
||||
<Alert
|
||||
type={severityLevel}
|
||||
variant="inline"
|
||||
text={errorMessage}
|
||||
close={discardAlert}
|
||||
link={
|
||||
isAvailabilityError
|
||||
? {
|
||||
title: intl.formatMessage({
|
||||
defaultMessage: "Change room",
|
||||
}),
|
||||
url: selectRateReturnUrl,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user