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 ( return (
<FormProvider {...methods}> <FormProvider {...methods}>
<section <section ref={bookingWidgetRef} className={styles.containerDesktop}>
ref={bookingWidgetRef} <Form locations={locations} type={type} />
className={styles.container} </section>
data-open={isOpen} <section className={styles.containerMobile} data-open={isOpen}>
>
<button <button
className={styles.close} className={styles.close}
onClick={closeMobileSearch} onClick={closeMobileSearch}

View File

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

View File

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

View File

@@ -3,6 +3,7 @@ import { create } from "zustand"
export enum StickyElementNameEnum { export enum StickyElementNameEnum {
SITEWIDE_ALERT = "SITEWIDE_ALERT", SITEWIDE_ALERT = "SITEWIDE_ALERT",
BOOKING_WIDGET = "BOOKING_WIDGET", BOOKING_WIDGET = "BOOKING_WIDGET",
BOOKING_WIDGET_MOBILE = "BOOKING_WIDGET_MOBILE",
HOTEL_TAB_NAVIGATION = "HOTEL_TAB_NAVIGATION", HOTEL_TAB_NAVIGATION = "HOTEL_TAB_NAVIGATION",
HOTEL_STATIC_MAP = "HOTEL_STATIC_MAP", HOTEL_STATIC_MAP = "HOTEL_STATIC_MAP",
} }
@@ -31,6 +32,7 @@ interface StickyStore {
const priorityMap: Record<StickyElementNameEnum, number> = { const priorityMap: Record<StickyElementNameEnum, number> = {
[StickyElementNameEnum.SITEWIDE_ALERT]: 1, [StickyElementNameEnum.SITEWIDE_ALERT]: 1,
[StickyElementNameEnum.BOOKING_WIDGET]: 2, [StickyElementNameEnum.BOOKING_WIDGET]: 2,
[StickyElementNameEnum.BOOKING_WIDGET_MOBILE]: 2,
[StickyElementNameEnum.HOTEL_TAB_NAVIGATION]: 3, [StickyElementNameEnum.HOTEL_TAB_NAVIGATION]: 3,
[StickyElementNameEnum.HOTEL_STATIC_MAP]: 3, [StickyElementNameEnum.HOTEL_STATIC_MAP]: 3,