"use client" import { zodResolver } from "@hookform/resolvers/zod" import { usePathname, useRouter } from "next/navigation" import { useState } from "react" import { Dialog } from "react-aria-components" import { FormProvider, useForm } from "react-hook-form" import { useIntl } from "react-intl" import { profileEdit } from "@scandic-hotels/common/constants/routes/myPages" import { formatPhoneNumber } from "@scandic-hotels/common/utils/phone" import { Button } from "@scandic-hotels/design-system/Button" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import Modal from "@scandic-hotels/design-system/Modal" import { ModalContentWithActions } from "@scandic-hotels/design-system/Modal/ModalContentWithActions" import { toast } from "@scandic-hotels/design-system/Toast" import { Typography } from "@scandic-hotels/design-system/Typography" import { trpc } from "@scandic-hotels/trpc/client" import { isWebview } from "@/constants/routes/webviews" import MembershipLevelIcon from "@/components/Levels/Icon" import useLang from "@/hooks/useLang" import ModifyContact from "../ModifyContact" import styles from "./guestDetails.module.css" import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation" import { type ModifyContactSchema, modifyContactSchema, } from "@/types/components/hotelReservation/myStay/modifyContact" import { MODAL_STEPS } from "@/types/components/hotelReservation/myStay/myStay" import type { SafeUser } from "@/types/user" type GuestDetailsProps = { refId: string guest: BookingConfirmation["booking"]["guest"] isCancelled: boolean user: SafeUser } export default function GuestDetails({ refId, guest, isCancelled, user, }: GuestDetailsProps) { const intl = useIntl() const lang = useLang() const router = useRouter() const utils = trpc.useUtils() const [currentStep, setCurrentStep] = useState(MODAL_STEPS.INITIAL) const [isLoading, setIsLoading] = useState(false) const pathname = usePathname() const [isModifyGuestDetailsOpen, setIsModifyGuestDetailsOpen] = useState(false) const form = useForm({ resolver: zodResolver(modifyContactSchema), defaultValues: { firstName: guest.firstName, lastName: guest.lastName, email: "", phoneNumber: "", // Default country code to guest country code since we don't have anything better to default to phoneNumberCC: guest.countryCode.toLowerCase(), countryCode: guest.countryCode, }, mode: "all", reValidateMode: "onChange", }) const isFirstStep = currentStep === MODAL_STEPS.INITIAL const isMemberBooking = !!user?.membership?.membershipNumber && guest.membershipNumber === user?.membership?.membershipNumber const updateGuest = trpc.booking.update.useMutation({ onMutate: () => setIsLoading(true), onSuccess: (data) => { if (data) { utils.booking.get.invalidate({ refId: data.refId, }) toast.success( intl.formatMessage({ id: "myStay.guestDetails.updatedSuccess", defaultMessage: "Guest details updated", }) ) setIsModifyGuestDetailsOpen(false) setCurrentStep(MODAL_STEPS.INITIAL) document.cookie = `bv=${JSON.stringify({ email: data.guest.email, firstName: data.guest.firstName, lastName: data.guest.lastName, confirmationNumber: data.confirmationNumber, })}; Path=/; Max-Age=600; Secure; SameSite=Strict` router.refresh() } else { toast.error( intl.formatMessage({ id: "myStay.guestDetails.updatedError", defaultMessage: "Failed to update guest details", }) ) } }, onError: () => { toast.error( intl.formatMessage({ id: "myStay.guestDetails.updatedError", defaultMessage: "Failed to update guest details", }) ) }, onSettled: () => { setIsLoading(false) }, }) async function onSubmit(data: ModifyContactSchema) { updateGuest.mutate({ refId, guest: { email: data.email, phoneNumber: formatPhoneNumber(data.phoneNumber, data.phoneNumberCC), countryCode: data.countryCode, }, language: lang, }) } function handleModifyMemberDetails() { const expirationTime = Date.now() + 10 * 60 * 1000 sessionStorage.setItem( "myStayReturnRoute", JSON.stringify({ path: window.location.href, expiry: expirationTime, }) ) router.push(profileEdit[lang]) } return (
{isMemberBooking && user.membership && (

{intl.formatMessage({ id: "myStay.yourMemberLevel", defaultMessage: "Your member level", })}

{intl.formatMessage({ id: "myStay.myTotalPoints", defaultMessage: "My total points", })}

{user.membership.currentPoints}

)}

{guest.firstName} {guest.lastName}

{isMemberBooking && user?.membership && (

{intl.formatMessage( { id: "myStay.membershipId", defaultMessage: "Membership ID: {nr}", }, { nr: user.membership.membershipNumber, } )}

)}

{guest.email}

{guest.phoneNumber}

{guest.email}

{guest.phoneNumber}

{!isWebview(pathname) && ( <> {isMemberBooking ? ( ) : ( <> {isModifyGuestDetailsOpen && ( {({ close }) => ( setIsModifyGuestDetailsOpen(false)} content={ guest && ( ) } primaryAction={{ label: isFirstStep ? intl.formatMessage({ id: "myStay.modifyContact.saveUpdates", defaultMessage: "Save updates", }) : intl.formatMessage({ id: "common.confirm", defaultMessage: "Confirm", }), onPress: () => isFirstStep ? setCurrentStep(MODAL_STEPS.CONFIRMATION) : form.handleSubmit(onSubmit)(), type: isFirstStep ? "button" : "submit", isDisabled: !form.formState.isValid, isPending: isLoading, variant: isFirstStep ? "Secondary" : "Primary", }} secondaryAction={{ label: isFirstStep ? intl.formatMessage({ id: "common.back", defaultMessage: "Back", }) : intl.formatMessage({ id: "common.cancel", defaultMessage: "Cancel", }), onPress: () => { close() setCurrentStep(MODAL_STEPS.INITIAL) }, }} /> )} )} )} )}
) }