feat(SW-650): fix sticky bug on booking widget mob

This commit is contained in:
Niclas Edenvin
2024-10-23 20:49:08 +02:00
committed by Erik Tiekstra
parent 20e3c9a35f
commit 63dbbac014
4 changed files with 102 additions and 76 deletions

View File

@@ -146,11 +146,10 @@ export default function BookingWidgetClient({
return (
<FormProvider {...methods}>
<section
ref={bookingWidgetRef}
className={styles.container}
data-open={isOpen}
>
<section ref={bookingWidgetRef} className={styles.containerDesktop}>
<Form locations={locations} type={type} />
</section>
<section className={styles.containerMobile} data-open={isOpen}>
<button
className={styles.close}
onClick={closeMobileSearch}

View File

@@ -1,15 +1,17 @@
"use client"
import { useEffect, useState } from "react"
import { useEffect, useMemo, useRef, useState } from "react"
import { useWatch } from "react-hook-form"
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
import { StickyElementNameEnum } from "@/stores/sticky-position"
import { EditIcon, SearchIcon } from "@/components/Icons"
import Divider from "@/components/TempDesignSystem/Divider"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import useLang from "@/hooks/useLang"
import useStickyPosition from "@/hooks/useStickyPosition"
import styles from "./button.module.css"
@@ -29,6 +31,12 @@ 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
@@ -42,74 +50,89 @@ export default function MobileToggleButton({
setHasMounted(true)
}, [])
const locationAndDateIsSet = useMemo(
() => parsedLocation && d,
[parsedLocation, d]
)
if (!hasMounted) {
return null
}
if (parsedLocation && d) {
const totalRooms = rooms.length
const totalAdults = rooms.reduce((acc, room) => {
if (room.adults) {
acc = acc + room.adults
}
return acc
}, 0)
const totalChildren = rooms.reduce((acc, room) => {
if (room.child) {
acc = acc + room.child.length
}
return acc
}, 0)
return (
<div className={styles.complete} onClick={openMobileSearch} role="button">
<div>
<Caption color="red">{parsedLocation.name}</Caption>
<Caption>
{`${selectedFromDate} - ${selectedToDate} (${intl.formatMessage(
{ id: "booking.nights" },
{ totalNights: nights }
)}) ${intl.formatMessage({ id: "booking.adults" }, { totalAdults })}, ${
totalChildren > 0
? intl.formatMessage(
{ id: "booking.children" },
{ totalChildren }
) + ", "
: ""
}${intl.formatMessage({ id: "booking.rooms" }, { totalRooms })}`}
</Caption>
</div>
<div className={styles.icon}>
<EditIcon color="white" />
</div>
</div>
)
}
const totalRooms = rooms.length
const totalAdults = rooms.reduce((acc, room) => {
if (room.adults) {
acc = acc + room.adults
}
return acc
}, 0)
const totalChildren = rooms.reduce((acc, room) => {
if (room.child) {
acc = acc + room.child.length
}
return acc
}, 0)
return (
<div className={styles.partial} onClick={openMobileSearch} role="button">
<div>
<Caption color="red">{intl.formatMessage({ id: "Where to" })}</Caption>
<Body color="uiTextPlaceholder">
{parsedLocation
? parsedLocation.name
: intl.formatMessage({ id: "Destination" })}
</Body>
</div>
<Divider color="baseSurfaceSubtleNormal" variant="vertical" />
<div>
<Caption color="red">
{intl.formatMessage(
{ id: "booking.nights" },
{ totalNights: nights }
)}
</Caption>
<Body>
{selectedFromDate} - {selectedToDate}
</Body>
</div>
<div className={styles.icon}>
<SearchIcon color="white" />
</div>
<div
className={locationAndDateIsSet ? styles.complete : styles.partial}
onClick={openMobileSearch}
role="button"
ref={bookingWidgetMobileRef}
>
{!locationAndDateIsSet && (
<>
<div>
<Caption color="red">
{intl.formatMessage({ id: "Where to" })}
</Caption>
<Body color="uiTextPlaceholder">
{parsedLocation
? parsedLocation.name
: intl.formatMessage({ id: "Destination" })}
</Body>
</div>
<Divider color="baseSurfaceSubtleNormal" variant="vertical" />
<div>
<Caption color="red">
{intl.formatMessage(
{ id: "booking.nights" },
{ totalNights: nights }
)}
</Caption>
<Body>
{selectedFromDate} - {selectedToDate}
</Body>
</div>
<div className={styles.icon}>
<SearchIcon color="white" />
</div>
</>
)}
{locationAndDateIsSet && (
<>
<div>
<Caption color="red">{parsedLocation?.name}</Caption>
<Caption>
{`${selectedFromDate} - ${selectedToDate} (${intl.formatMessage(
{ id: "booking.nights" },
{ totalNights: nights }
)}) ${intl.formatMessage({ id: "booking.adults" }, { totalAdults })}, ${
totalChildren > 0
? intl.formatMessage(
{ id: "booking.children" },
{ totalChildren }
) + ", "
: ""
}${intl.formatMessage({ id: "booking.rooms" }, { totalRooms })}`}
</Caption>
</div>
<div className={styles.icon}>
<EditIcon color="white" />
</div>
</>
)}
</div>
)
}

View File

@@ -1,5 +1,11 @@
.containerDesktop,
.containerMobile,
.close {
display: none;
}
@media screen and (max-width: 767px) {
.container {
.containerMobile {
background-color: var(--UI-Input-Controls-Surface-Normal);
bottom: -100%;
display: grid;
@@ -14,7 +20,7 @@
border-radius: var(--Corner-radius-Large) var(--Corner-radius-Large) 0 0;
}
.container[data-open="true"] {
.containerMobile[data-open="true"] {
bottom: 0;
}
@@ -25,7 +31,7 @@
justify-self: flex-end;
}
.container[data-open="true"] + .backdrop {
.containerMobile[data-open="true"] + .backdrop {
background-color: rgba(0, 0, 0, 0.4);
height: 100%;
left: 0;
@@ -37,7 +43,7 @@
}
@media screen and (min-width: 768px) {
.container {
.containerDesktop {
display: block;
box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05);
position: sticky;
@@ -45,10 +51,6 @@
z-index: 10;
background-color: var(--Base-Surface-Primary-light-Normal);
}
.close {
display: none;
}
}
@media screen and (min-width: 1367px) {

View File

@@ -3,6 +3,7 @@ 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",
}
@@ -31,6 +32,7 @@ interface StickyStore {
const priorityMap: Record<StickyElementNameEnum, number> = {
[StickyElementNameEnum.SITEWIDE_ALERT]: 1,
[StickyElementNameEnum.BOOKING_WIDGET]: 2,
[StickyElementNameEnum.BOOKING_WIDGET_MOBILE]: 2,
[StickyElementNameEnum.HOTEL_TAB_NAVIGATION]: 3,
[StickyElementNameEnum.HOTEL_STATIC_MAP]: 3,