diff --git a/components/BookingWidget/Client.tsx b/components/BookingWidget/Client.tsx index 5906ec34d..69bdd1c42 100644 --- a/components/BookingWidget/Client.tsx +++ b/components/BookingWidget/Client.tsx @@ -85,7 +85,7 @@ export default function BookingWidgetClient({ const selectedBookingCode = bookingWidgetSearchData ? bookingWidgetSearchData.bookingCode - : undefined + : "" const defaultRoomsData: BookingWidgetSchema["rooms"] = bookingWidgetSearchData?.rooms?.map((room) => ({ @@ -113,7 +113,7 @@ export default function BookingWidgetClient({ : now.utc().add(1, "day").format("YYYY-MM-DD"), }, bookingCode: { - value: selectedBookingCode ?? "", + value: selectedBookingCode, remember: false, }, redemption: false, @@ -156,36 +156,36 @@ export default function BookingWidgetClient({ }, []) useEffect(() => { - const sessionStorageSearchData = - typeof window !== "undefined" - ? sessionStorage.getItem("searchData") - : undefined + if (typeof window !== "undefined" && !selectedLocation) { + const sessionStorageSearchData = sessionStorage.getItem("searchData") - const initialSelectedLocation: Location | undefined = - sessionStorageSearchData && isValidJson(sessionStorageSearchData) - ? JSON.parse(sessionStorageSearchData) - : undefined + const initialSelectedLocation: Location | undefined = + sessionStorageSearchData && isValidJson(sessionStorageSearchData) + ? JSON.parse(sessionStorageSearchData) + : undefined - !selectedLocation?.name && initialSelectedLocation?.name && - methods.setValue("search", initialSelectedLocation.name) - !selectedLocation && + methods.setValue("search", initialSelectedLocation.name) sessionStorageSearchData && - methods.setValue("location", encodeURIComponent(sessionStorageSearchData)) + methods.setValue( + "location", + encodeURIComponent(sessionStorageSearchData) + ) + } + }, [methods, selectedLocation]) - const storedBookingCode = - typeof window !== "undefined" - ? localStorage.getItem("bookingCode") - : undefined - const initialBookingCode: BookingCodeSchema | undefined = - storedBookingCode && isValidJson(storedBookingCode) - ? JSON.parse(storedBookingCode) - : undefined - !selectedBookingCode && - initialBookingCode && - initialBookingCode.remember && - methods.setValue("bookingCode", initialBookingCode) - }, [methods, selectedLocation, selectedBookingCode]) + useEffect(() => { + if (typeof window !== "undefined" && !selectedBookingCode) { + const storedBookingCode = localStorage.getItem("bookingCode") + const initialBookingCode: BookingCodeSchema | undefined = + storedBookingCode && isValidJson(storedBookingCode) + ? JSON.parse(storedBookingCode) + : undefined + + initialBookingCode?.remember && + methods.setValue("bookingCode", initialBookingCode) + } + }, [methods, selectedBookingCode]) return ( diff --git a/components/Forms/BookingWidget/FormContent/BookingCode/booking-code.module.css b/components/Forms/BookingWidget/FormContent/BookingCode/booking-code.module.css index e1528b677..169f0b512 100644 --- a/components/Forms/BookingWidget/FormContent/BookingCode/booking-code.module.css +++ b/components/Forms/BookingWidget/FormContent/BookingCode/booking-code.module.css @@ -1,7 +1,12 @@ +.container { + position: relative; +} + .bookingCodeLabel { display: flex; align-items: center; gap: var(--Spacing-x-half); + position: relative; } .error { @@ -13,10 +18,33 @@ min-width: 20px; } -.bookingCodeRemember { - display: flex; - gap: var(--Spacing-x1); - - /* ToDo: Remove once remember checkbox design are ready */ +.bookingCodeRemember, +.bookingCodeRememberVisible { display: none; + gap: var(--Spacing-x1); +} + +.bookingCodeRememberVisible { + display: flex; + position: absolute; + top: calc(100% + 16px); + width: 100%; +} + +@media screen and (max-width: 768px) { + .hideOnMobile { + display: none; + } +} + +@media screen and (min-width: 1367px) { + .bookingCodeRememberVisible { + padding: var(--Spacing-x2); + border-radius: var(--Spacing-x-one-and-half); + width: 320px; + background: white; + top: calc(100% + 24px); + justify-content: space-between; + align-items: center; + } } diff --git a/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx b/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx index 58adeb8c3..118e1f9a8 100644 --- a/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx +++ b/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx @@ -1,10 +1,14 @@ +import { useCallback, useEffect, useRef, useState } from "react" +import { Dialog, DialogTrigger, Popover } from "react-aria-components" import { useFormContext } from "react-hook-form" import { useIntl } from "react-intl" +import { useMediaQuery } from "usehooks-ts" import { ErrorCircleIcon, InfoCircleIcon } from "@/components/Icons" import Modal from "@/components/Modal" import Button from "@/components/TempDesignSystem/Button" import Checkbox from "@/components/TempDesignSystem/Form/Checkbox" +import Switch from "@/components/TempDesignSystem/Form/Switch" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" @@ -19,72 +23,228 @@ import type { export default function BookingCode() { const intl = useIntl() + const checkIsTablet = useMediaQuery( + "(min-width: 768px) and (max-width: 1367px)" + ) + const checkIsDesktop = useMediaQuery("(min-width: 1367px)") + const [isTablet, setIsTablet] = useState(false) + const [isDesktop, setIsDesktop] = useState(false) const { setValue, formState: { errors }, getValues, } = useFormContext() - const codeError = errors["bookingCode"]?.value + const bookingCode: BookingCodeSchema = getValues("bookingCode") + const [isOpen, setIsOpen] = useState(!!bookingCode?.value) + const [showRemember, setShowRemember] = useState(false) + const [showRememberMobile, setShowRememberMobile] = useState(false) + const codeError = errors["bookingCode"]?.value const codeVoucher = intl.formatMessage({ id: "Code / Voucher" }) const addCode = intl.formatMessage({ id: "Add code" }) const bookingCodeTooltipText = intl.formatMessage({ - id: "booking.codes.information", + id: "If you're booking a promotional offer or a Corporate negotiated rate you'll need a special booking code. Don't use any special characters such as (.) (,) (-) (:). If you would like to make a booking with code VOF, please call us +46 8 517 517 20.Save your booking code for the next time you visit the page by ticking the box “Remember”. Don't tick the box if you're using a public computer to avoid unauthorized access to your booking code.", }) - const bookingCode: BookingCodeSchema = getValues("bookingCode") + const ref = useRef(null) function updateBookingCodeFormValue(value: string) { setValue("bookingCode.value", value, { shouldValidate: true }) } - return ( + function toggleModal(isOpen: boolean) { + if (!isOpen && codeError) { + // console.log("Cannot be closed!!") + // setValue("bookingCode.flag", false) + } else if (!isOpen && !bookingCode?.value) { + setValue("bookingCode.flag", false) + setIsOpen(isOpen) + } else { + setIsOpen(isOpen) + if (isOpen || bookingCode?.value) { + setValue("bookingCode.flag", true) + } + } + } + const closeIfOutside = useCallback( + (target: HTMLElement) => { + if (ref.current && target && !ref.current.contains(target)) { + setShowRemember(false) + } + }, + [setShowRemember, ref] + ) + + function showRememberCheck() { + setShowRemember(true) + } + + useEffect(() => { + setIsTablet(checkIsTablet) + }, [checkIsTablet]) + + useEffect(() => { + setIsDesktop(checkIsDesktop) + }, [checkIsDesktop]) + + const isRememberMobileVisible = + !isDesktop && (showRemember || !!bookingCode?.remember) + useEffect(() => { + setShowRememberMobile(isRememberMobileVisible) + }, [isRememberMobileVisible]) + + useEffect(() => { + function handleClickOutside(evt: Event) { + if (showRemember) { + const target = evt.target as HTMLElement + closeIfOutside(target) + } + } + document.body.addEventListener("click", handleClickOutside) + return () => { + document.body.removeEventListener("click", handleClickOutside) + } + }, [closeIfOutside, showRemember]) + + return isTablet ? ( <> -