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" "use client"
import { useEffect, useRef } from "react" import { useCallback, useEffect, useRef } from "react"
import HotelCardDialog from "../HotelCardDialog" import HotelCardDialog from "../HotelCardDialog"
import { getHotelPins } from "./utils" import { getHotelPins } from "./utils"
import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps" 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({ export default function HotelCardDialogListing({
hotels, hotels,
activeCard, activeCard,
}: { onActiveCardChange,
hotels: HotelData[] }: HotelCardDialogListingProps) {
activeCard: string | null | undefined
}) {
const hotelsPinData = getHotelPins(hotels) const hotelsPinData = getHotelPins(hotels)
const activeCardRef = useRef<HTMLDivElement | null>(null) 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(() => { useEffect(() => {
if (activeCardRef.current) { if (activeCardRef.current) {
activeCardRef.current.scrollIntoView({ activeCardRef.current.scrollIntoView({
@@ -33,7 +65,11 @@ export default function HotelCardDialogListing({
hotelsPinData.map((data) => { hotelsPinData.map((data) => {
const isActive = data.name === activeCard const isActive = data.name === activeCard
return ( return (
<div key={data.name} ref={isActive ? activeCardRef : null}> <div
key={data.name}
ref={isActive ? activeCardRef : null}
data-name={data.name}
>
<HotelCardDialog <HotelCardDialog
data={data} data={data}
isOpen={!!activeCard} isOpen={!!activeCard}

View File

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

View File

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

View File

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