diff --git a/apps/scandic-web/components/Carousel/CarouselContent.tsx b/apps/scandic-web/components/Carousel/CarouselContent.tsx index 2fff8c089..f54cedeed 100644 --- a/apps/scandic-web/components/Carousel/CarouselContent.tsx +++ b/apps/scandic-web/components/Carousel/CarouselContent.tsx @@ -1,6 +1,7 @@ "use client" import { cx } from "class-variance-authority" +import { useEffect, useState } from "react" import { useCarousel } from "./CarouselContext" @@ -11,11 +12,21 @@ export function CarouselContent({ children, ...props }: React.HTMLAttributes) { - const { carouselRef } = useCarousel() + const { carouselRef, canScrollNext, canScrollPrev } = useCarousel() + const [isOneItem, setIsOneItem] = useState(false) + + useEffect(() => { + setIsOneItem(!canScrollPrev() && !canScrollNext()) + }, [canScrollPrev, canScrollNext]) return (
-
+
{children}
diff --git a/apps/scandic-web/components/Carousel/carousel.module.css b/apps/scandic-web/components/Carousel/carousel.module.css index ef10b75a9..e902f3846 100644 --- a/apps/scandic-web/components/Carousel/carousel.module.css +++ b/apps/scandic-web/components/Carousel/carousel.module.css @@ -13,6 +13,10 @@ gap: var(--Spacing-x2); } +.centerContent { + justify-content: center; +} + .item { min-width: 0; } diff --git a/apps/scandic-web/components/Carousel/index.tsx b/apps/scandic-web/components/Carousel/index.tsx index 6d6c30254..20d859a9e 100644 --- a/apps/scandic-web/components/Carousel/index.tsx +++ b/apps/scandic-web/components/Carousel/index.tsx @@ -20,17 +20,19 @@ function Carousel({ plugins, className, children, + scrollToIdx = 0, + align = "start", }: CarouselProps) { const [carouselRef, api] = useEmblaCarousel( { containScroll: "trimSnaps", - align: "start", + align, axis: "x", ...opts, }, plugins ) - const [selectedIndex, setSelectedIndex] = useState(0) + const [selectedIndex, setSelectedIndex] = useState(scrollToIdx) const onSelect = useCallback((api: CarouselApi) => { if (!api) return @@ -62,7 +64,6 @@ function Carousel({ useEffect(() => { if (!api) return - onSelect(api) api.on("reInit", onSelect) api.on("select", onSelect) @@ -72,6 +73,11 @@ function Carousel({ } }, [api, onSelect]) + useEffect(() => { + if (!api || scrollToIdx === -1) return + api.scrollTo(scrollToIdx) + }, [api, scrollToIdx]) + return ( void className?: string + handleScrollSelected?: (idx: number) => void + scrollToIdx?: number + align?: "start" | "center" } export interface CarouselContextProps extends Omit { diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/hotelList.module.css b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/hotelList.module.css index bac560db2..6bb8fe838 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/hotelList.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/hotelList.module.css @@ -18,12 +18,7 @@ } @media screen and (max-width: 949px) { - .hotelList { - flex-direction: row; - align-items: end; - overflow-x: scroll; - } - + .hotelList, .header { display: none; } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/index.tsx index 907fa75a9..313500ad2 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/index.tsx @@ -11,6 +11,7 @@ import Alert from "@/components/TempDesignSystem/Alert" import Body from "@/components/TempDesignSystem/Text/Body" import { debounce } from "@/utils/debounce" +import HotelCardCarousel from "../../../HotelCardCarousel" import HotelListItem from "../HotelListItem" import HotelListSkeleton from "./HotelListSkeleton" import { getVisibleHotels } from "./utils" @@ -75,13 +76,16 @@ export default function HotelList() { })} /> ) : ( -
    - {visibleHotels.map(({ hotel, url }) => ( -
  • - -
  • - ))} -
+ <> + +
    + {visibleHotels.map(({ hotel, url }) => ( +
  • + +
  • + ))} +
+ )}
) diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/hotelCardCarousel.module.css b/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/hotelCardCarousel.module.css new file mode 100644 index 000000000..8dbc57a58 --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/hotelCardCarousel.module.css @@ -0,0 +1,28 @@ +.noActiveHotel, +.carousel { + display: none; +} + +@media screen and (max-width: 949px) { + .carousel:not(.noActiveHotel) { + display: grid; + } + + .carouselContent { + gap: var(--Spacing-x1); + } +} + +.carouselContent .item:first-child:not(:only-child) { + padding-left: var(--Spacing-x2); +} + +.carouselContent .item:last-child:not(:only-child) { + padding-right: var(--Spacing-x2); +} + +@media screen and (max-width: 500px) { + .carouselContent { + grid-auto-columns: 90%; + } +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/index.tsx new file mode 100644 index 000000000..89eb9da49 --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/index.tsx @@ -0,0 +1,61 @@ +"use client" + +import { cx } from "class-variance-authority" + +import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" + +import { Carousel } from "@/components/Carousel" + +import HotelMapCard from "../HotelMapCard" + +import styles from "./hotelCardCarousel.module.css" + +import type { Hotel, HotelDataWithUrl } from "@/types/hotel" + +interface MapCardCarouselProps { + visibleHotels: HotelDataWithUrl[] | [] +} +export default function HotelCardCarousel({ + visibleHotels, +}: MapCardCarouselProps) { + const { clickedHotel } = useDestinationPageHotelsMapStore() + + const selectedHotelIdx = visibleHotels.findIndex( + (hotel) => hotel.hotel.operaId === clickedHotel + ) + + return ( + + + {visibleHotels.map(({ hotel, url }) => ( + + + + ))} + + + ) +} + +function getImage(hotel: Hotel) { + return { + src: hotel.galleryImages[0].imageSizes.medium, + alt: + hotel.galleryImages[0].metaData.altText || + hotel.galleryImages[0].metaData.altText_En, + } +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/dialogImage.module.css b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/dialogImage.module.css index 37495a049..861b56acd 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/dialogImage.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/dialogImage.module.css @@ -2,7 +2,8 @@ height: 100%; width: 100%; background-color: #fff; - background-image: linear-gradient(45deg, #000000 25%, transparent 25%), + background-image: + linear-gradient(45deg, #000000 25%, transparent 25%), linear-gradient(-45deg, #000000 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #000000 75%), linear-gradient(-45deg, transparent 75%, #000000 75%); @@ -31,3 +32,9 @@ top: 7px; border-radius: var(--Corner-radius-Small); } + +@media screen and (max-width: 500px) { + .imageContainer { + min-width: 120px; + } +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/hotelMapCard.module.css b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/hotelMapCard.module.css index b64d2e97a..9b8327249 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/hotelMapCard.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/hotelMapCard.module.css @@ -1,23 +1,22 @@ .dialog { - bottom: 0; - left: 50%; - transform: translateX(-50%); - border: none; - background: transparent; + display: none; } .dialogContent { + background: var(--Base-Surface-Primary-light-Normal); border: 1px solid var(--Base-Border-Subtle); border-radius: var(--Corner-radius-Medium); - min-width: 402px; - background: var(--Base-Surface-Primary-light-Normal); box-shadow: 0px 0px 8px 3px rgba(0, 0, 0, 0.1); flex-direction: row; display: flex; position: relative; } -.dialogContent::after { +.dialog .dialogContent { + min-width: 402px; +} + +.dialog .dialogContent::after { content: ""; display: block; position: absolute; @@ -55,7 +54,7 @@ .content { width: 100%; - min-width: 220px; + min-width: 150px; padding: var(--Spacing-x-one-and-half); display: flex; flex-direction: column; @@ -83,8 +82,21 @@ padding-bottom: var(--Spacing-x1); } -@media (min-width: 768px) { +@media (min-width: 950px) { .iconFootnote { display: block; } + + .dialog { + bottom: 0; + left: 50%; + transform: translateX(-50%); + border: none; + background: transparent; + display: block; + } + + .content { + min-width: 220px; + } } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx index f59628bda..1bea77f8e 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/index.tsx @@ -1,8 +1,11 @@ "use client" +import { cx } from "class-variance-authority" import Link from "next/link" -import { useState } from "react" +import { useCallback, useState } from "react" import { useIntl } from "react-intl" +import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" + import CloseLargeIcon from "@/components/Icons/CloseLarge" import Button from "@/components/TempDesignSystem/Button" import Body from "@/components/TempDesignSystem/Text/Body" @@ -18,37 +21,60 @@ import type { GalleryImage } from "@/types/components/imageGallery" import type { Amenities } from "@/types/hotel" interface HotelMapCardProps { - isActive: boolean + isActive?: boolean amenities: Amenities tripadvisorRating: number | undefined hotelName: string image: GalleryImage | null url: string - onClose: () => void + type?: "dialog" | "article" + className?: string } export default function HotelMapCard({ - isActive, + isActive = false, amenities, tripadvisorRating, hotelName, image, url, - onClose, + type = "dialog", + className, }: HotelMapCardProps) { const intl = useIntl() const pageType = usePageType() const [imageError, setImageError] = useState(false) + const { setClickedHotel } = useDestinationPageHotelsMapStore() + + const handleClose = useCallback(() => { + setClickedHotel(null) + }, [setClickedHotel]) + + function Wrapper({ children }: React.PropsWithChildren) { + if (type === "dialog") { + return ( + + {children} + + ) + } + return
{children}
+ } return ( - +
{url && ( -
+ ) } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/clusterMarker.module.css b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/clusterMarker.module.css index c526784ea..3858dfd0f 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/clusterMarker.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/clusterMarker.module.css @@ -18,6 +18,8 @@ background: linear-gradient(rgba(31, 28, 27, 0.3), rgba(31, 28, 27, 0.3)), var(--Surface-Brand-Primary-2-Default); + width: 46px !important; + height: 46px !important; } .count { diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/index.tsx index 415fd8260..00b847563 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/index.tsx @@ -27,10 +27,10 @@ export default function ClusterMarker({ onMarkerClick, hotelIds, }: ClusterMarkerProps) { - const { hoveredHotel } = useDestinationPageHotelsMapStore() - const isActive = hoveredHotel - ? hotelIds.includes(Number(hoveredHotel)) - : false + const { hoveredHotel, clickedHotel } = useDestinationPageHotelsMapStore() + const isActive = + hotelIds.includes(Number(hoveredHotel)) || + hotelIds.includes(Number(clickedHotel)) const handleClick = useCallback(() => { if (onMarkerClick) { diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx index dfe5e5b37..4b974a640 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx @@ -32,10 +32,6 @@ export default function Marker({ position, properties }: MarkerProps) { trackMapClick(properties.name) }, [setClickedHotel, properties]) - function handleCloseCard() { - setClickedHotel(null) - } - const handleMouseEnter = useCallback(() => { setHoveredHotel(properties.id) }, [setHoveredHotel, properties.id]) @@ -70,7 +66,6 @@ export default function Marker({ position, properties }: MarkerProps) { hotelName={properties.name} image={properties.image} url={properties.url} - onClose={handleCloseCard} /> ) diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css b/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css index fadac49c7..78e26a3c2 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css @@ -53,7 +53,7 @@ .sidebar { position: absolute; max-width: none; - padding: 0 var(--Spacing-x2) var(--Spacing-x3); + padding: 0 0 var(--Spacing-x2) 0; overflow: hidden; bottom: 0; z-index: 3;