feat(SW-344): set active pin on scroll

This commit is contained in:
Pontus Dreij
2024-11-12 09:31:20 +01:00
parent b73421dbde
commit 96a5277881
4 changed files with 51 additions and 11 deletions

View File

@@ -1,22 +1,54 @@
"use client"
import { useEffect, useRef } from "react"
import { useCallback, useEffect, useRef } from "react"
import HotelCardDialog from "../HotelCardDialog"
import { getHotelPins } from "./utils"
import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
interface HotelCardDialogListingProps {
hotels: HotelData[]
activeCard: string | null | undefined
onActiveCardChange: (hotelName: string | null) => void
}
export default function HotelCardDialogListing({
hotels,
activeCard,
}: {
hotels: HotelData[]
activeCard: string | null | undefined
}) {
onActiveCardChange,
}: HotelCardDialogListingProps) {
const hotelsPinData = getHotelPins(hotels)
const activeCardRef = useRef<HTMLDivElement | null>(null)
const handleIntersection = useCallback(
(entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const cardName = entry.target.getAttribute("data-name")
if (cardName) {
onActiveCardChange(cardName)
}
}
})
},
[onActiveCardChange]
)
useEffect(() => {
const observer = new IntersectionObserver(handleIntersection, {
root: null,
threshold: 0.5, // Adjust threshold as needed
})
const elements = document.querySelectorAll("[data-name]")
elements.forEach((el) => observer.observe(el))
return () => {
elements.forEach((el) => observer.unobserve(el))
}
}, [handleIntersection])
useEffect(() => {
if (activeCardRef.current) {
activeCardRef.current.scrollIntoView({
@@ -33,7 +65,11 @@ export default function HotelCardDialogListing({
hotelsPinData.map((data) => {
const isActive = data.name === activeCard
return (
<div key={data.name} ref={isActive ? activeCardRef : null}>
<div
key={data.name}
ref={isActive ? activeCardRef : null}
data-name={data.name}
>
<HotelCardDialog
data={data}
isOpen={!!activeCard}

View File

@@ -11,7 +11,7 @@ import type { HotelListingProps } from "@/types/components/hotelReservation/sele
export default function HotelListing({
hotels,
activeHotelPin,
onHotelCardHover,
setActiveHotelPin,
}: HotelListingProps) {
return (
<>
@@ -20,11 +20,15 @@ export default function HotelListing({
hotelData={hotels}
type={HotelCardListingTypeEnum.MapListing}
activeCard={activeHotelPin}
onHotelCardHover={onHotelCardHover}
onHotelCardHover={setActiveHotelPin}
/>
</div>
<div className={styles.hotelListingMobile} data-open={!!activeHotelPin}>
<HotelCardDialogListing hotels={hotels} activeCard={activeHotelPin} />
<HotelCardDialogListing
hotels={hotels}
activeCard={activeHotelPin}
onActiveCardChange={setActiveHotelPin}
/>
</div>
</>
)

View File

@@ -95,7 +95,7 @@ export default function SelectHotelMap({
<HotelListing
hotels={hotels}
activeHotelPin={activeHotelPin}
onHotelCardHover={setActiveHotelPin}
setActiveHotelPin={setActiveHotelPin}
/>
{showBackToTop && (
<Button

View File

@@ -13,7 +13,7 @@ import type { Coordinates } from "@/types/components/maps/coordinates"
export interface HotelListingProps {
hotels: HotelData[]
activeHotelPin?: string | null
onHotelCardHover?: (hotelName: string | null) => void
setActiveHotelPin: (hotelName: string | null) => void
}
export interface SelectHotelMapProps {