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
This commit is contained in:
@@ -1,23 +1,34 @@
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import PriceContainer from "../../../PriceContainer"
|
||||
import { useCheckedRoomsCounts } from "../utils"
|
||||
|
||||
import type { PriceContainerProps } from "@/types/components/hotelReservation/myStay/cancelStay"
|
||||
import type {
|
||||
CancelStayFormValues,
|
||||
PriceContainerProps,
|
||||
} from "@/types/components/hotelReservation/myStay/cancelStay"
|
||||
|
||||
export default function CancelStayPriceContainer({
|
||||
booking,
|
||||
roomDetails,
|
||||
stayDetails,
|
||||
}: PriceContainerProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
const checkedRoomsDetails = useCheckedRoomsCounts(booking, intl)
|
||||
const { getValues } = useFormContext<CancelStayFormValues>()
|
||||
const formRooms = getValues("rooms")
|
||||
|
||||
const checkedRoomsDetails = useCheckedRoomsCounts(
|
||||
roomDetails,
|
||||
formRooms,
|
||||
intl
|
||||
)
|
||||
|
||||
return (
|
||||
<PriceContainer
|
||||
text={intl.formatMessage({ id: "Cancellation cost" })}
|
||||
price={0}
|
||||
currencyCode={booking.currencyCode}
|
||||
currencyCode={roomDetails.currencyCode}
|
||||
nightsText={stayDetails.nightsText}
|
||||
adultsText={checkedRoomsDetails.adultsText}
|
||||
childrenText={checkedRoomsDetails.childrenText}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useMyStayRoomDetailsStore } from "@/components/HotelReservation/MyStay/stores/myStayRoomDetailsStore"
|
||||
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
@@ -19,12 +20,16 @@ import type {
|
||||
|
||||
export function CancelStayConfirmation({
|
||||
hotel,
|
||||
booking,
|
||||
stayDetails,
|
||||
}: CancelStayConfirmationProps) {
|
||||
const intl = useIntl()
|
||||
const { getValues } = useFormContext<CancelStayFormValues>()
|
||||
const { rooms: roomDetails } = useMyStayRoomDetailsStore()
|
||||
const { watch } = useFormContext<CancelStayFormValues>()
|
||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||
const linkedReservationRooms = useMyStayRoomDetailsStore(
|
||||
(state) => state.linkedReservationRooms
|
||||
)
|
||||
|
||||
const { multiRoom } = bookedRoom
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -45,25 +50,31 @@ export function CancelStayConfirmation({
|
||||
{intl.formatMessage({ id: "No charges were made." })}
|
||||
</Caption>
|
||||
</div>
|
||||
{booking.multiRoom && (
|
||||
{multiRoom && (
|
||||
<>
|
||||
<Body color="uiTextHighContrast" textTransform="bold">
|
||||
{intl.formatMessage({ id: "Select rooms" })}
|
||||
</Body>
|
||||
|
||||
<div className={styles.rooms}>
|
||||
{getValues("rooms").map((room, index) => {
|
||||
{watch("rooms").map((room, index) => {
|
||||
// Find room details from store by confirmationNumber
|
||||
const roomDetail = roomDetails.find(
|
||||
(detail) => detail.id === room.confirmationNumber
|
||||
)
|
||||
const roomDetail =
|
||||
linkedReservationRooms.find(
|
||||
(detail) =>
|
||||
detail.confirmationNumber === room.confirmationNumber
|
||||
) ?? bookedRoom
|
||||
|
||||
return (
|
||||
<div key={room.id} className={styles.roomContainer}>
|
||||
<div
|
||||
key={room.confirmationNumber}
|
||||
className={styles.roomContainer}
|
||||
>
|
||||
<Checkbox
|
||||
name={`rooms.${index}.checked`}
|
||||
registerOptions={{
|
||||
disabled: !roomDetail?.isCancelable,
|
||||
disabled:
|
||||
!roomDetail.isCancelable || roomDetail.isCancelled,
|
||||
}}
|
||||
>
|
||||
<div className={styles.roomInfo}>
|
||||
@@ -90,8 +101,11 @@ export function CancelStayConfirmation({
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{getValues("rooms").some((room) => room.checked) && (
|
||||
<CancelStayPriceContainer booking={booking} stayDetails={stayDetails} />
|
||||
{watch("rooms").some((room) => room.checked) && (
|
||||
<CancelStayPriceContainer
|
||||
roomDetails={bookedRoom}
|
||||
stayDetails={stayDetails}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import CancelStayPriceContainer from "../CancelStayPriceContainer"
|
||||
@@ -8,12 +10,11 @@ import styles from "../cancelStay.module.css"
|
||||
|
||||
import type { FinalConfirmationProps } from "@/types/components/hotelReservation/myStay/cancelStay"
|
||||
|
||||
export function FinalConfirmation({
|
||||
booking,
|
||||
stayDetails,
|
||||
}: FinalConfirmationProps) {
|
||||
export function FinalConfirmation({ stayDetails }: FinalConfirmationProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.modalText}>
|
||||
@@ -23,7 +24,12 @@ export function FinalConfirmation({
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
<CancelStayPriceContainer booking={booking} stayDetails={stayDetails} />
|
||||
{bookedRoom && (
|
||||
<CancelStayPriceContainer
|
||||
roomDetails={bookedRoom}
|
||||
stayDetails={stayDetails}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { trpc } from "@/lib/trpc/client"
|
||||
import { useManageStayStore } from "@/stores/my-stay/manageStayStore"
|
||||
import {
|
||||
type Room,
|
||||
useMyStayRoomDetailsStore,
|
||||
} from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
import { useManageStayStore } from "@/components/HotelReservation/MyStay/stores/manageStayStore"
|
||||
import { toast } from "@/components/TempDesignSystem/Toasts"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { trackCancelStay } from "@/utils/tracking"
|
||||
@@ -13,14 +17,12 @@ import type {
|
||||
} from "@/types/components/hotelReservation/myStay/cancelStay"
|
||||
|
||||
interface UseCancelStayProps extends Omit<CancelStayProps, "hotel"> {
|
||||
getFormValues: () => CancelStayFormValues
|
||||
checkedRooms: CancelStayFormValues["rooms"]
|
||||
}
|
||||
|
||||
export default function useCancelStay({
|
||||
booking,
|
||||
setBookingStatus,
|
||||
handleCloseModal,
|
||||
getFormValues,
|
||||
checkedRooms,
|
||||
}: UseCancelStayProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
@@ -28,12 +30,25 @@ export default function useCancelStay({
|
||||
actions: { setIsLoading },
|
||||
} = useManageStayStore()
|
||||
|
||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||
const linkedReservationRooms = useMyStayRoomDetailsStore(
|
||||
(state) => state.linkedReservationRooms
|
||||
)
|
||||
|
||||
const updateBookedRoom = useMyStayRoomDetailsStore(
|
||||
(state) => state.actions.updateBookedRoom
|
||||
)
|
||||
|
||||
const updateLinkedReservationRoom = useMyStayRoomDetailsStore(
|
||||
(state) => state.actions.updateLinkedReservationRoom
|
||||
)
|
||||
|
||||
const cancelStay = trpc.booking.cancel.useMutation({
|
||||
onMutate: () => setIsLoading(true),
|
||||
})
|
||||
|
||||
async function handleCancelStay() {
|
||||
if (!booking.confirmationNumber) {
|
||||
if (!bookedRoom.confirmationNumber) {
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
@@ -45,61 +60,96 @@ export default function useCancelStay({
|
||||
setIsLoading(true)
|
||||
|
||||
try {
|
||||
const formValues = getFormValues()
|
||||
const { rooms } = formValues
|
||||
const checkedRooms = rooms.filter((room) => room.checked)
|
||||
|
||||
const results = []
|
||||
const errors = []
|
||||
|
||||
for (const room of checkedRooms) {
|
||||
const confirmationNumber =
|
||||
room.confirmationNumber || booking.confirmationNumber
|
||||
let targetRoom: Room | undefined
|
||||
|
||||
// Check if this is the main booked room
|
||||
if (room.confirmationNumber === bookedRoom.confirmationNumber) {
|
||||
targetRoom = bookedRoom
|
||||
}
|
||||
// Check if this is a linked reservation room
|
||||
else {
|
||||
targetRoom = linkedReservationRooms.find(
|
||||
(r) => r.confirmationNumber === room.confirmationNumber
|
||||
)
|
||||
}
|
||||
|
||||
if (!targetRoom?.confirmationNumber) {
|
||||
errors.push(room.confirmationNumber)
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await cancelStay.mutateAsync({
|
||||
confirmationNumber: confirmationNumber,
|
||||
const response = await cancelStay.mutateAsync({
|
||||
confirmationNumber: targetRoom.confirmationNumber,
|
||||
language: lang,
|
||||
})
|
||||
|
||||
if (result) {
|
||||
results.push(room.id)
|
||||
if (response) {
|
||||
results.push(room.confirmationNumber)
|
||||
const cancelledRoom = response.rooms.find(
|
||||
(r) => r.confirmationNumber === targetRoom?.confirmationNumber
|
||||
)
|
||||
|
||||
if (cancelledRoom) {
|
||||
if (
|
||||
targetRoom.confirmationNumber === bookedRoom.confirmationNumber
|
||||
) {
|
||||
// Update main booked room
|
||||
updateBookedRoom({
|
||||
...bookedRoom,
|
||||
isCancelled: true,
|
||||
cancellationNumber: cancelledRoom.cancellationNumber,
|
||||
})
|
||||
} else {
|
||||
// Update linked reservation room
|
||||
updateLinkedReservationRoom({
|
||||
...targetRoom,
|
||||
isCancelled: true,
|
||||
cancellationNumber: cancelledRoom.cancellationNumber,
|
||||
})
|
||||
}
|
||||
|
||||
trackCancelStay(
|
||||
bookedRoom.hotelId,
|
||||
cancelledRoom.confirmationNumber
|
||||
)
|
||||
}
|
||||
} else {
|
||||
errors.push(room.id)
|
||||
errors.push(room.confirmationNumber)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error cancelling room ${room.confirmationNumber}:`,
|
||||
`Error cancelling room ${targetRoom.confirmationNumber}:`,
|
||||
error
|
||||
)
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
})
|
||||
)
|
||||
errors.push(room.id)
|
||||
errors.push(room.confirmationNumber)
|
||||
}
|
||||
}
|
||||
|
||||
// Show appropriate toast based on results
|
||||
if (results.length > 0 && errors.length === 0) {
|
||||
setBookingStatus()
|
||||
// All selected rooms cancelled successfully
|
||||
toast.success(
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: "Your stay was cancelled. Cancellation cost: 0 {currency}. We're sorry to see that the plans didn't work out",
|
||||
},
|
||||
{ currency: booking.currencyCode }
|
||||
{ currency: bookedRoom.currencyCode }
|
||||
)
|
||||
)
|
||||
trackCancelStay(booking.hotelId, booking.confirmationNumber)
|
||||
} else if (results.length > 0 && errors.length > 0) {
|
||||
setBookingStatus()
|
||||
// Some rooms cancelled, some failed
|
||||
toast.warning(
|
||||
intl.formatMessage({
|
||||
id: "Some rooms were cancelled successfully, but we encountered issues with others. Please contact customer service for assistance.",
|
||||
})
|
||||
)
|
||||
} else {
|
||||
// No rooms cancelled successfully
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
@@ -115,6 +165,7 @@ export default function useCancelStay({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
})
|
||||
)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { FormProvider, useForm } from "react-hook-form"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useManageStayStore } from "@/components/HotelReservation/MyStay/stores/manageStayStore"
|
||||
import { useManageStayStore } from "@/stores/my-stay/manageStayStore"
|
||||
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
import { ModalContentWithActions } from "@/components/Modal/ModalContentWithActions"
|
||||
import Alert from "@/components/TempDesignSystem/Alert"
|
||||
import useLang from "@/hooks/useLang"
|
||||
@@ -21,44 +23,38 @@ import {
|
||||
import { MODAL_STEPS } from "@/types/components/hotelReservation/myStay/myStay"
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
import type { Hotel } from "@/types/hotel"
|
||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||
|
||||
interface CancelStayProps {
|
||||
booking: BookingConfirmation["booking"]
|
||||
hotel: Hotel
|
||||
setBookingStatus: () => void
|
||||
}
|
||||
|
||||
export default function CancelStay({
|
||||
booking,
|
||||
hotel,
|
||||
setBookingStatus,
|
||||
}: CancelStayProps) {
|
||||
export default function CancelStay({ hotel }: CancelStayProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
|
||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||
|
||||
const form = useForm<CancelStayFormValues>({
|
||||
resolver: zodResolver(cancelStaySchema),
|
||||
defaultValues: {
|
||||
rooms: getDefaultRooms(booking),
|
||||
rooms: getDefaultRooms(bookedRoom),
|
||||
},
|
||||
})
|
||||
|
||||
const {
|
||||
currentStep,
|
||||
isLoading,
|
||||
actions: { handleForward, handleCloseView, handleCloseModal },
|
||||
} = useManageStayStore()
|
||||
|
||||
const { rooms } = form.watch()
|
||||
|
||||
const { handleCancelStay } = useCancelStay({
|
||||
booking,
|
||||
setBookingStatus,
|
||||
handleCloseModal,
|
||||
getFormValues: form.getValues,
|
||||
checkedRooms: rooms.filter((room) => room.checked),
|
||||
})
|
||||
|
||||
const { mainRoom } = booking
|
||||
const isFirstStep = currentStep === MODAL_STEPS.INITIAL
|
||||
const stayDetails = formatStayDetails({ booking, lang, intl })
|
||||
const stayDetails = formatStayDetails({ bookedRoom, lang, intl })
|
||||
|
||||
function getModalCopy() {
|
||||
if (isFirstStep) {
|
||||
@@ -77,19 +73,13 @@ export default function CancelStay({
|
||||
}
|
||||
|
||||
function getModalContent() {
|
||||
if (mainRoom && isFirstStep)
|
||||
return (
|
||||
<CancelStayConfirmation
|
||||
hotel={hotel}
|
||||
booking={booking}
|
||||
stayDetails={stayDetails}
|
||||
/>
|
||||
)
|
||||
if (bookedRoom && isFirstStep)
|
||||
return <CancelStayConfirmation hotel={hotel} stayDetails={stayDetails} />
|
||||
|
||||
if (mainRoom && !isFirstStep)
|
||||
return <FinalConfirmation booking={booking} stayDetails={stayDetails} />
|
||||
if (bookedRoom && !isFirstStep)
|
||||
return <FinalConfirmation stayDetails={stayDetails} />
|
||||
|
||||
if (!mainRoom && isFirstStep)
|
||||
if (!bookedRoom && isFirstStep)
|
||||
return (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
@@ -103,7 +93,6 @@ export default function CancelStay({
|
||||
)
|
||||
}
|
||||
|
||||
const { rooms } = form.watch()
|
||||
const isFormValid = rooms?.some((room) => room.checked)
|
||||
|
||||
return (
|
||||
@@ -113,7 +102,7 @@ export default function CancelStay({
|
||||
content={getModalContent()}
|
||||
onClose={handleCloseModal}
|
||||
primaryAction={
|
||||
mainRoom
|
||||
bookedRoom
|
||||
? {
|
||||
label: getModalCopy().primaryLabel,
|
||||
onClick: isFirstStep ? handleForward : handleCancelStay,
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { useFormContext } from "react-hook-form"
|
||||
|
||||
import { dt } from "@/lib/dt"
|
||||
|
||||
import type { IntlShape } from "react-intl"
|
||||
|
||||
import type { CancelStayFormValues } from "@/types/components/hotelReservation/myStay/cancelStay"
|
||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||
import type { Room } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
export function getDefaultRooms(booking: BookingConfirmation["booking"]) {
|
||||
const { multiRoom, confirmationNumber, linkedReservations = [] } = booking
|
||||
export function getDefaultRooms(room: Room) {
|
||||
const { multiRoom, confirmationNumber, linkedReservations = [] } = room
|
||||
|
||||
if (!multiRoom) {
|
||||
return [{ id: "1", checked: true, confirmationNumber }]
|
||||
@@ -25,35 +23,43 @@ export function getDefaultRooms(booking: BookingConfirmation["booking"]) {
|
||||
}
|
||||
|
||||
export function formatStayDetails({
|
||||
booking,
|
||||
bookedRoom,
|
||||
lang,
|
||||
intl,
|
||||
}: {
|
||||
booking: BookingConfirmation["booking"]
|
||||
bookedRoom: Room
|
||||
lang: string
|
||||
intl: IntlShape
|
||||
}) {
|
||||
const { multiRoom } = booking
|
||||
const totalAdults = multiRoom
|
||||
? (booking.adults ?? 0) +
|
||||
(booking.linkedReservations ?? []).reduce((acc, reservation) => {
|
||||
return acc + (reservation.adults ?? 0)
|
||||
}, 0)
|
||||
: (booking.adults ?? 0)
|
||||
const totalChildren = multiRoom
|
||||
? booking.childrenAges?.length +
|
||||
(booking.linkedReservations ?? []).reduce((acc, reservation) => {
|
||||
return acc + reservation.children
|
||||
}, 0)
|
||||
: booking.childrenAges?.length
|
||||
const {
|
||||
multiRoom,
|
||||
adults,
|
||||
childrenAges,
|
||||
linkedReservations,
|
||||
checkInDate,
|
||||
checkOutDate,
|
||||
} = bookedRoom
|
||||
|
||||
const checkInDate = dt(booking.checkInDate)
|
||||
const totalAdults = multiRoom
|
||||
? linkedReservations.reduce((acc, reservation) => {
|
||||
return acc + reservation.adults
|
||||
}, adults)
|
||||
: adults
|
||||
const totalChildren = multiRoom
|
||||
? linkedReservations.reduce((acc, reservation) => {
|
||||
return acc + reservation.children
|
||||
}, childrenAges.length)
|
||||
: childrenAges.length
|
||||
|
||||
const checkInDateFormatted = dt(checkInDate)
|
||||
.locale(lang)
|
||||
.format("dddd D MMM YYYY")
|
||||
const checkOutDate = dt(booking.checkOutDate)
|
||||
const checkOutDateFormatted = dt(checkOutDate)
|
||||
.locale(lang)
|
||||
.format("dddd D MMM YYYY")
|
||||
const diff = dt(checkOutDate).diff(checkInDate, "days")
|
||||
const diff = dt(checkOutDate)
|
||||
.startOf("day")
|
||||
.diff(dt(checkInDate).startOf("day"), "days")
|
||||
|
||||
const nightsText = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
@@ -69,8 +75,8 @@ export function formatStayDetails({
|
||||
)
|
||||
|
||||
return {
|
||||
checkInDate,
|
||||
checkOutDate,
|
||||
checkInDate: checkInDateFormatted,
|
||||
checkOutDate: checkOutDateFormatted,
|
||||
nightsText,
|
||||
adultsText,
|
||||
childrenText,
|
||||
@@ -79,31 +85,28 @@ export function formatStayDetails({
|
||||
}
|
||||
|
||||
function getMatchedRooms(
|
||||
booking: BookingConfirmation["booking"],
|
||||
roomDetails: Room,
|
||||
checkedConfirmationNumbers: string[]
|
||||
) {
|
||||
let matchedRooms = []
|
||||
|
||||
// Main booking
|
||||
if (checkedConfirmationNumbers.includes(booking.confirmationNumber)) {
|
||||
if (checkedConfirmationNumbers.includes(roomDetails.confirmationNumber)) {
|
||||
matchedRooms.push({
|
||||
adults: booking.adults ?? 0,
|
||||
children: booking.childrenAges?.length ?? 0,
|
||||
adults: roomDetails.adults,
|
||||
children: roomDetails.childrenAges.length,
|
||||
})
|
||||
}
|
||||
|
||||
// Linked reservations
|
||||
if (booking.linkedReservations) {
|
||||
const matchedLinkedRooms = booking.linkedReservations
|
||||
.filter((reservation) =>
|
||||
checkedConfirmationNumbers.includes(reservation.confirmationNumber)
|
||||
)
|
||||
.map((reservation) => ({
|
||||
adults: reservation.adults ?? 0,
|
||||
children: reservation.children ?? 0,
|
||||
}))
|
||||
|
||||
matchedRooms = [...matchedRooms, ...matchedLinkedRooms]
|
||||
if (roomDetails.linkedReservations) {
|
||||
roomDetails.linkedReservations.forEach((reservation) => {
|
||||
if (checkedConfirmationNumbers.includes(reservation.confirmationNumber))
|
||||
matchedRooms.push({
|
||||
adults: reservation.adults,
|
||||
children: reservation.children,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return matchedRooms
|
||||
@@ -119,12 +122,10 @@ function calculateTotals(matchedRooms: { adults: number; children: number }[]) {
|
||||
}
|
||||
|
||||
export const useCheckedRoomsCounts = (
|
||||
booking: BookingConfirmation["booking"],
|
||||
roomDetails: Room,
|
||||
formRooms: CancelStayFormValues["rooms"],
|
||||
intl: IntlShape
|
||||
) => {
|
||||
const { getValues } = useFormContext<CancelStayFormValues>()
|
||||
const formRooms = getValues("rooms")
|
||||
|
||||
const checkedFormRooms = formRooms.filter((room) => room.checked)
|
||||
const checkedConfirmationNumbers = checkedFormRooms
|
||||
.map((room) => room.confirmationNumber)
|
||||
@@ -133,7 +134,7 @@ export const useCheckedRoomsCounts = (
|
||||
confirmationNumber !== null && confirmationNumber !== undefined
|
||||
)
|
||||
|
||||
const matchedRooms = getMatchedRooms(booking, checkedConfirmationNumbers)
|
||||
const matchedRooms = getMatchedRooms(roomDetails, checkedConfirmationNumbers)
|
||||
const { totalAdults, totalChildren } = calculateTotals(matchedRooms)
|
||||
|
||||
const adultsText = intl.formatMessage(
|
||||
|
||||
@@ -2,9 +2,9 @@ import { useFormContext } from "react-hook-form"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { dt } from "@/lib/dt"
|
||||
import { useMyStayTotalPriceStore } from "@/stores/my-stay/myStayTotalPrice"
|
||||
|
||||
import PriceContainer from "@/components/HotelReservation/MyStay/ManageStay/ActionPanel/PriceContainer"
|
||||
import { useMyStayTotalPriceStore } from "@/components/HotelReservation/MyStay/stores/myStayTotalPrice"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
@@ -21,7 +21,7 @@ interface ConfirmationProps {
|
||||
nightsText: string
|
||||
adultsText: string
|
||||
childrenText: string
|
||||
totalChildren: number
|
||||
totalChildren?: number
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,15 @@ export default function Confirmation({
|
||||
.locale(lang)
|
||||
.format("dddd, DD MMM, YYYY")
|
||||
|
||||
const diff = dt(newCheckOut)
|
||||
.startOf("day")
|
||||
.diff(dt(newCheckIn).startOf("day"), "days")
|
||||
|
||||
const nightsText = intl.formatMessage(
|
||||
{ id: "{totalNights, plural, one {# night} other {# nights}}" },
|
||||
{ totalNights: diff }
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.dateComparison}>
|
||||
@@ -130,7 +139,7 @@ export default function Confirmation({
|
||||
text={intl.formatMessage({ id: "To be paid" })}
|
||||
price={newPrice}
|
||||
currencyCode={currencyCode}
|
||||
nightsText={stayDetails.nightsText}
|
||||
nightsText={nightsText}
|
||||
adultsText={stayDetails.adultsText}
|
||||
childrenText={stayDetails.childrenText}
|
||||
totalChildren={stayDetails.totalChildren}
|
||||
|
||||
@@ -21,7 +21,7 @@ import styles from "./newDates.module.css"
|
||||
import type { DateRange } from "react-day-picker"
|
||||
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
import type { RoomDetails } from "@/components/HotelReservation/MyStay/stores/myStayRoomDetailsStore"
|
||||
import type { Room } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
const locales = {
|
||||
[Lang.da]: da,
|
||||
@@ -32,7 +32,7 @@ const locales = {
|
||||
}
|
||||
|
||||
interface NewDatesProps {
|
||||
mainRoom: RoomDetails
|
||||
mainRoom: Room
|
||||
noAvailability: boolean
|
||||
error: boolean
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import { useIntl } from "react-intl"
|
||||
|
||||
import { dt } from "@/lib/dt"
|
||||
import { trpc } from "@/lib/trpc/client"
|
||||
import { useManageStayStore } from "@/stores/my-stay/manageStayStore"
|
||||
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
import { useManageStayStore } from "@/components/HotelReservation/MyStay/stores/manageStayStore"
|
||||
import { useMyStayRoomDetailsStore } from "@/components/HotelReservation/MyStay/stores/myStayRoomDetailsStore"
|
||||
import { toast } from "@/components/TempDesignSystem/Toasts"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
@@ -13,18 +13,12 @@ import type { UseFormGetValues } from "react-hook-form"
|
||||
import type { ModifyDateSchema } from "@/types/components/hotelReservation/myStay/modifyDate"
|
||||
|
||||
interface UseModifyStayOptions {
|
||||
booking: {
|
||||
confirmationNumber: string
|
||||
roomPrice?: number
|
||||
currencyCode?: string
|
||||
}
|
||||
isLoggedIn?: boolean
|
||||
getFormValues: UseFormGetValues<ModifyDateSchema>
|
||||
handleCloseModal: () => void
|
||||
}
|
||||
|
||||
export default function useModifyStay({
|
||||
booking,
|
||||
isLoggedIn,
|
||||
getFormValues,
|
||||
handleCloseModal,
|
||||
@@ -34,45 +28,51 @@ export default function useModifyStay({
|
||||
const {
|
||||
actions: { setIsLoading },
|
||||
} = useManageStayStore()
|
||||
const {
|
||||
rooms,
|
||||
actions: { updateRoomDetails },
|
||||
} = useMyStayRoomDetailsStore()
|
||||
|
||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||
|
||||
const updateBookedRoom = useMyStayRoomDetailsStore(
|
||||
(state) => state.actions.updateBookedRoom
|
||||
)
|
||||
|
||||
const utils = trpc.useUtils()
|
||||
|
||||
const updateBooking = trpc.booking.update.useMutation({
|
||||
onMutate: () => setIsLoading(true),
|
||||
onSuccess: (updatedBooking) => {
|
||||
if (!updatedBooking) return
|
||||
if (!updatedBooking) {
|
||||
toast.error(intl.formatMessage({ id: "Failed to update your stay" }))
|
||||
return
|
||||
}
|
||||
|
||||
// Update room details with server response data
|
||||
for (const room of rooms) {
|
||||
const originalCheckIn = dt(room.checkInDate)
|
||||
const originalCheckOut = dt(room.checkOutDate)
|
||||
|
||||
updateRoomDetails({
|
||||
...room,
|
||||
checkInDate: dt(updatedBooking.checkInDate)
|
||||
.hour(originalCheckIn.hour())
|
||||
.minute(originalCheckIn.minute())
|
||||
.second(originalCheckIn.second())
|
||||
.toDate(),
|
||||
checkOutDate: dt(updatedBooking.checkOutDate)
|
||||
.hour(originalCheckOut.hour())
|
||||
.minute(originalCheckOut.minute())
|
||||
.second(originalCheckOut.second())
|
||||
.toDate(),
|
||||
})
|
||||
}
|
||||
setIsLoading(false)
|
||||
const originalCheckIn = dt(bookedRoom.checkInDate)
|
||||
const originalCheckOut = dt(bookedRoom.checkOutDate)
|
||||
|
||||
updateBookedRoom({
|
||||
...bookedRoom,
|
||||
checkInDate: dt(updatedBooking.checkInDate)
|
||||
.hour(originalCheckIn.hour())
|
||||
.minute(originalCheckIn.minute())
|
||||
.second(originalCheckIn.second())
|
||||
.toDate(),
|
||||
checkOutDate: dt(updatedBooking.checkOutDate)
|
||||
.hour(originalCheckOut.hour())
|
||||
.minute(originalCheckOut.minute())
|
||||
.second(originalCheckOut.second())
|
||||
.toDate(),
|
||||
})
|
||||
|
||||
toast.success(intl.formatMessage({ id: "Your stay was updated" }))
|
||||
handleCloseModal()
|
||||
},
|
||||
onError: () => {
|
||||
setIsLoading(false)
|
||||
toast.error(intl.formatMessage({ id: "Failed to update your stay" }))
|
||||
},
|
||||
onSettled: () => {
|
||||
setIsLoading(false)
|
||||
},
|
||||
})
|
||||
|
||||
async function checkAvailability() {
|
||||
@@ -89,34 +89,32 @@ export default function useModifyStay({
|
||||
const availabilityResults = []
|
||||
let totalNewPrice = 0
|
||||
|
||||
for (const room of rooms) {
|
||||
try {
|
||||
const data = await utils.client.hotel.availability.room.query({
|
||||
hotelId: room.hotelId,
|
||||
roomStayStartDate: formValues.checkInDate,
|
||||
roomStayEndDate: formValues.checkOutDate,
|
||||
adults: room.adults,
|
||||
children: room.children,
|
||||
bookingCode: room.bookingCode,
|
||||
rateCode: room.rateCode,
|
||||
roomTypeCode: room.roomTypeCode,
|
||||
lang,
|
||||
})
|
||||
try {
|
||||
const data = await utils.client.hotel.availability.room.query({
|
||||
hotelId: bookedRoom.hotelId,
|
||||
roomStayStartDate: formValues.checkInDate,
|
||||
roomStayEndDate: formValues.checkOutDate,
|
||||
adults: bookedRoom.adults,
|
||||
children: bookedRoom.childrenAsString,
|
||||
bookingCode: bookedRoom.bookingCode ?? undefined,
|
||||
rateCode: bookedRoom.rateDefinition.rateCode,
|
||||
roomTypeCode: bookedRoom.roomTypeCode,
|
||||
lang,
|
||||
})
|
||||
|
||||
if (!data?.selectedRoom || data.selectedRoom.roomsLeft <= 0) {
|
||||
return { success: false, noAvailability: true }
|
||||
}
|
||||
|
||||
const roomPrice = isLoggedIn
|
||||
? data.memberRate?.requestedPrice?.pricePerStay
|
||||
: data.publicRate?.requestedPrice?.pricePerStay
|
||||
|
||||
totalNewPrice += roomPrice || 0
|
||||
availabilityResults.push(data)
|
||||
} catch (error) {
|
||||
console.error("Error checking room availability:", error)
|
||||
return { success: false, error: true }
|
||||
if (!data?.selectedRoom || data.selectedRoom.roomsLeft <= 0) {
|
||||
return { success: false, noAvailability: true }
|
||||
}
|
||||
|
||||
const roomPrice = isLoggedIn
|
||||
? data.memberRate?.localPrice.pricePerStay
|
||||
: data.publicRate?.localPrice.pricePerStay
|
||||
|
||||
totalNewPrice += roomPrice ?? 0
|
||||
availabilityResults.push(data)
|
||||
} catch (error) {
|
||||
console.error("Error checking room availability:", error)
|
||||
return { success: false, error: true }
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -133,21 +131,12 @@ export default function useModifyStay({
|
||||
}
|
||||
|
||||
async function handleModifyStay() {
|
||||
if (!booking.confirmationNumber) {
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "Something went wrong. Please try again later.",
|
||||
})
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const formValues = getFormValues()
|
||||
setIsLoading(true)
|
||||
|
||||
try {
|
||||
await updateBooking.mutateAsync({
|
||||
confirmationNumber: booking.confirmationNumber,
|
||||
confirmationNumber: bookedRoom.confirmationNumber,
|
||||
checkInDate: formValues.checkInDate,
|
||||
checkOutDate: formValues.checkOutDate,
|
||||
})
|
||||
|
||||
@@ -5,9 +5,9 @@ import { FormProvider, useForm } from "react-hook-form"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { dt } from "@/lib/dt"
|
||||
import { useManageStayStore } from "@/stores/my-stay/manageStayStore"
|
||||
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
|
||||
import { useManageStayStore } from "@/components/HotelReservation/MyStay/stores/manageStayStore"
|
||||
import { useMyStayRoomDetailsStore } from "@/components/HotelReservation/MyStay/stores/myStayRoomDetailsStore"
|
||||
import { ModalContentWithActions } from "@/components/Modal/ModalContentWithActions"
|
||||
import Alert from "@/components/TempDesignSystem/Alert"
|
||||
import useLang from "@/hooks/useLang"
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
import { MODAL_STEPS } from "@/types/components/hotelReservation/myStay/myStay"
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
|
||||
export default function ModifyStay({ booking, user }: ModifyStayProps) {
|
||||
export default function ModifyStay({ isLoggedIn }: ModifyStayProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
|
||||
@@ -46,20 +46,24 @@ export default function ModifyStay({ booking, user }: ModifyStayProps) {
|
||||
isLoading,
|
||||
actions: { handleCloseView, handleCloseModal, setCurrentStep },
|
||||
} = useManageStayStore()
|
||||
const { rooms } = useMyStayRoomDetailsStore()
|
||||
|
||||
const { mainRoom: isMainRoom } = booking
|
||||
const stayDetails = formatStayDetails({ booking, lang, intl })
|
||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||
|
||||
const stayDetails = formatStayDetails({ bookedRoom, lang, intl })
|
||||
|
||||
const isFirstStep = currentStep === MODAL_STEPS.INITIAL
|
||||
|
||||
const mainRoom = rooms.find((room) => room.mainRoom)
|
||||
|
||||
const isMultiRoom = rooms.length > 1
|
||||
const {
|
||||
multiRoom,
|
||||
checkInDate,
|
||||
checkOutDate,
|
||||
mainRoom,
|
||||
roomPrice,
|
||||
canChangeDate,
|
||||
} = bookedRoom
|
||||
|
||||
const { checkAvailability, handleModifyStay } = useModifyStay({
|
||||
booking,
|
||||
isLoggedIn: !!user,
|
||||
isLoggedIn,
|
||||
getFormValues: form.getValues,
|
||||
handleCloseModal,
|
||||
})
|
||||
@@ -84,20 +88,12 @@ export default function ModifyStay({ booking, user }: ModifyStayProps) {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (mainRoom) {
|
||||
form.setValue(
|
||||
"checkInDate",
|
||||
dt(mainRoom.checkInDate).format("YYYY-MM-DD")
|
||||
)
|
||||
form.setValue(
|
||||
"checkOutDate",
|
||||
dt(mainRoom.checkOutDate).format("YYYY-MM-DD")
|
||||
)
|
||||
}
|
||||
}, [mainRoom, form])
|
||||
form.setValue("checkInDate", dt(checkInDate).format("YYYY-MM-DD"))
|
||||
form.setValue("checkOutDate", dt(checkOutDate).format("YYYY-MM-DD"))
|
||||
}, [checkInDate, checkOutDate, form])
|
||||
|
||||
function getModalContent() {
|
||||
if (mainRoom && isFirstStep && isMultiRoom) {
|
||||
if (bookedRoom && isFirstStep && multiRoom) {
|
||||
return (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
@@ -110,10 +106,23 @@ export default function ModifyStay({ booking, user }: ModifyStayProps) {
|
||||
/>
|
||||
)
|
||||
}
|
||||
if (mainRoom && !canChangeDate) {
|
||||
return (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "Contact customer service",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "Please contact customer service to update the dates.",
|
||||
})}
|
||||
/>
|
||||
)
|
||||
}
|
||||
if (mainRoom && isFirstStep)
|
||||
return (
|
||||
<NewDates
|
||||
mainRoom={mainRoom}
|
||||
mainRoom={bookedRoom}
|
||||
noAvailability={noAvailability}
|
||||
error={error}
|
||||
/>
|
||||
@@ -122,7 +131,7 @@ export default function ModifyStay({ booking, user }: ModifyStayProps) {
|
||||
if (mainRoom && !isFirstStep)
|
||||
return (
|
||||
<Confirmation
|
||||
oldPrice={booking.roomPrice}
|
||||
oldPrice={roomPrice.perStay.local.price}
|
||||
newPrice={newRoomPrice}
|
||||
stayDetails={stayDetails}
|
||||
/>
|
||||
@@ -153,7 +162,7 @@ export default function ModifyStay({ booking, user }: ModifyStayProps) {
|
||||
content={getModalContent()}
|
||||
onClose={handleCloseModal}
|
||||
primaryAction={
|
||||
isMainRoom && !isMultiRoom
|
||||
mainRoom && !multiRoom && canChangeDate
|
||||
? {
|
||||
label: isFirstStep
|
||||
? intl.formatMessage({ id: "Check availability" })
|
||||
|
||||
@@ -10,7 +10,7 @@ interface PriceContainerProps {
|
||||
nightsText: string
|
||||
adultsText: string
|
||||
childrenText: string
|
||||
totalChildren: number
|
||||
totalChildren?: number
|
||||
}
|
||||
|
||||
export default function PriceContainer({
|
||||
@@ -20,7 +20,7 @@ export default function PriceContainer({
|
||||
nightsText,
|
||||
adultsText,
|
||||
childrenText,
|
||||
totalChildren,
|
||||
totalChildren = 0,
|
||||
}: PriceContainerProps) {
|
||||
return (
|
||||
<div className={styles.priceContainer}>
|
||||
|
||||
@@ -6,12 +6,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 1367px) {
|
||||
.actionPanel {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -19,12 +13,6 @@
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
|
||||
@media (min-width: 1367px) {
|
||||
.menu {
|
||||
width: 432px;
|
||||
}
|
||||
}
|
||||
|
||||
.actionPanel .menu .button,
|
||||
.actionLink {
|
||||
width: 100%;
|
||||
@@ -49,12 +37,6 @@
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
@media (min-width: 1367px) {
|
||||
.info {
|
||||
width: 256px;
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
@@ -66,3 +48,17 @@
|
||||
.link {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 1367px) {
|
||||
.actionPanel {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.menu {
|
||||
width: 432px;
|
||||
}
|
||||
|
||||
.info {
|
||||
width: 256px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { BookingStatusEnum } from "@/constants/booking"
|
||||
import { customerService } from "@/constants/currentWebHrefs"
|
||||
import { useManageStayStore } from "@/stores/my-stay/manageStayStore"
|
||||
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||
import { preliminaryReceipt } from "@/constants/routes/myStay"
|
||||
|
||||
import AddToCalendar from "@/components/HotelReservation/AddToCalendar"
|
||||
@@ -23,7 +24,6 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { trackMyStayPageLink } from "@/utils/tracking"
|
||||
|
||||
import { useManageStayStore } from "../../stores/manageStayStore"
|
||||
import AddToCalendarButton from "./Actions/AddToCalendarButton"
|
||||
|
||||
import styles from "./actionPanel.module.css"
|
||||
@@ -31,46 +31,45 @@ import styles from "./actionPanel.module.css"
|
||||
import type { EventAttributes } from "ics"
|
||||
|
||||
import type { Hotel } from "@/types/hotel"
|
||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||
|
||||
interface ActionPanelProps {
|
||||
booking: BookingConfirmation["booking"]
|
||||
hotel: Hotel
|
||||
bookingStatus: string | null
|
||||
showGuaranteeButton: boolean
|
||||
onCancelClick: () => void
|
||||
onGuaranteeClick: () => void
|
||||
}
|
||||
|
||||
export default function ActionPanel({
|
||||
booking,
|
||||
hotel,
|
||||
bookingStatus,
|
||||
showGuaranteeButton,
|
||||
onGuaranteeClick,
|
||||
}: ActionPanelProps) {
|
||||
export default function ActionPanel({ hotel }: ActionPanelProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
const {
|
||||
actions: { setActiveView },
|
||||
} = useManageStayStore()
|
||||
|
||||
const showCancelStayButton =
|
||||
bookingStatus !== BookingStatusEnum.Cancelled && booking.isCancelable
|
||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||
const linkedReservationRooms = useMyStayRoomDetailsStore(
|
||||
(state) => state.linkedReservationRooms
|
||||
)
|
||||
|
||||
const event: EventAttributes = {
|
||||
const showCancelStayButton =
|
||||
bookedRoom.isCancelable ||
|
||||
linkedReservationRooms.some((room) => room.isCancelable)
|
||||
const showGuaranteeButton =
|
||||
!bookedRoom.guaranteeInfo && !bookedRoom.isCancelled
|
||||
|
||||
const { confirmationNumber, checkInDate, checkOutDate, createDateTime } =
|
||||
bookedRoom
|
||||
|
||||
const calendarEvent: EventAttributes = {
|
||||
busyStatus: "FREE",
|
||||
categories: ["booking", "hotel", "stay"],
|
||||
created: generateDateTime(booking.createDateTime),
|
||||
created: generateDateTime(createDateTime),
|
||||
description: hotel.hotelContent.texts.descriptions?.medium,
|
||||
end: generateDateTime(booking.checkOutDate),
|
||||
end: generateDateTime(checkOutDate),
|
||||
endInputType: "utc",
|
||||
geo: {
|
||||
lat: hotel.location.latitude,
|
||||
lon: hotel.location.longitude,
|
||||
},
|
||||
location: `${hotel.address.streetAddress}, ${hotel.address.zipCode} ${hotel.address.city} ${hotel.address.country}`,
|
||||
start: generateDateTime(booking.checkInDate),
|
||||
start: generateDateTime(checkInDate),
|
||||
startInputType: "utc",
|
||||
status: "CONFIRMED",
|
||||
title: hotel.name,
|
||||
@@ -93,7 +92,7 @@ export default function ActionPanel({
|
||||
|
||||
const handleGuaranteeLateArrival = () => {
|
||||
trackMyStayPageLink("guarantee late arrival")
|
||||
onGuaranteeClick()
|
||||
setActiveView("guaranteeLateArrival")
|
||||
}
|
||||
|
||||
const handleCustomerSupport = () => {
|
||||
@@ -124,8 +123,8 @@ export default function ActionPanel({
|
||||
</Button>
|
||||
)}
|
||||
<AddToCalendar
|
||||
checkInDate={booking.checkInDate}
|
||||
event={event}
|
||||
checkInDate={checkInDate}
|
||||
event={calendarEvent}
|
||||
hotelName={hotel.name}
|
||||
renderButton={(onPress) => <AddToCalendarButton onPress={onPress} />}
|
||||
/>
|
||||
@@ -157,7 +156,7 @@ export default function ActionPanel({
|
||||
{intl.formatMessage({ id: "Reference number" })}
|
||||
</span>
|
||||
<Subtitle color="burgundy" textAlign="right">
|
||||
{booking.confirmationNumber}
|
||||
{confirmationNumber}
|
||||
</Subtitle>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user