From ca3819f7cc52131a268b61e811a229bd2f779af8 Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Tue, 12 Nov 2024 16:45:25 +0100 Subject: [PATCH] fix: remove guest picker store --- app/globals.css | 2 + components/BookingWidget/Client.tsx | 40 +-- .../MobileToggleButton/button.module.css | 2 - .../MobileToggleButton/index.tsx | 7 - .../BookingWidget/bookingWidget.module.css | 96 ++++---- .../Forms/BookingWidget/FormContent/index.tsx | 12 +- .../GuestsRoomsPicker/AdultSelector/index.tsx | 38 ++- .../ChildSelector/ChildInfoSelector.tsx | 35 +-- .../GuestsRoomsPicker/ChildSelector/index.tsx | 41 ++-- components/GuestsRoomsPicker/Dialog.tsx | 130 ---------- components/GuestsRoomsPicker/Form.tsx | 146 +++++++++++ .../Provider/GuestsRoomsProvider.tsx | 26 -- .../guests-rooms-picker.module.css | 70 ++++-- components/GuestsRoomsPicker/index.tsx | 80 +++--- stores/guests-rooms.ts | 227 ------------------ stores/sticky-position.ts | 2 - .../bookingWidget/guestsRoomsPicker.ts | 11 +- 17 files changed, 368 insertions(+), 597 deletions(-) delete mode 100644 components/GuestsRoomsPicker/Dialog.tsx create mode 100644 components/GuestsRoomsPicker/Form.tsx delete mode 100644 components/GuestsRoomsPicker/Provider/GuestsRoomsProvider.tsx delete mode 100644 stores/guests-rooms.ts diff --git a/app/globals.css b/app/globals.css index 7dd0c44fb..a266e9f31 100644 --- a/app/globals.css +++ b/app/globals.css @@ -114,6 +114,8 @@ /* Z-INDEX */ --header-z-index: 11; --menu-overlay-z-index: 11; + --booking-widget-z-index: 10; + --booking-widget-open-z-index: 100; --dialog-z-index: 9; --sidepeek-z-index: 100; --lightbox-z-index: 150; diff --git a/components/BookingWidget/Client.tsx b/components/BookingWidget/Client.tsx index 70daa6a20..3819eb912 100644 --- a/components/BookingWidget/Client.tsx +++ b/components/BookingWidget/Client.tsx @@ -36,7 +36,6 @@ export default function BookingWidgetClient({ name: StickyElementNameEnum.BOOKING_WIDGET, }) - const bookingWidgetSearchData: BookingWidgetSearchParams | undefined = searchParams ? (getFormattedUrlQueryParams(new URLSearchParams(searchParams), { @@ -79,9 +78,7 @@ export default function BookingWidgetClient({ const methods = useForm({ defaultValues: { search: selectedLocation?.name ?? "", - location: selectedLocation - ? JSON.stringify(selectedLocation) - : undefined, + location: selectedLocation ? JSON.stringify(selectedLocation) : undefined, date: { // UTC is required to handle requests from far away timezones https://scandichotels.atlassian.net/browse/SWAP-6375 & PET-507 // This is specifically to handle timezones falling in different dates. @@ -147,29 +144,34 @@ export default function BookingWidgetClient({ ? JSON.parse(sessionStorageSearchData) : undefined - !(selectedLocation?.name) && initialSelectedLocation?.name && + !selectedLocation?.name && + initialSelectedLocation?.name && methods.setValue("search", initialSelectedLocation.name) - !selectedLocation && sessionStorageSearchData && + !selectedLocation && + sessionStorageSearchData && methods.setValue("location", encodeURIComponent(sessionStorageSearchData)) }, [methods, selectedLocation]) return ( -
-
-
-
- - +
+ +
+ + +
- ) } diff --git a/components/BookingWidget/MobileToggleButton/button.module.css b/components/BookingWidget/MobileToggleButton/button.module.css index 9a0912b07..1742ee38a 100644 --- a/components/BookingWidget/MobileToggleButton/button.module.css +++ b/components/BookingWidget/MobileToggleButton/button.module.css @@ -6,8 +6,6 @@ display: grid; gap: var(--Spacing-x-one-and-half); padding: var(--Spacing-x2); - position: sticky; - top: 0; z-index: 1; background-color: var(--Base-Surface-Primary-light-Normal); } diff --git a/components/BookingWidget/MobileToggleButton/index.tsx b/components/BookingWidget/MobileToggleButton/index.tsx index 80026ff93..8ecdfd606 100644 --- a/components/BookingWidget/MobileToggleButton/index.tsx +++ b/components/BookingWidget/MobileToggleButton/index.tsx @@ -31,12 +31,6 @@ export default function MobileToggleButton({ const location = useWatch({ name: "location" }) const rooms: BookingWidgetSchema["rooms"] = useWatch({ name: "rooms" }) - const bookingWidgetMobileRef = useRef(null) - useStickyPosition({ - ref: bookingWidgetMobileRef, - name: StickyElementNameEnum.BOOKING_WIDGET_MOBILE, - }) - const parsedLocation: Location | null = location ? JSON.parse(decodeURIComponent(location)) : null @@ -75,7 +69,6 @@ export default function MobileToggleButton({ className={locationAndDateIsSet ? styles.complete : styles.partial} onClick={openMobileSearch} role="button" - ref={bookingWidgetMobileRef} > {!locationAndDateIsSet && ( <> diff --git a/components/BookingWidget/bookingWidget.module.css b/components/BookingWidget/bookingWidget.module.css index f0dec979d..ccf77032c 100644 --- a/components/BookingWidget/bookingWidget.module.css +++ b/components/BookingWidget/bookingWidget.module.css @@ -1,60 +1,62 @@ -.containerDesktop, -.containerMobile, -.close { - display: none; +.wrapper { + position: sticky; + z-index: var(--booking-widget-z-index); } -@media screen and (max-width: 767px) { - .containerMobile { - background-color: var(--UI-Input-Controls-Surface-Normal); - bottom: -100%; - display: grid; - gap: var(--Spacing-x3); - grid-template-rows: 36px 1fr; - height: calc(100dvh - 20px); - padding: var(--Spacing-x3) var(--Spacing-x2) var(--Spacing-x7); - position: fixed; - transition: bottom 300ms ease; - width: 100%; - z-index: 10000; - border-radius: var(--Corner-radius-Large) var(--Corner-radius-Large) 0 0; - } +.formContainer { + display: grid; + grid-template-rows: 36px 1fr; + background-color: var(--UI-Input-Controls-Surface-Normal); + border-radius: var(--Corner-radius-Large) var(--Corner-radius-Large) 0 0; + gap: var(--Spacing-x3); + height: calc(100dvh - 20px); + width: 100%; + padding: var(--Spacing-x3) var(--Spacing-x2) var(--Spacing-x7); + position: fixed; + bottom: -100%; + transition: bottom 300ms ease; +} - .containerMobile[data-open="true"] { - bottom: 0; - } +.wrapper[data-open="true"] { + z-index: var(--booking-widget-open-z-index); +} - .close { - background: none; - border: none; - cursor: pointer; - justify-self: flex-end; - } +.wrapper[data-open="true"] .formContainer { + bottom: 0; +} - .containerMobile[data-open="true"] + .backdrop { - background-color: rgba(0, 0, 0, 0.4); - height: 100%; - left: 0; - position: absolute; - top: 0; - width: 100%; - z-index: 1000; - } +.close { + background: none; + border: none; + cursor: pointer; + justify-self: flex-end; +} + +.wrapper[data-open="true"] + .backdrop { + background-color: rgba(0, 0, 0, 0.4); + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + z-index: calc(var(--booking-widget-open-z-index) - 1); } @media screen and (min-width: 768px) { - .containerDesktop { - display: block; - box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05); - position: sticky; + .wrapper { top: 0; - z-index: 10; - background-color: var(--Base-Surface-Primary-light-Normal); } -} -@media screen and (min-width: 1367px) { - .container { - z-index: 9; + .formContainer { + display: block; + background-color: var(--Base-Surface-Primary-light-Normal); + box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05); + height: auto; + position: static; + padding: 0; + } + + .close { + display: none; } } diff --git a/components/Forms/BookingWidget/FormContent/index.tsx b/components/Forms/BookingWidget/FormContent/index.tsx index d5dba4d47..8001747e6 100644 --- a/components/Forms/BookingWidget/FormContent/index.tsx +++ b/components/Forms/BookingWidget/FormContent/index.tsx @@ -1,5 +1,4 @@ "use client" -import { useState } from "react" import { useWatch } from "react-hook-form" import { useIntl } from "react-intl" @@ -7,7 +6,6 @@ import { dt } from "@/lib/dt" import DatePicker from "@/components/DatePicker" import GuestsRoomsPickerForm from "@/components/GuestsRoomsPicker" -import GuestsRoomsProvider from "@/components/GuestsRoomsPicker/Provider/GuestsRoomsProvider" import { SearchIcon } from "@/components/Icons" import Button from "@/components/TempDesignSystem/Button" import Caption from "@/components/TempDesignSystem/Text/Caption" @@ -26,12 +24,10 @@ export default function FormContent({ const intl = useIntl() const selectedDate = useWatch({ name: "date" }) - const rooms = intl.formatMessage({ id: "Guests & Rooms" }) + const roomsLabel = intl.formatMessage({ id: "Guests & Rooms" }) const nights = dt(selectedDate.toDate).diff(dt(selectedDate.fromDate), "days") - const selectedGuests = useWatch({ name: "rooms" }) - return ( <>
@@ -51,12 +47,10 @@ export default function FormContent({
- - - +
diff --git a/components/GuestsRoomsPicker/AdultSelector/index.tsx b/components/GuestsRoomsPicker/AdultSelector/index.tsx index b24d5f681..d9069b6d0 100644 --- a/components/GuestsRoomsPicker/AdultSelector/index.tsx +++ b/components/GuestsRoomsPicker/AdultSelector/index.tsx @@ -3,8 +3,6 @@ import { useFormContext } from "react-hook-form" import { useIntl } from "react-intl" -import { useGuestsRoomsStore } from "@/stores/guests-rooms" - import Caption from "@/components/TempDesignSystem/Text/Caption" import Counter from "../Counter" @@ -13,39 +11,37 @@ import styles from "./adult-selector.module.css" import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" import { - AdultSelectorProps, Child, + SelectorProps, } from "@/types/components/bookingWidget/guestsRoomsPicker" -export default function AdultSelector({ roomIndex = 0 }: AdultSelectorProps) { +export default function AdultSelector({ + roomIndex = 0, + currentAdults, + currentChildren, + childrenInAdultsBed, +}: SelectorProps) { const intl = useIntl() const adultsLabel = intl.formatMessage({ id: "Adults" }) const { setValue } = useFormContext() - const { adults, child, childrenInAdultsBed } = useGuestsRoomsStore( - (state) => state.rooms[roomIndex] - ) - const increaseAdults = useGuestsRoomsStore((state) => state.increaseAdults) - const decreaseAdults = useGuestsRoomsStore((state) => state.decreaseAdults) function increaseAdultsCount(roomIndex: number) { - if (adults < 6) { - increaseAdults(roomIndex) - setValue(`rooms.${roomIndex}.adults`, adults + 1) + if (currentAdults < 6) { + setValue(`rooms.${roomIndex}.adults`, currentAdults + 1) } } function decreaseAdultsCount(roomIndex: number) { - if (adults > 1) { - decreaseAdults(roomIndex) - setValue(`rooms.${roomIndex}.adults`, adults - 1) - if (childrenInAdultsBed > adults) { - const toUpdateIndex = child.findIndex( + if (currentAdults > 1) { + setValue(`rooms.${roomIndex}.adults`, currentAdults - 1) + if (childrenInAdultsBed > currentAdults) { + const toUpdateIndex = currentChildren.findIndex( (child: Child) => child.bed == ChildBedMapEnum.IN_ADULTS_BED ) if (toUpdateIndex != -1) { setValue( `rooms.${roomIndex}.children.${toUpdateIndex}.bed`, - child[toUpdateIndex].age < 3 + currentChildren[toUpdateIndex].age < 3 ? ChildBedMapEnum.IN_CRIB : ChildBedMapEnum.IN_EXTRA_BED ) @@ -60,15 +56,15 @@ export default function AdultSelector({ roomIndex = 0 }: AdultSelectorProps) { {adultsLabel} { decreaseAdultsCount(roomIndex) }} handleOnIncrease={() => { increaseAdultsCount(roomIndex) }} - disableDecrease={adults == 1} - disableIncrease={adults == 6} + disableDecrease={currentAdults == 1} + disableIncrease={currentAdults == 6} />
) diff --git a/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx b/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx index d8e541eb3..83e3893d1 100644 --- a/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx +++ b/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx @@ -3,8 +3,6 @@ import { useFormContext } from "react-hook-form" import { useIntl } from "react-intl" -import { useGuestsRoomsStore } from "@/stores/guests-rooms" - import { ErrorCircleIcon } from "@/components/Icons" import Select from "@/components/TempDesignSystem/Select" import Caption from "@/components/TempDesignSystem/Text/Caption" @@ -19,6 +17,8 @@ import { export default function ChildInfoSelector({ child = { age: -1, bed: -1 }, + childrenInAdultsBed, + adults, index = 0, roomIndex = 0, }: ChildInfoSelectorProps) { @@ -26,23 +26,7 @@ export default function ChildInfoSelector({ const ageLabel = intl.formatMessage({ id: "Age" }) const ageReqdErrMsg = intl.formatMessage({ id: "Child age is required" }) const bedLabel = intl.formatMessage({ id: "Bed" }) - const { setValue } = useFormContext() - const { adults, childrenInAdultsBed } = useGuestsRoomsStore( - (state) => state.rooms[roomIndex] - ) - const { - isValidated, - updateChildAge, - updateChildBed, - increaseChildInAdultsBed, - decreaseChildInAdultsBed, - } = useGuestsRoomsStore((state) => ({ - isValidated: state.isValidated, - updateChildAge: state.updateChildAge, - updateChildBed: state.updateChildBed, - increaseChildInAdultsBed: state.increaseChildInAdultsBed, - decreaseChildInAdultsBed: state.decreaseChildInAdultsBed, - })) + const { setValue, formState } = useFormContext() const ageList = Array.from(Array(13).keys()).map((age) => ({ label: `${age}`, @@ -50,7 +34,6 @@ export default function ChildInfoSelector({ })) function updateSelectedAge(age: number) { - updateChildAge(age, roomIndex, index) setValue(`rooms.${roomIndex}.child.${index}.age`, age, { shouldValidate: true, }) @@ -59,12 +42,6 @@ export default function ChildInfoSelector({ } function updateSelectedBed(bed: number) { - if (bed == ChildBedMapEnum.IN_ADULTS_BED) { - increaseChildInAdultsBed(roomIndex) - } else if (child.bed == ChildBedMapEnum.IN_ADULTS_BED) { - decreaseChildInAdultsBed(roomIndex) - } - updateChildBed(bed, roomIndex, index) setValue(`rooms.${roomIndex}.child.${index}.bed`, bed) } @@ -97,6 +74,7 @@ export default function ChildInfoSelector({ return availableBedTypes } + console.log("ALL TJHE ERORRORS", formState.errors) return ( <>
@@ -131,12 +109,13 @@ export default function ChildInfoSelector({ ) : null}
- {isValidated && child.age < 0 ? ( + + {/* {isValidated && child.age < 0 ? ( {ageReqdErrMsg} - ) : null} + ) : null} */} ) } diff --git a/components/GuestsRoomsPicker/ChildSelector/index.tsx b/components/GuestsRoomsPicker/ChildSelector/index.tsx index 22d594397..2d8db11f0 100644 --- a/components/GuestsRoomsPicker/ChildSelector/index.tsx +++ b/components/GuestsRoomsPicker/ChildSelector/index.tsx @@ -3,8 +3,6 @@ import { useFormContext } from "react-hook-form" import { useIntl } from "react-intl" -import { useGuestsRoomsStore } from "@/stores/guests-rooms" - import Caption from "@/components/TempDesignSystem/Text/Caption" import Counter from "../Counter" @@ -13,25 +11,22 @@ import ChildInfoSelector from "./ChildInfoSelector" import styles from "./child-selector.module.css" import { BookingWidgetSchema } from "@/types/components/bookingWidget" -import { ChildSelectorProps } from "@/types/components/bookingWidget/guestsRoomsPicker" +import { SelectorProps } from "@/types/components/bookingWidget/guestsRoomsPicker" -export default function ChildSelector({ roomIndex = 0 }: ChildSelectorProps) { +export default function ChildSelector({ + roomIndex = 0, + currentAdults, + childrenInAdultsBed, + currentChildren, +}: SelectorProps) { const intl = useIntl() const childrenLabel = intl.formatMessage({ id: "Children" }) - const { setValue, trigger } = useFormContext() - const children = useGuestsRoomsStore((state) => state.rooms[roomIndex].child) - const increaseChildren = useGuestsRoomsStore( - (state) => state.increaseChildren - ) - const decreaseChildren = useGuestsRoomsStore( - (state) => state.decreaseChildren - ) + const { setValue } = useFormContext() function increaseChildrenCount(roomIndex: number) { - if (children.length < 5) { - increaseChildren(roomIndex) + if (currentChildren.length < 5) { setValue( - `rooms.${roomIndex}.child.${children.length}`, + `rooms.${roomIndex}.child.${currentChildren.length}`, { age: -1, bed: -1, @@ -41,9 +36,9 @@ export default function ChildSelector({ roomIndex = 0 }: ChildSelectorProps) { } } function decreaseChildrenCount(roomIndex: number) { - if (children.length > 0) { - const newChildrenList = decreaseChildren(roomIndex) - setValue(`rooms.${roomIndex}.child`, newChildrenList, { + if (currentChildren.length > 0) { + currentChildren.pop() + setValue(`rooms.${roomIndex}.child`, currentChildren, { shouldValidate: true, }) } @@ -56,23 +51,25 @@ export default function ChildSelector({ roomIndex = 0 }: ChildSelectorProps) { {childrenLabel} { decreaseChildrenCount(roomIndex) }} handleOnIncrease={() => { increaseChildrenCount(roomIndex) }} - disableDecrease={children.length == 0} - disableIncrease={children.length == 5} + disableDecrease={currentChildren.length == 0} + disableIncrease={currentChildren.length == 5} /> - {children.map((child, index) => ( + {currentChildren.map((child, index) => ( ))} diff --git a/components/GuestsRoomsPicker/Dialog.tsx b/components/GuestsRoomsPicker/Dialog.tsx deleted file mode 100644 index 1c5d8e53d..000000000 --- a/components/GuestsRoomsPicker/Dialog.tsx +++ /dev/null @@ -1,130 +0,0 @@ -"use client" -import { Dialog } from "react-aria-components" -import { useFormContext } from "react-hook-form" -import { useIntl } from "react-intl" - -import { useGuestsRoomsStore } from "@/stores/guests-rooms" - -import { CloseLargeIcon, PlusCircleIcon, PlusIcon } from "../Icons" -import Button from "../TempDesignSystem/Button" -import Divider from "../TempDesignSystem/Divider" -import Subtitle from "../TempDesignSystem/Text/Subtitle" -import { Tooltip } from "../TempDesignSystem/Tooltip" -import AdultSelector from "./AdultSelector" -import ChildSelector from "./ChildSelector" - -import styles from "./guests-rooms-picker.module.css" - -import { BookingWidgetSchema } from "@/types/components/bookingWidget" - -export default function GuestsRoomsPickerDialog() { - const intl = useIntl() - const doneLabel = intl.formatMessage({ id: "Done" }) - const roomLabel = intl.formatMessage({ id: "Room" }) - const disabledBookingOptionsHeader = intl.formatMessage({ - id: "Disabled booking options header", - }) - const disabledBookingOptionsText = intl.formatMessage({ - id: "Disabled adding room", - }) - const addRoomLabel = intl.formatMessage({ id: "Add Room" }) - - const { getFieldState } = useFormContext() - - const rooms = useGuestsRoomsStore((state) => state.rooms) - - return ( - - {({ close }) => { - return ( - <> -
- -
-
- {rooms.map((room, index) => ( -
-
- - {roomLabel} {index + 1} - - - -
- -
- ))} -
- - {rooms.length < 4 ? ( - - ) : null} - -
-
-
-
- - {rooms.length < 4 ? ( - - ) : null} - -
- - -
- - ) - }} -
- ) -} diff --git a/components/GuestsRoomsPicker/Form.tsx b/components/GuestsRoomsPicker/Form.tsx new file mode 100644 index 000000000..74f1dab6b --- /dev/null +++ b/components/GuestsRoomsPicker/Form.tsx @@ -0,0 +1,146 @@ +"use client" + +import { useFormContext } from "react-hook-form" +import { useIntl } from "react-intl" + +import { CloseLargeIcon, PlusCircleIcon, PlusIcon } from "../Icons" +import Button from "../TempDesignSystem/Button" +import Divider from "../TempDesignSystem/Divider" +import Subtitle from "../TempDesignSystem/Text/Subtitle" +import { Tooltip } from "../TempDesignSystem/Tooltip" +import AdultSelector from "./AdultSelector" +import ChildSelector from "./ChildSelector" + +import styles from "./guests-rooms-picker.module.css" + +import { BookingWidgetSchema } from "@/types/components/bookingWidget" +import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" +import { GuestsRoom } from "@/types/components/bookingWidget/guestsRoomsPicker" + +export default function GuestsRoomsPickerDialog({ + rooms, + onClose, +}: { + rooms: GuestsRoom[] + onClose: () => void +}) { + const intl = useIntl() + const doneLabel = intl.formatMessage({ id: "Done" }) + const roomLabel = intl.formatMessage({ id: "Room" }) + const disabledBookingOptionsHeader = intl.formatMessage({ + id: "Disabled booking options header", + }) + const disabledBookingOptionsText = intl.formatMessage({ + id: "Disabled adding room", + }) + const addRoomLabel = intl.formatMessage({ id: "Add Room" }) + + const { getFieldState } = useFormContext() + + return ( + <> +
+ +
+
+ {rooms.map((room, index) => { + const currentAdults = room.adults + const currentChildren = room.child + const childrenInAdultsBed = currentChildren.filter( + (child) => child.bed === ChildBedMapEnum.IN_ADULTS_BED + ).length + + return ( +
+
+ + {roomLabel} {index + 1} + + + +
+ +
+ ) + })} +
+ + {rooms.length < 4 ? ( + + ) : null} + +
+
+
+
+ + {rooms.length < 4 ? ( + + ) : null} + +
+ + +
+ + ) +} diff --git a/components/GuestsRoomsPicker/Provider/GuestsRoomsProvider.tsx b/components/GuestsRoomsPicker/Provider/GuestsRoomsProvider.tsx deleted file mode 100644 index 5a85102e7..000000000 --- a/components/GuestsRoomsPicker/Provider/GuestsRoomsProvider.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client" -import { PropsWithChildren, useRef } from "react" - -import { - GuestsRoomsContext, - type GuestsRoomsStore, - initGuestsRoomsState, -} from "@/stores/guests-rooms" - -import { GuestsRoom } from "@/types/components/bookingWidget/guestsRoomsPicker" - -export default function GuestsRoomsProvider({ - selectedGuests, - children, -}: PropsWithChildren<{ selectedGuests?: GuestsRoom[] }>) { - const initialStore = useRef() - if (!initialStore.current) { - initialStore.current = initGuestsRoomsState(selectedGuests) - } - - return ( - - {children} - - ) -} diff --git a/components/GuestsRoomsPicker/guests-rooms-picker.module.css b/components/GuestsRoomsPicker/guests-rooms-picker.module.css index 01dea2e78..0a6c09a6f 100644 --- a/components/GuestsRoomsPicker/guests-rooms-picker.module.css +++ b/components/GuestsRoomsPicker/guests-rooms-picker.module.css @@ -1,7 +1,23 @@ -.container { - overflow: hidden; - position: relative; +.triggerDesktop { + display: none; } + +.pickerContainerMobile { + background-color: var(--Main-Grey-White); + border-radius: var(--Corner-radius-Large) var(--Corner-radius-Large) 0 0; + bottom: 0; + left: 0; + position: fixed; + right: 0; + top: 0; + transition: top 300ms ease; + z-index: 1000; +} + +.pickerContainerDesktop { + display: none; +} + .roomContainer { display: grid; gap: var(--Spacing-x2); @@ -23,9 +39,7 @@ width: 100%; text-align: left; } -.body { - opacity: 0.8; -} + .footer { display: grid; gap: var(--Spacing-x1); @@ -33,25 +47,7 @@ margin-top: var(--Spacing-x2); } -.pickerContainer { - --header-height: 72px; - --sticky-button-height: 140px; - background-color: var(--Main-Grey-White); - display: grid; - - border-radius: var(--Corner-radius-Large); - box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1); - - max-width: calc(100vw - 20px); - padding: var(--Spacing-x2) var(--Spacing-x3); - - width: 360px; -} @media screen and (max-width: 1366px) { - .container[data-isopen="true"] .hideWrapper { - top: 20px; - } - .contentContainer { grid-area: content; overflow-y: scroll; @@ -107,6 +103,32 @@ } @media screen and (min-width: 1367px) { + .pickerContainerMobisse { + display: none; + } + .triggerMobile { + display: none; + } + + .triggerDesktop { + display: block; + } + + .pickerContainerDesktop { + --header-height: 72px; + --sticky-button-height: 140px; + background-color: var(--Main-Grey-White); + display: grid; + + border-radius: var(--Corner-radius-Large); + box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1); + + max-width: calc(100vw - 20px); + padding: var(--Spacing-x2) var(--Spacing-x3); + + width: 360px; + } + .header { display: none; } diff --git a/components/GuestsRoomsPicker/index.tsx b/components/GuestsRoomsPicker/index.tsx index 84ef6f930..84595815c 100644 --- a/components/GuestsRoomsPicker/index.tsx +++ b/components/GuestsRoomsPicker/index.tsx @@ -1,37 +1,64 @@ "use client" -import { useCallback, useEffect, useRef, useState } from "react" -import { Button, DialogTrigger, Popover } from "react-aria-components" +import { + Button, + Dialog, + DialogTrigger, + Modal, + Popover, +} from "react-aria-components" import { useFormContext } from "react-hook-form" import { useIntl } from "react-intl" -import { useGuestsRoomsStore } from "@/stores/guests-rooms" - -import { guestRoomsSchema } from "@/components/Forms/BookingWidget/schema" import Body from "@/components/TempDesignSystem/Text/Body" -import Dialog from "./Dialog" +import PickerForm from "./Form" import styles from "./guests-rooms-picker.module.css" -export default function GuestsRoomsPickerForm({ - name = "rooms", +import { GuestsRoom } from "@/types/components/bookingWidget/guestsRoomsPicker" + +export default function GuestsRoomsPickerForm() { + const { watch } = useFormContext() + + const rooms = watch("rooms") as GuestsRoom[] + + return ( + <> + + + + + {({ close }) => } + + + + + + + + {({ close }) => } + + + + + ) +} + +function Trigger({ + rooms, + className, }: { - name: string + rooms: GuestsRoom[] + className: string }) { const intl = useIntl() - const { rooms, adultCount, childCount } = useGuestsRoomsStore((state) => ({ - rooms: state.rooms, - adultCount: state.adultCount, - childCount: state.childCount, - })) - return ( - - - - - - + ))} + + ) } diff --git a/stores/guests-rooms.ts b/stores/guests-rooms.ts deleted file mode 100644 index 04cfbc3ec..000000000 --- a/stores/guests-rooms.ts +++ /dev/null @@ -1,227 +0,0 @@ -"use client" - -import { produce } from "immer" -import { createContext, useContext } from "react" -import { create, useStore } from "zustand" - -import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" -import { - Child, - GuestsRoom, -} from "@/types/components/bookingWidget/guestsRoomsPicker" - -const SESSION_STORAGE_KEY = "guests_rooms" - -interface extendedGuestsRoom extends GuestsRoom { - childrenInAdultsBed: number -} -interface GuestsRoomsState { - rooms: extendedGuestsRoom[] - adultCount: number - childCount: number - isValidated: boolean -} - -interface GuestsRoomsStoreState extends GuestsRoomsState { - increaseAdults: (roomIndex: number) => void - decreaseAdults: (roomIndex: number) => void - increaseChildren: (roomIndex: number) => void - decreaseChildren: (roomIndex: number) => Child[] - updateChildAge: (age: number, roomIndex: number, childIndex: number) => void - updateChildBed: (bed: number, roomIndex: number, childIndex: number) => void - increaseChildInAdultsBed: (roomIndex: number) => void - decreaseChildInAdultsBed: (roomIndex: number) => void - increaseRoom: () => void - decreaseRoom: (roomIndex: number) => void - setIsValidated: (isValidated: boolean) => void -} - -export function validateBedTypes(data: extendedGuestsRoom[]) { - data.forEach((room) => { - room.child.forEach((child) => { - const allowedBedTypes: number[] = [] - if (child.age <= 5 && room.adults >= room.childrenInAdultsBed) { - allowedBedTypes.push(ChildBedMapEnum.IN_ADULTS_BED) - } else if (child.age <= 5) { - room.childrenInAdultsBed = room.childrenInAdultsBed - 1 - } - if (child.age < 3) { - allowedBedTypes.push(ChildBedMapEnum.IN_CRIB) - } - if (child.age > 2) { - allowedBedTypes.push(ChildBedMapEnum.IN_EXTRA_BED) - } - if (!allowedBedTypes.includes(child.bed)) { - child.bed = allowedBedTypes[0] - } - }) - }) -} - -export function initGuestsRoomsState(initData?: GuestsRoom[]) { - const isBrowser = typeof window !== "undefined" - const sessionData = isBrowser - ? sessionStorage.getItem(SESSION_STORAGE_KEY) - : null - - const defaultGuestsData: extendedGuestsRoom = { - adults: 1, - child: [], - childrenInAdultsBed: 0, - } - const defaultData: GuestsRoomsState = { - rooms: [defaultGuestsData], - adultCount: 1, - childCount: 0, - isValidated: false, - } - - let inputData: GuestsRoomsState = defaultData - if (sessionData) { - inputData = JSON.parse(sessionData) - } - if (initData) { - inputData.rooms = initData.map((room) => { - const childrenInAdultsBed = room.child - ? room.child.reduce((acc, child) => { - acc = acc + (child.bed == ChildBedMapEnum.IN_ADULTS_BED ? 1 : 0) - return acc - }, 0) - : 0 - return { ...defaultGuestsData, ...room, childrenInAdultsBed } - }) as extendedGuestsRoom[] - - inputData.adultCount = initData.reduce((acc, room) => { - acc = acc + room.adults - return acc - }, 0) - inputData.childCount = initData.reduce((acc, room) => { - acc = acc + room.child?.length - return acc - }, 0) - validateBedTypes(inputData.rooms) - } - - return create()((set, get) => ({ - ...inputData, - increaseAdults: (roomIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms[roomIndex].adults = state.rooms[roomIndex].adults + 1 - state.adultCount = state.adultCount + 1 - }) - ), - decreaseAdults: (roomIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms[roomIndex].adults = state.rooms[roomIndex].adults - 1 - state.adultCount = state.adultCount - 1 - if ( - state.rooms[roomIndex].childrenInAdultsBed > - state.rooms[roomIndex].adults - ) { - const toUpdateIndex = state.rooms[roomIndex].child.findIndex( - (child) => child.bed == ChildBedMapEnum.IN_ADULTS_BED - ) - if (toUpdateIndex != -1) { - state.rooms[roomIndex].child[toUpdateIndex].bed = - state.rooms[roomIndex].child[toUpdateIndex].age < 3 - ? ChildBedMapEnum.IN_CRIB - : ChildBedMapEnum.IN_EXTRA_BED - state.rooms[roomIndex].childrenInAdultsBed = - state.rooms[roomIndex].adults - } - } - }) - ), - increaseChildren: (roomIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms[roomIndex].child.push({ - age: -1, - bed: -1, - }) - state.childCount = state.childCount + 1 - }) - ), - decreaseChildren: (roomIndex) => { - set( - produce((state: GuestsRoomsState) => { - const roomChildren = state.rooms[roomIndex].child - if ( - roomChildren.length && - roomChildren[roomChildren.length - 1].bed == - ChildBedMapEnum.IN_ADULTS_BED - ) { - state.rooms[roomIndex].childrenInAdultsBed = - state.rooms[roomIndex].childrenInAdultsBed - 1 - } - state.rooms[roomIndex].child.pop() - state.childCount = state.childCount - 1 - }) - ) - return get().rooms[roomIndex].child - }, - updateChildAge: (age, roomIndex, childIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms[roomIndex].child[childIndex].age = age - }) - ), - updateChildBed: (bed, roomIndex, childIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms[roomIndex].child[childIndex].bed = bed - }) - ), - increaseChildInAdultsBed: (roomIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms[roomIndex].childrenInAdultsBed = - state.rooms[roomIndex].childrenInAdultsBed + 1 - }) - ), - decreaseChildInAdultsBed: (roomIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms[roomIndex].childrenInAdultsBed = - state.rooms[roomIndex].childrenInAdultsBed - 1 - }) - ), - increaseRoom: () => - set( - produce((state: GuestsRoomsState) => { - state.rooms.push({ - adults: 1, - child: [], - childrenInAdultsBed: 0, - }) - }) - ), - decreaseRoom: (roomIndex) => - set( - produce((state: GuestsRoomsState) => { - state.rooms.splice(roomIndex, 1) - }) - ), - setIsValidated: (isValidated) => set(() => ({ isValidated })), - })) -} - -export type GuestsRoomsStore = ReturnType - -export const GuestsRoomsContext = createContext(null) - -export const useGuestsRoomsStore = ( - selector: (store: GuestsRoomsStoreState) => T -): T => { - const guestsRoomsContextStore = useContext(GuestsRoomsContext) - - if (!guestsRoomsContextStore) { - throw new Error( - `guestsRoomsContextStore must be used within GuestsRoomsContextProvider` - ) - } - - return useStore(guestsRoomsContextStore, selector) -} diff --git a/stores/sticky-position.ts b/stores/sticky-position.ts index 99272ab62..93328b9e9 100644 --- a/stores/sticky-position.ts +++ b/stores/sticky-position.ts @@ -3,7 +3,6 @@ import { create } from "zustand" export enum StickyElementNameEnum { SITEWIDE_ALERT = "SITEWIDE_ALERT", BOOKING_WIDGET = "BOOKING_WIDGET", - BOOKING_WIDGET_MOBILE = "BOOKING_WIDGET_MOBILE", HOTEL_TAB_NAVIGATION = "HOTEL_TAB_NAVIGATION", HOTEL_STATIC_MAP = "HOTEL_STATIC_MAP", } @@ -32,7 +31,6 @@ interface StickyStore { const priorityMap: Record = { [StickyElementNameEnum.SITEWIDE_ALERT]: 1, [StickyElementNameEnum.BOOKING_WIDGET]: 2, - [StickyElementNameEnum.BOOKING_WIDGET_MOBILE]: 2, [StickyElementNameEnum.HOTEL_TAB_NAVIGATION]: 3, [StickyElementNameEnum.HOTEL_STATIC_MAP]: 3, diff --git a/types/components/bookingWidget/guestsRoomsPicker.ts b/types/components/bookingWidget/guestsRoomsPicker.ts index b59744afc..a075c9f8d 100644 --- a/types/components/bookingWidget/guestsRoomsPicker.ts +++ b/types/components/bookingWidget/guestsRoomsPicker.ts @@ -17,18 +17,19 @@ export type GuestsRoomPickerProps = { index: number } -export type AdultSelectorProps = { - roomIndex: number -} - -export type ChildSelectorProps = { +export type SelectorProps = { roomIndex: number + currentAdults: number + currentChildren: Child[] + childrenInAdultsBed: number } export type ChildInfoSelectorProps = { child: Child + adults: number index: number roomIndex: number + childrenInAdultsBed: number } export interface CounterProps {