diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx index c611404b6..3b0980346 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx +++ b/apps/scandic-web/app/[lang]/(live)/(public)/(contentTypes)/destination_country_page/[uid]/page.tsx @@ -5,18 +5,18 @@ import DestinationCountryPageSkeleton from "@/components/ContentType/Destination import styles from "./page.module.css" +import type { PageArgs } from "@/types/params" + export { generateMetadata } from "@/utils/metadata/generateMetadata" -export default async function DestinationCountryPagePage() { - // props: PageArgs<{}, { view?: "map"; }> - // const searchParams = await props.searchParams +export default async function DestinationCountryPagePage( + props: PageArgs +) { + const searchParams = await props.searchParams return (
}> - +
) diff --git a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/cityListing.module.css b/apps/scandic-web/components/ContentType/DestinationPage/CityListing/cityListing.module.css deleted file mode 100644 index b5f62647a..000000000 --- a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/cityListing.module.css +++ /dev/null @@ -1,27 +0,0 @@ -.container { - --scroll-margin-top: calc( - var(--booking-widget-mobile-height) + var(--Spacing-x2) - ); - display: grid; - gap: var(--Spacing-x2); - scroll-margin-top: var(--scroll-margin-top); -} - -.listHeader { - display: flex; - justify-content: space-between; -} - -.cityList { - list-style: none; - display: grid; - gap: var(--Spacing-x2); -} - -@media screen and (min-width: 768px) { - .container { - --scroll-margin-top: calc( - var(--booking-widget-desktop-height) + var(--Spacing-x2) - ); - } -} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCardCarousel/CityCardCarousel.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCardCarousel/CityCardCarousel.tsx new file mode 100644 index 000000000..f01d126ee --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCardCarousel/CityCardCarousel.tsx @@ -0,0 +1,82 @@ +"use client" + +import { cx } from "class-variance-authority" +import { useCallback } from "react" + +import { useDestinationPageCitiesMapStore } from "@/stores/destination-page-cities-map" + +import { Carousel } from "@/components/Carousel" + +import CityMapCard from "../DestinationCountryPage/CityMapCard" + +import styles from "./destinationCardCarousel.module.css" + +import type { DestinationCityListItem } from "@scandic-hotels/trpc/types/destinationCityPage" + +interface CityCardCarouselProps { + activeCities: DestinationCityListItem[] +} +export default function CityCardCarousel({ + activeCities, +}: CityCardCarouselProps) { + const { activeCityMarker, setActiveCityMarker } = + useDestinationPageCitiesMapStore() + + const selectedCityIdx = activeCities.findIndex( + (city) => city.cityIdentifier === activeCityMarker?.cityId + ) + + const handleScrollSelect = useCallback( + (idx: number) => { + if ( + selectedCityIdx !== -1 && + activeCities[idx]?.destination_settings.location + ) { + setActiveCityMarker({ + cityId: activeCities[idx].cityIdentifier, + location: { + lat: activeCities[idx].destination_settings.location.latitude, + lng: activeCities[idx].destination_settings.location.longitude, + }, + }) + } + }, + [setActiveCityMarker, activeCities, selectedCityIdx] + ) + + return ( + + + {activeCities.map(({ cityIdentifier, cityName, url, images }) => ( + + + + ))} + + + ) +} + +function getImage(images: DestinationCityListItem["images"]) { + if (images?.length) { + const image = images[0] + return { + src: image.url, + alt: image.meta.alt || image.meta.caption || "", + } + } + return null +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCardCarousel/HotelCardCarousel.tsx similarity index 86% rename from apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/index.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationCardCarousel/HotelCardCarousel.tsx index d59e4bd30..c8bb5f102 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelCardCarousel/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCardCarousel/HotelCardCarousel.tsx @@ -9,16 +9,16 @@ import { Carousel } from "@/components/Carousel" import HotelMapCard from "../HotelMapCard" -import styles from "./hotelCardCarousel.module.css" +import styles from "./destinationCardCarousel.module.css" import type { HotelListingHotelData } from "@scandic-hotels/trpc/types/hotel" -interface MapCardCarouselProps { +interface HotelCardCarouselProps { visibleHotels: HotelListingHotelData[] } export default function HotelCardCarousel({ visibleHotels, -}: MapCardCarouselProps) { +}: HotelCardCarouselProps) { const { activeMarker, setActiveMarker } = useDestinationPageHotelsMapStore() const selectedHotelIdx = visibleHotels.findIndex( @@ -36,18 +36,18 @@ export default function HotelCardCarousel({ return ( {visibleHotels.map(({ hotel, url }) => ( - + + + {intl.formatMessage({ defaultMessage: "Back to cities" })} + + ) +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/Content.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/Content.tsx index 5fc9266fc..eb2d0faa4 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/Content.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelList/Content.tsx @@ -1,12 +1,9 @@ -"use client" - import { useIntl } from "react-intl" -import { useMediaQuery } from "usehooks-ts" import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert" import { Alert } from "@scandic-hotels/design-system/Alert" -import HotelCardCarousel from "../../../HotelCardCarousel" +import HotelCardCarousel from "../../../DestinationCardCarousel/HotelCardCarousel" import HotelListItem from "../HotelListItem" import styles from "./hotelList.module.css" @@ -23,7 +20,6 @@ export default function HotelListContent({ visibleHotels, }: HotelListContentProps) { const intl = useIntl() - const isMobile = useMediaQuery("(max-width: 949px)") if (hotelsCount === 0) { return ( @@ -40,17 +36,17 @@ export default function HotelListContent({ ) } - if (isMobile) { - return - } - return ( -
    - {visibleHotels.map(({ hotel, url }) => ( -
  • - -
  • - ))} -
+ <> + + +
    + {visibleHotels.map(({ hotel, url }) => ( +
  • + +
  • + ))} +
+ ) } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx index 9a6c4ea1d..8ee2ce1ee 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/HotelListItem/index.tsx @@ -96,7 +96,7 @@ export default function HotelListItem({ hotel, url }: HotelListItemProps) {

{hotel.name}

-

+ -

+
diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx index 7efddd9a0..cf71c7c83 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/CityMap/index.tsx @@ -1,12 +1,15 @@ "use client" +import { useParams } from "next/navigation" +import { useEffect, useState } from "react" import { useIntl } from "react-intl" import { Typography } from "@scandic-hotels/design-system/Typography" import { useDestinationDataStore } from "@/stores/destination-data" -import Map from "../../Map" -import { getHeadingText } from "../../utils" +import CityMapContainer from "../../Map/CityMapContainer" +import { getCityHeadingText } from "../../utils" +import { BackToCities } from "./BackToCitiesLink" import HotelList from "./HotelList" import styles from "./cityMap.module.css" @@ -36,21 +39,30 @@ export default function CityMap({ filterFromUrl: state.filterFromUrl, }) ) + const [fromCountryPage, setIsFromCountryPage] = useState(false) + const params = useParams() + + useEffect(() => { + const url = new URL(window.location.href) + setIsFromCountryPage(url.searchParams.has("fromCountry")) + }, [params]) return ( - - -

- {getHeadingText(intl, city.name, allFilters, filterFromUrl)} -

-
+ + {fromCountryPage ? : null} + +

+ {getCityHeadingText(intl, city.name, allFilters, filterFromUrl)} +

+
+
-
+ ) } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/DestinationCityPageSkeleton.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/DestinationCityPageSkeleton.tsx index 811b9d60c..ca2a9890b 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/DestinationCityPageSkeleton.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/DestinationCityPageSkeleton.tsx @@ -4,8 +4,8 @@ import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" +import HotelListingSkeleton from "../DestinationListing/HotelListing/HotelListingSkeleton" import ExperienceListSkeleton from "../ExperienceList/ExperienceListSkeleton" -import HotelListingSkeleton from "../HotelListing/HotelListingSkeleton" import SidebarContentWrapperSkeleton from "../SidebarContentWrapper/SidebarContentWrapperSkeleton" import TopImagesSkeleton from "../TopImages/TopImagesSkeleton" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx index 6fbc7d79f..e97e046e8 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx @@ -22,8 +22,8 @@ import DestinationDataProvider from "@/providers/DestinationDataProvider" import { getPathname } from "@/utils/getPathname" import Blocks from "../Blocks" +import HotelListing from "../DestinationListing/HotelListing" import ExperienceList from "../ExperienceList" -import HotelListing from "../HotelListing" import SidebarContentWrapper from "../SidebarContentWrapper" import DestinationPageSidePeek from "../Sidepeek" import StaticMap from "../StaticMap" @@ -121,7 +121,11 @@ export default async function DestinationCityPage({ diff --git a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/CityListingItemSkeleton.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/CityListingItemSkeleton.tsx similarity index 92% rename from apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/CityListingItemSkeleton.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/CityListingItemSkeleton.tsx index 03f00b920..328ee3877 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/CityListingItemSkeleton.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/CityListingItemSkeleton.tsx @@ -3,7 +3,7 @@ import { Divider } from "@scandic-hotels/design-system/Divider" import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" -import ExperienceListSkeleton from "../../ExperienceList/ExperienceListSkeleton" +import ExperienceListSkeleton from "../../../ExperienceList/ExperienceListSkeleton" import styles from "./cityListingItem.module.css" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/cityListingItem.module.css b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/cityListingItem.module.css similarity index 89% rename from apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/cityListingItem.module.css rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/cityListingItem.module.css index 8861d1c56..d51e16d60 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/cityListingItem.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/cityListingItem.module.css @@ -17,8 +17,8 @@ .content { display: grid; - gap: var(--Spacing-x2); - padding: var(--Spacing-x2) var(--Spacing-x3); + gap: var(--Space-x2); + padding: var(--Space-x2) var(--Space-x3); } @media screen and (min-width: 768px) { diff --git a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/index.tsx similarity index 97% rename from apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/index.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/index.tsx index 3427afb25..0b2ab0c10 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingItem/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingItem/index.tsx @@ -11,7 +11,7 @@ import Subtitle from "@scandic-hotels/design-system/Subtitle" import { mapImageVaultImagesToGalleryImages } from "@/utils/imageGallery" -import ExperienceList from "../../ExperienceList" +import ExperienceList from "../../../ExperienceList" import styles from "./cityListingItem.module.css" diff --git a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingSkeleton.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingSkeleton.tsx similarity index 92% rename from apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingSkeleton.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingSkeleton.tsx index ace259d14..11e5670e5 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/CityListingSkeleton.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/CityListingSkeleton.tsx @@ -4,7 +4,7 @@ import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" import CityListingItemSkeleton from "./CityListingItem/CityListingItemSkeleton" -import styles from "./cityListing.module.css" +import styles from "../destinationListing.module.css" export default function CityListingSkeleton() { return ( diff --git a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/index.tsx similarity index 87% rename from apps/scandic-web/components/ContentType/DestinationPage/CityListing/index.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/index.tsx index b9c8d9f60..91bac17c2 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/CityListing/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/CityListing/index.tsx @@ -4,6 +4,7 @@ import { useRef } from "react" import { useIntl } from "react-intl" import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert" +import useSetMapView from "@scandic-hotels/common/hooks/map/useSetMapView" import { useScrollToTop } from "@scandic-hotels/common/hooks/useScrollToTop" import { Alert } from "@scandic-hotels/design-system/Alert" import { BackToTopButton } from "@scandic-hotels/design-system/BackToTopButton" @@ -11,16 +12,16 @@ import { Typography } from "@scandic-hotels/design-system/Typography" import { useDestinationDataStore } from "@/stores/destination-data" -import DestinationFilterAndSort from "@/components/DestinationFilterAndSort" - +import { SeeOnMapFilterWrapper } from "../../SeeOnMapFilterWrapper" import CityListingItem from "./CityListingItem" import CityListingSkeleton from "./CityListingSkeleton" -import styles from "./cityListing.module.css" +import styles from "../destinationListing.module.css" export default function CityListing() { const intl = useIntl() const scrollRef = useRef(null) + const mapUrl = useSetMapView() const { showBackToTop, scrollToTop } = useScrollToTop({ threshold: 300, elementRef: scrollRef, @@ -46,7 +47,7 @@ export default function CityListing() { )}
- + {activeCities.length === 0 ? ( ) : ( <> -
    +
      {activeCities.map((city) => (
    • diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/HotelListingItemSkeleton.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingItem/HotelListingItemSkeleton.tsx similarity index 100% rename from apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/HotelListingItemSkeleton.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingItem/HotelListingItemSkeleton.tsx diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/hotelListingItem.module.css b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingItem/hotelListingItem.module.css similarity index 100% rename from apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/hotelListingItem.module.css rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingItem/hotelListingItem.module.css diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingItem/index.tsx similarity index 94% rename from apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/index.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingItem/index.tsx index 2ff686998..c2626ea58 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingItem/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingItem/index.tsx @@ -1,10 +1,9 @@ "use client" import NextLink from "next/link" -import { useParams } from "next/navigation" -import { useEffect, useState } from "react" import { useIntl } from "react-intl" +import useSetMapView from "@scandic-hotels/common/hooks/map/useSetMapView" import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting" import ButtonLink from "@scandic-hotels/design-system/ButtonLink" import { Divider } from "@scandic-hotels/design-system/Divider" @@ -33,20 +32,12 @@ export default function HotelListingItem({ url, }: HotelListingItemProps) { const intl = useIntl() - const params = useParams() const { setActiveMarker } = useDestinationPageHotelsMapStore() const galleryImages = mapApiImagesToGalleryImages(hotel.galleryImages || []) const amenities = hotel.detailedFacilities.slice(0, 5) - const [mapUrl, setMapUrl] = useState(null) - + const mapUrl = useSetMapView() const address = `${hotel.address.streetAddress}, ${hotel.address.city}` - useEffect(() => { - const url = new URL(window.location.href) - url.searchParams.set("view", "map") - setMapUrl(url.toString()) - }, [params, hotel.name]) - return (
      diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingSkeleton.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingSkeleton.tsx similarity index 92% rename from apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingSkeleton.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingSkeleton.tsx index ecb03a3d6..327c4fba6 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/HotelListingSkeleton.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/HotelListingSkeleton.tsx @@ -4,7 +4,7 @@ import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer" import HotelListingItemSkeleton from "./HotelListingItem/HotelListingItemSkeleton" -import styles from "./hotelListing.module.css" +import styles from "../destinationListing.module.css" export default function HotelListingSkeleton() { return ( diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/index.tsx similarity index 64% rename from apps/scandic-web/components/ContentType/DestinationPage/HotelListing/index.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/index.tsx index daf4e8430..4a57b005c 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/HotelListing/index.tsx @@ -1,32 +1,27 @@ "use client" -import Link from "next/link" -import { useParams } from "next/navigation" -import { useEffect, useRef, useState } from "react" +import { useRef } from "react" import { useIntl } from "react-intl" import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert" +import useSetMapView from "@scandic-hotels/common/hooks/map/useSetMapView" import { useScrollToTop } from "@scandic-hotels/common/hooks/useScrollToTop" import { Alert } from "@scandic-hotels/design-system/Alert" import { BackToTopButton } from "@scandic-hotels/design-system/BackToTopButton" -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton" import { Typography } from "@scandic-hotels/design-system/Typography" import { useDestinationDataStore } from "@/stores/destination-data" -import DestinationFilterAndSort from "@/components/DestinationFilterAndSort" - +import { SeeOnMapFilterWrapper } from "../../SeeOnMapFilterWrapper" import HotelListingItem from "./HotelListingItem" import HotelListingSkeleton from "./HotelListingSkeleton" -import styles from "./hotelListing.module.css" +import styles from "../destinationListing.module.css" export default function HotelListing() { const intl = useIntl() const scrollRef = useRef(null) - const params = useParams() - const [mapUrl, setMapUrl] = useState(null) + const mapUrl = useSetMapView() const { showBackToTop, scrollToTop } = useScrollToTop({ threshold: 300, elementRef: scrollRef, @@ -36,12 +31,6 @@ export default function HotelListing() { isLoading: state.isLoading, })) - useEffect(() => { - const url = new URL(window.location.href) - url.searchParams.set("view", "map") - setMapUrl(url.toString()) - }, [params]) - return isLoading ? ( ) : ( @@ -58,26 +47,7 @@ export default function HotelListing() { )} -
      - {mapUrl && ( - - )} - -
      +
      {activeHotels.length === 0 ? ( ) : ( <> -
        +
          {activeHotels.map(({ hotel, url }) => (
        • diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/hotelListing.module.css b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/destinationListing.module.css similarity index 57% rename from apps/scandic-web/components/ContentType/DestinationPage/HotelListing/hotelListing.module.css rename to apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/destinationListing.module.css index 65003aaeb..68cff03db 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelListing/hotelListing.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationListing/destinationListing.module.css @@ -1,10 +1,10 @@ .container { --scroll-margin-top: calc( - var(--booking-widget-mobile-height) + var(--Spacing-x2) + var(--booking-widget-mobile-height) + var(--Space-x2) ); - position: relative; display: grid; - gap: var(--Spacing-x2); + position: relative; + gap: var(--Space-x4); scroll-margin-top: var(--scroll-margin-top); } @@ -13,16 +13,10 @@ gap: var(--Space-x2); } -.cta { - display: flex; - justify-content: space-between; - gap: var(--Spacing-x2); -} - -.hotelList { +.list { list-style: none; display: grid; - gap: var(--Spacing-x2); + gap: var(--Space-x2); } @media screen and (min-width: 768px) { @@ -33,13 +27,14 @@ } } -@media screen and (min-width: 1367px) { +@media screen and (min-width: 950px) { .listHeader { display: flex; justify-content: space-between; + align-items: center; } - .mapButton { - display: none !important; /* Important to override button higher specificy */ + .container { + gap: var(--Space-x1); } } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx index 2828a02ea..4d3d3e0f0 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx @@ -29,7 +29,7 @@ export default async function OverviewMapContainer() { boundsPadding={0} gestureHandling="cooperative" > - + 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 7ee18c5bb..23f768e44 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 @@ -1,20 +1,3 @@ -.imagePlaceholder { - height: 100%; - width: 100%; - background-color: #fff; - 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%); - background-size: 120px 120px; - background-position: - 0 0, - 0 60px, - 60px -60px, - -60px 0; -} - .imageContainer { position: relative; min-width: 177px; diff --git a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/index.tsx index 0e5fbe937..97dc0ce62 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/HotelMapCard/DialogImage/index.tsx @@ -1,6 +1,7 @@ import Chip from "@scandic-hotels/design-system/Chip" import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon" import Image from "@scandic-hotels/design-system/Image" +import ImageFallback from "@scandic-hotels/design-system/ImageFallback" import { Typography } from "@scandic-hotels/design-system/Typography" import styles from "./dialogImage.module.css" @@ -22,7 +23,7 @@ export default function DialogImage({ return (
          {!image || imageError ? ( -
          + ) : ( ) { + const { activeMarker: activeHotelId, setActiveMarker } = + useDestinationPageHotelsMapStore() + + const activeHotel = hotels.find(({ hotel }) => hotel.id === activeHotelId) + const markers = getHotelMapMarkers(hotels) + const geoJson = mapMarkerDataToGeoJson(markers) + + return ( + + {children} + + ) +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/CountryMapContainer.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/CountryMapContainer.tsx new file mode 100644 index 000000000..fc3823a4d --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/CountryMapContainer.tsx @@ -0,0 +1,52 @@ +"use client" + +import { type PropsWithChildren } from "react" + +import { useDestinationPageCitiesMapStore } from "@/stores/destination-page-cities-map" + +import { getCityMapMarkers, mapCityMarkerDataToGeoJson } from "./utils" +import Map from "." + +import type { DestinationCityListItem } from "@scandic-hotels/trpc/types/destinationCityPage" + +import type { MapLocation } from "@/types/components/mapLocation" + +interface MapProps { + cities: DestinationCityListItem[] + mapId: string + apiKey: string + defaultLocation: MapLocation +} + +export default function CountryMapContainer({ + cities, + mapId, + apiKey, + defaultLocation, + children, +}: PropsWithChildren) { + const { activeCityMarker, setActiveCityMarker } = + useDestinationPageCitiesMapStore() + + const activeCity = cities.find( + (city) => city.cityIdentifier === activeCityMarker?.cityId + ) + + const markers = getCityMapMarkers(cities) + const geoJson = mapCityMarkerDataToGeoJson(markers) + + return ( + + {children} + + ) +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/dynamicMap.module.css b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/dynamicMap.module.css index c3b70b434..ddcf93f2b 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/dynamicMap.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/dynamicMap.module.css @@ -6,7 +6,7 @@ z-index: 0; } -.mapWrapperWithCloseButton:after { +.mapWrapperWithSeeAsListButton:after { content: ""; position: absolute; top: 0; @@ -23,39 +23,35 @@ .ctaButtons { position: absolute; - top: var(--Spacing-x2); - right: var(--Spacing-x2); + top: var(--Space-x2); + right: var(--Space-x2); z-index: 1; display: flex; flex-direction: column; - gap: var(--Spacing-x7); + gap: var(--Space-x7); align-items: flex-end; pointer-events: none; } .zoomButtons { display: grid; - gap: var(--Spacing-x1); + gap: var(--Space-x1); margin-top: auto; } -.closeButton { +.seeAsListButton { display: none !important; } .zoomButton { - width: var(--Spacing-x5); - height: var(--Spacing-x5); - padding: 0; pointer-events: initial; - box-shadow: var(--button-box-shadow); } @media screen and (min-width: 950px) { .ctaButtons { - top: var(--Spacing-x4); - right: var(--Spacing-x4); - bottom: var(--Spacing-x4); + top: var(--Space-x4); + right: var(--Space-x4); + bottom: var(--Space-x4); justify-content: space-between; } @@ -64,11 +60,10 @@ flex-direction: row-reverse; } - .closeButton { + .seeAsListButton { display: flex !important; pointer-events: initial; box-shadow: var(--button-box-shadow); - gap: var(--Spacing-x-half); } /* Overriding Google maps infoWindow styles */ diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx index d09eb3c27..3055e56a1 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/DynamicMap/index.tsx @@ -7,9 +7,14 @@ import { cx } from "class-variance-authority" import { type PropsWithChildren, useEffect, useRef, useState } from "react" import { useIntl } from "react-intl" +import { useZoomControls } from "@scandic-hotels/common/hooks/map/useZoomControls" +import { Button } from "@scandic-hotels/design-system/Button" +import { IconButton } from "@scandic-hotels/design-system/IconButton" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { MAP_RESTRICTIONS } from "@scandic-hotels/design-system/Map/mapConstants" -import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton" +import { + DESTINATION_PAGE, + MAP_RESTRICTIONS, +} from "@scandic-hotels/design-system/Map/mapConstants" import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" @@ -20,7 +25,10 @@ import { usePageType } from "../PageTypeProvider" import styles from "./dynamicMap.module.css" -import type { DestinationMarker } from "@/types/components/maps/destinationMarkers" +import type { + CityMarker, + DestinationMarker, +} from "@/types/components/maps/destinationMarkers" const BACKUP_COORDINATES = { lat: 59.3293, @@ -28,7 +36,7 @@ const BACKUP_COORDINATES = { } interface DynamicMapProps { - markers: DestinationMarker[] + markers: DestinationMarker[] | CityMarker[] mapId: string defaultCenter?: google.maps.LatLngLiteral defaultZoom?: number @@ -42,7 +50,7 @@ export default function DynamicMap({ markers, mapId, defaultCenter = BACKUP_COORDINATES, - defaultZoom = 3, + defaultZoom = DESTINATION_PAGE.DEFAULT_ZOOM, fitBounds = true, boundsPadding = 100, onClose, @@ -55,6 +63,8 @@ export default function DynamicMap({ const { activeMarker } = useDestinationPageHotelsMapStore() const ref = useRef(null) const [hasFittedBounds, setHasFittedBounds] = useState(!!activeMarker) + const { zoomIn, zoomOut, isMaxZoom, isMinZoom } = + useZoomControls(DESTINATION_PAGE) useEffect(() => { if (ref.current && activeMarker && pageType === "overview") { @@ -82,23 +92,10 @@ export default function DynamicMap({ } }) - function zoomIn() { - const currentZoom = map && map.getZoom() - if (currentZoom) { - map.setZoom(currentZoom + 1) - } - } - function zoomOut() { - const currentZoom = map && map.getZoom() - if (currentZoom) { - map.setZoom(currentZoom - 1) - } - } - const mapOptions: MapProps = { defaultCenter, // Default center will be overridden by the bounds - minZoom: 3, - maxZoom: 18, + minZoom: DESTINATION_PAGE.MIN_ZOOM, + maxZoom: DESTINATION_PAGE.MAX_ZOOM, defaultZoom, disableDefaultUI: true, clickableIcons: false, @@ -111,7 +108,7 @@ export default function DynamicMap({
          @@ -129,48 +126,46 @@ export default function DynamicMap({
          {onClose && ( )}
          - - + +
          diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/CityMarker/cityMarker.module.css b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/CityMarker/cityMarker.module.css new file mode 100644 index 000000000..be3b5154a --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/CityMarker/cityMarker.module.css @@ -0,0 +1,19 @@ +.cityMarker { + width: 28px !important; + height: 28px !important; + background-color: var(--Base-Text-High-contrast); + border: 4px solid var(--Base-Surface-Primary-light-Normal); + border-radius: var(--Corner-radius-rounded); + box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.1); + cursor: pointer; + transition: all 0.3s; +} + +.cityMarker:hover, +.hoveredChild { + background: + linear-gradient(rgba(31, 28, 27, 0.3), rgba(31, 28, 27, 0.3)), + var(--Surface-Brand-Primary-2-Default); + width: var(--Space-x4) !important; + height: var(--Space-x4) !important; +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/CityMarker/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/CityMarker/index.tsx new file mode 100644 index 000000000..71c8ba546 --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/CityMarker/index.tsx @@ -0,0 +1,93 @@ +"use client" + +import { + AdvancedMarker, + AdvancedMarkerAnchorPoint, + InfoWindow, +} from "@vis.gl/react-google-maps" +import { useCallback, useState } from "react" +import { useMediaQuery } from "usehooks-ts" + +import { useDestinationPageCitiesMapStore } from "@/stores/destination-page-cities-map" + +import { trackMapClick } from "@/utils/tracking/destinationPage" + +import CityMapCard from "../../../DestinationCountryPage/CityMapCard" + +import styles from "./cityMarker.module.css" + +import type { CityMarkerProperties } from "@/types/components/maps/destinationMarkers" + +interface CityMarkerProps { + position: google.maps.LatLngLiteral + properties: CityMarkerProperties +} + +export default function CityMarker({ position, properties }: CityMarkerProps) { + const { + hoveredCityMarker, + setHoveredCityMarker, + activeCityMarker, + setActiveCityMarker, + } = useDestinationPageCitiesMapStore() + + const [infoWindowHovered, setInfoWindowHovered] = useState(false) + + const isDesktop = useMediaQuery("(min-width: 950px)") + + const handleClick = useCallback(() => { + setActiveCityMarker({ cityId: properties.id, location: position }) + trackMapClick(`city with id: ${properties.id}`) + }, [position, properties.id, setActiveCityMarker]) + + function handleMouseEnter() { + if (activeCityMarker?.cityId !== hoveredCityMarker) { + setActiveCityMarker(null) + } + setHoveredCityMarker(properties.id) + } + + function handleMouseLeave() { + setTimeout(() => { + if (!infoWindowHovered) { + setHoveredCityMarker(null) + } + }, 100) + } + + const isHovered = hoveredCityMarker === properties.id || infoWindowHovered + const isActive = activeCityMarker?.cityId === properties.id + + return ( + + {isDesktop && (isActive || isHovered) ? ( + setInfoWindowHovered(true)} + onMouseLeave={() => setInfoWindowHovered(false)} + > + + + + + ) : ( + + )} + + ) +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/CityClusterMarker.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/CityClusterMarker.tsx new file mode 100644 index 000000000..51caff5c7 --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/CityClusterMarker.tsx @@ -0,0 +1,100 @@ +"use client" + +import { + AdvancedMarker, + AdvancedMarkerAnchorPoint, + InfoWindow, +} from "@vis.gl/react-google-maps" +import { useCallback, useState } from "react" +import { useMediaQuery } from "usehooks-ts" + +import { useDestinationPageCitiesMapStore } from "@/stores/destination-page-cities-map" + +import { trackMapClick } from "@/utils/tracking/destinationPage" + +import { LocationsList } from "../../../DestinationCountryPage/LocationsList" + +import styles from "./clusterMarker.module.css" + +import type { CityMarkerProperties } from "@/types/components/maps/destinationMarkers" + +interface ClusterMarkerProps { + position: google.maps.LatLngLiteral + size: number + sizeAsText: string + onMarkerClick?: (position: google.maps.LatLngLiteral) => void + cities: CityMarkerProperties[] +} + +export default function CityClusterMarker({ + position, + size, + sizeAsText, + onMarkerClick, + cities, +}: ClusterMarkerProps) { + const { hoveredCityMarker, activeCityMarker, setActiveCityMarker } = + useDestinationPageCitiesMapStore() + const isDesktop = useMediaQuery("(min-width: 950px)") + + const [isHoveredOnMap, setIsHoveredOnMap] = useState(false) + const [infoWindowHovered, setInfoWindowHovered] = useState(false) + + const isActive = + cities.find( + (city) => + city.id === hoveredCityMarker || city.id === activeCityMarker?.cityId + ) || infoWindowHovered + + const handleClick = useCallback(() => { + if (onMarkerClick) { + onMarkerClick(position) + } + trackMapClick( + `cluster with cities: ${cities.map((city) => city.id).join(",")}` + ) + }, [onMarkerClick, position, cities]) + + function handleMouseEnter() { + if (activeCityMarker?.cityId !== hoveredCityMarker) { + setActiveCityMarker(null) + } + setIsHoveredOnMap(true) + } + + function handleMouseLeave() { + setTimeout(() => { + if (!infoWindowHovered) { + setIsHoveredOnMap(false) + } + }, 100) + } + + return ( + + {sizeAsText} + {isDesktop && (isHoveredOnMap || infoWindowHovered) ? ( + setInfoWindowHovered(true)} + onMouseLeave={() => setInfoWindowHovered(false)} + > + + + + + ) : null} + + ) +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/HotelClusterMarker.tsx similarity index 84% rename from apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/index.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/HotelClusterMarker.tsx index 56113cb8f..0ab5b45cd 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/ClusterMarker/HotelClusterMarker.tsx @@ -12,25 +12,25 @@ import { trackMapClick } from "@/utils/tracking/destinationPage" import styles from "./clusterMarker.module.css" -interface ClusterMarkerProps { +interface HotelClusterMarkerProps { position: google.maps.LatLngLiteral size: number sizeAsText: string onMarkerClick?: (position: google.maps.LatLngLiteral) => void - hotelIds: number[] + hotelIds: string[] } - -export default function ClusterMarker({ +export default function HotelClusterMarker({ position, size, sizeAsText, onMarkerClick, hotelIds, -}: ClusterMarkerProps) { +}: HotelClusterMarkerProps) { const { hoveredMarker, activeMarker } = useDestinationPageHotelsMapStore() + const isActive = - hotelIds.includes(Number(hoveredMarker)) || - hotelIds.includes(Number(activeMarker)) + hotelIds.includes(String(hoveredMarker)) || + hotelIds.includes(String(activeMarker)) 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/HotelMarker/index.tsx similarity index 95% rename from apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx rename to apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/HotelMarker/index.tsx index 720d8eb0b..97d0a3f09 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/Marker/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/HotelMarker/index.tsx @@ -20,12 +20,15 @@ import type { HotelType } from "@scandic-hotels/common/constants/hotelType" import type { MarkerProperties } from "@/types/components/maps/destinationMarkers" -interface MarkerProps { +interface HotelMarkerProps { position: google.maps.LatLngLiteral properties: MarkerProperties } -export default function Marker({ position, properties }: MarkerProps) { +export default function HotelMarker({ + position, + properties, +}: HotelMarkerProps) { const [markerRef] = useAdvancedMarkerRef() const { setHoveredMarker, setActiveMarker, hoveredMarker, activeMarker } = diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/index.tsx index 871ff6f76..55f001a59 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/MapContent/index.tsx @@ -2,24 +2,33 @@ import { useMap } from "@vis.gl/react-google-maps" import { useEffect } from "react" +import { useMediaQuery } from "usehooks-ts" +import { CITY_PAGE } from "@scandic-hotels/design-system/Map/mapConstants" + +import { useDestinationPageCitiesMapStore } from "@/stores/destination-page-cities-map" import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" import { useSupercluster } from "@/hooks/maps/use-supercluster" -import ClusterMarker from "./ClusterMarker" -import Marker from "./Marker" +import CityClusterMarker from "./ClusterMarker/CityClusterMarker" +import HotelClusterMarker from "./ClusterMarker/HotelClusterMarker" +import CityMarker from "./CityMarker" +import HotelMarker from "./HotelMarker" import type { ClusterProperties } from "supercluster" import type { + CityMarkerGeojson, + CityMarkerProperties, MarkerGeojson, MarkerProperties, } from "@/types/components/maps/destinationMarkers" interface MapContentProps { - geojson: MarkerGeojson + geojson: MarkerGeojson | CityMarkerGeojson disableClustering?: boolean + pageType: "city" | "country" | "overview" } // Important this is outside the component to avoid re-creating the object on each render @@ -33,12 +42,19 @@ const CLUSTER_OPTIONS = { export default function MapContent({ geojson, disableClustering, + pageType, }: MapContentProps) { const { setActiveMarker, activeMarker } = useDestinationPageHotelsMapStore() - const map = useMap() + const { setActiveCityMarker, activeCityMarker } = + useDestinationPageCitiesMapStore() - const { clusters, containedHotels, getClusterZoom } = - useSupercluster(geojson, CLUSTER_OPTIONS) + const { clusters, containedHotelIds, containedCityIds, getClusterZoom } = + useSupercluster( + geojson, + CLUSTER_OPTIONS + ) + const map = useMap() + const isDesktop = useMediaQuery("(min-width: 950px)") // Based on the length of active filters, we decide if should show clusters or individual markers const markerList = disableClustering ? geojson.features : clusters @@ -51,6 +67,23 @@ export default function MapContent({ }) }, [activeMarker, map, setActiveMarker]) + useEffect(() => { + map?.addListener("click", () => { + if (activeCityMarker) { + setActiveCityMarker(null) + } + }) + }, [activeCityMarker, map, setActiveCityMarker]) + + useEffect(() => { + if (!isDesktop) return + const currentZoom = map && map.getZoom() + if (currentZoom && activeCityMarker?.location) { + map.panTo(activeCityMarker.location) + map.setZoom(CITY_PAGE.DEFAULT_ZOOM) + } + }, [activeCityMarker, map, isDesktop]) + function handleClusterClick( position: google.maps.LatLngLiteral, clusterProperties: ClusterProperties @@ -67,26 +100,47 @@ export default function MapContent({ return markerList.map((feature, idx) => { const [lng, lat] = feature.geometry.coordinates const clusterProperties = feature.properties as ClusterProperties - const markerProperties = feature.properties as MarkerProperties + const hotelMarkerProperties = feature.properties as MarkerProperties + const cityMarkerProperties = feature.properties as CityMarkerProperties const isCluster = clusterProperties?.cluster - return isCluster ? ( - - handleClusterClick(position, clusterProperties) - } - hotelIds={containedHotels[idx]} - /> - ) : ( - - ) + if (pageType === "country") { + return isCluster ? ( + + handleClusterClick(position, clusterProperties) + } + cities={containedCityIds[idx]} + /> + ) : ( + + ) + } else + return isCluster ? ( + + handleClusterClick(position, clusterProperties) + } + hotelIds={containedHotelIds[idx]} + /> + ) : ( + + ) }) } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx index 396c1611d..12f00da0b 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/index.tsx @@ -1,6 +1,6 @@ "use client" -import { useRouter } from "next/navigation" +import { useParams, useRouter } from "next/navigation" import { type PropsWithChildren, useCallback, @@ -14,47 +14,59 @@ import { useIntl } from "react-intl" import { useScrollToTop } from "@scandic-hotels/common/hooks/useScrollToTop" import { debounce } from "@scandic-hotels/common/utils/debounce" import { BackToTopButton } from "@scandic-hotels/design-system/BackToTopButton" +import { Button } from "@scandic-hotels/design-system/Button" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton" +import { + CITY_PAGE, + COUNTRY_PAGE, +} from "@scandic-hotels/design-system/Map/mapConstants" import { useDestinationDataStore } from "@/stores/destination-data" -import { useDestinationPageHotelsMapStore } from "@/stores/destination-page-hotels-map" import DestinationFilterAndSort from "@/components/DestinationFilterAndSort" import DynamicMap from "./DynamicMap" import MapContent from "./MapContent" import MapProvider from "./MapProvider" -import { getHotelMapMarkers, mapMarkerDataToGeoJson } from "./utils" import styles from "./map.module.css" -import type { HotelListingHotelData } from "@scandic-hotels/trpc/types/hotel" - import type { MapLocation } from "@/types/components/mapLocation" +import type { + CityMarker, + CityMarkerGeojson, + DestinationMarker, + MarkerGeojson, +} from "@/types/components/maps/destinationMarkers" interface MapProps { - hotels: HotelListingHotelData[] mapId: string apiKey: string - pageType: "city" | "country" + pageType: "country" | "city" + activeLocation?: { latitude: number; longitude: number } | null + setActiveLocation: (id: null) => void + markers: DestinationMarker[] | CityMarker[] + geoJson: MarkerGeojson | CityMarkerGeojson defaultLocation: MapLocation } export default function Map({ - hotels, mapId, apiKey, - defaultLocation, pageType, + activeLocation, children, + setActiveLocation, + markers, + geoJson, + defaultLocation, }: PropsWithChildren) { const router = useRouter() - const { activeMarker: activeHotelId, setActiveMarker } = - useDestinationPageHotelsMapStore() - const activeHotel = hotels.find(({ hotel }) => hotel.id === activeHotelId) + const rootDiv = useRef(null) const [mapHeight, setMapHeight] = useState("100dvh") + const [fromCountryPage, setFromCountryPage] = useState(false) + const params = useParams() const scrollRef = useRef(null) const { showBackToTop, scrollToTop } = useScrollToTop({ threshold: 550, @@ -68,24 +80,14 @@ export default function Map({ activeFilters: state.activeFilters, })) + const zoomConstants = pageType === "city" ? CITY_PAGE : COUNTRY_PAGE + const hasActiveFilters = activeFilters.length > 0 - const markers = getHotelMapMarkers(hotels) - const geoJson = mapMarkerDataToGeoJson(markers) - const defaultCenter = activeHotel - ? { - lat: activeHotel.hotel.location.latitude, - lng: activeHotel.hotel.location.longitude, - } - : defaultLocation - ? { - lat: defaultLocation.latitude, - lng: defaultLocation.longitude, - } - : undefined - const defaultZoom = activeHotel - ? 15 - : (defaultLocation?.default_zoom ?? (pageType === "city" ? 10 : 3)) + useEffect(() => { + const url = new URL(window.location.href) + setFromCountryPage(url.searchParams.has("fromCountry")) + }, [params]) // Calculate the height of the map based on the viewport height from the start-point (below the header and booking widget) const handleMapHeight = useCallback(() => { @@ -94,10 +96,22 @@ export default function Map({ }, []) function handleClose() { + if (fromCountryPage) { + const url = new URL(window.location.href) + url.searchParams.set("view", "map") + router.push(url.toString()) + setActiveLocation(null) + } else { + backToListView() + } + } + + function backToListView() { const url = new URL(window.location.href) url.searchParams.delete("view") + url.searchParams.delete("fromCountry") router.push(url.toString()) - setActiveMarker(null) + setActiveLocation(null) } useLayoutEffect(() => { @@ -131,6 +145,22 @@ export default function Map({ } }, [rootDiv, handleMapHeight]) + const defaultCenter = activeLocation + ? { + lat: activeLocation.latitude, + lng: activeLocation.longitude, + } + : defaultLocation + ? { + lat: defaultLocation.latitude, + lng: defaultLocation.longitude, + } + : undefined + + const defaultZoom = activeLocation + ? zoomConstants.SELECTED_HOTEL_ZOOM + : (defaultLocation?.default_zoom ?? zoomConstants.DEFAULT_ZOOM) + return (
          - +
          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 c524afe27..c9761b371 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/map.module.css @@ -22,7 +22,7 @@ .mobileNavigation { display: flex; - padding: var(--Space-x2); + padding: 0 var(--Space-x2); justify-content: space-between; background-color: var(--Surface-Primary-OnSurface-Default); } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts b/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts index ec5416023..509d636e4 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts +++ b/apps/scandic-web/components/ContentType/DestinationPage/Map/utils.ts @@ -1,6 +1,10 @@ +import type { DestinationCityListItem } from "@scandic-hotels/trpc/types/destinationCityPage" import type { HotelListingHotelData } from "@scandic-hotels/trpc/types/hotel" import type { + CityMarker, + CityMarkerFeature, + CityMarkerGeojson, DestinationMarker, MarkerFeature, MarkerGeojson, @@ -52,6 +56,59 @@ export function getHotelMapMarkers(hotels: HotelListingHotelData[]) { return markers } +export function mapCityMarkerDataToGeoJson(markers: CityMarker[]) { + const features = markers.map( + ({ coordinates, ...properties }) => { + return { + type: "Feature", + id: properties.id, + geometry: { + type: "Point", + coordinates: [coordinates.lng, coordinates.lat], + }, + properties, + } + } + ) + + const geoJson: CityMarkerGeojson = { + type: "FeatureCollection", + features, + } + + return geoJson +} + +export function getCityMapMarkers(cities: DestinationCityListItem[]) { + const markers = cities + .map( + ({ + cityName, + cityIdentifier, + url, + destination_settings, + images, + hotelsCount, + }) => ({ + id: cityIdentifier, + name: cityName, + coordinates: destination_settings.location + ? { + lat: destination_settings.location.latitude, + lng: destination_settings.location.longitude, + } + : null, + hotelsCount, + url, + image: getCityImage({ images }), + }) + ) + + .filter((item): item is CityMarker => !!item.coordinates) + + return markers +} + function getImage({ hotel }: Pick) { if (hotel.galleryImages?.length) { const image = hotel.galleryImages[0] @@ -62,3 +119,13 @@ function getImage({ hotel }: Pick) { } return null } +function getCityImage({ images }: Pick) { + if (images?.length) { + const image = images[0] + return { + src: image.url, + alt: image.meta.alt || image.meta.caption, + } + } + return null +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/SeeOnMapFilterWrapper/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/SeeOnMapFilterWrapper/index.tsx new file mode 100644 index 000000000..0561f3986 --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/SeeOnMapFilterWrapper/index.tsx @@ -0,0 +1,42 @@ +import { useIntl } from "react-intl" + +import ButtonLink from "@scandic-hotels/design-system/ButtonLink" +import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" + +import DestinationFilterAndSort, { + type HotelFilterAndSortProps, +} from "@/components/DestinationFilterAndSort" + +import styles from "./seeOnMapFilterWrapper.module.css" + +interface SeeOnMapFilterWrapperProps extends HotelFilterAndSortProps { + mapUrl: string | null +} + +export function SeeOnMapFilterWrapper({ + listType, + mapUrl, +}: SeeOnMapFilterWrapperProps) { + const intl = useIntl() + return ( +
          + {mapUrl ? ( + + + {intl.formatMessage({ + defaultMessage: "See on map", + })} + + ) : null} + +
          + ) +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/SeeOnMapFilterWrapper/seeOnMapFilterWrapper.module.css b/apps/scandic-web/components/ContentType/DestinationPage/SeeOnMapFilterWrapper/seeOnMapFilterWrapper.module.css new file mode 100644 index 000000000..19b879e2e --- /dev/null +++ b/apps/scandic-web/components/ContentType/DestinationPage/SeeOnMapFilterWrapper/seeOnMapFilterWrapper.module.css @@ -0,0 +1,15 @@ +.cta { + display: flex; + justify-content: space-between; + gap: var(--Space-x2); +} + +.mapButton { + width: 100%; +} + +@media screen and (min-width: 950px) { + .mapButton { + display: none !important; /* Important to override button higher specificy */ + } +} diff --git a/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/index.tsx index 44eea98a5..65782bb68 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/index.tsx @@ -1,6 +1,6 @@ "use client" -import { useRef } from "react" +import React, { useRef } from "react" import { useIntl } from "react-intl" import useStickyPosition from "@scandic-hotels/common/hooks/useStickyPosition" @@ -9,18 +9,20 @@ import { Typography } from "@scandic-hotels/design-system/Typography" import { useDestinationDataStore } from "@/stores/destination-data" -import { getHeadingText } from "@/components/ContentType/DestinationPage/utils" +import { getCityHeadingText, getCountryHeadingText } from "../utils" import styles from "./sidebarContentWrapper.module.css" interface SidebarContentWrapperProps extends React.PropsWithChildren { preamble: string location: string + pageType: "country" | "city" } export default function SidebarContentWrapper({ preamble, location, + pageType, children, }: SidebarContentWrapperProps) { const intl = useIntl() @@ -33,19 +35,23 @@ export default function SidebarContentWrapper({ ref: sidebarRef, name: StickyElementNameEnum.DESTINATION_SIDEBAR, }) - - const heading = getHeadingText(intl, location, allFilters, filterFromUrl) + const heading = + pageType === "country" + ? getCountryHeadingText(intl, location, allFilters, filterFromUrl) + : getCityHeadingText(intl, location, allFilters, filterFromUrl) return (
          - -

          {heading}

          -
          - {!filterFromUrl ? ( - -

          {preamble}

          +
          + +

          {heading}

          - ) : null} + {!filterFromUrl ? ( + +

          {preamble}

          +
          + ) : null} +
          {children}
          ) diff --git a/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/sidebarContentWrapper.module.css b/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/sidebarContentWrapper.module.css index 4ae46d039..32ef8161d 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/sidebarContentWrapper.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/SidebarContentWrapper/sidebarContentWrapper.module.css @@ -5,20 +5,30 @@ padding: 0 var(--max-width-single-spacing) var(--Space-x3); } +.text { + display: grid; + gap: var(--Space-x2); + color: var(--Text-Default); + max-width: var(--max-width-text-block); +} + .heading { color: var(--Text-Heading); hyphens: auto; text-wrap: balance; } -.text { - color: var(--Text-Default); - max-width: var(--max-width-text-block); +@media screen and (min-width: 950px) { + .sidebarContent { + grid-template-columns: 1fr auto; + padding: var(--Space-x4) var(--Space-x3); + } } @media screen and (min-width: 1367px) { .sidebarContent { position: sticky; padding: var(--Space-x4) var(--Space-x3); + grid-template-columns: none; } } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/index.tsx index 640ac415e..232025da5 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/index.tsx @@ -1,22 +1,15 @@ "use client" import Link from "next/link" -import { useParams } from "next/navigation" -import { useEffect, useState } from "react" + +import useSetMapView from "@scandic-hotels/common/hooks/map/useSetMapView" import { MapWithButtonWrapper } from "@/components/Maps/MapWithButtonWrapper" import styles from "./mapWrapper.module.css" export default function MapWrapper({ children }: React.PropsWithChildren) { - const params = useParams() - const [mapUrl, setMapUrl] = useState(null) - - useEffect(() => { - const url = new URL(window.location.href) - url.searchParams.set("view", "map") - setMapUrl(url.toString()) - }, [params]) + const mapUrl = useSetMapView() if (!mapUrl) { return null diff --git a/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/mapWrapper.module.css b/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/mapWrapper.module.css index 4d3964190..68a31db9c 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/mapWrapper.module.css +++ b/apps/scandic-web/components/ContentType/DestinationPage/StaticMap/MapWrapper/mapWrapper.module.css @@ -2,8 +2,8 @@ display: none; } -@media (min-width: 1367px) { +@media (min-width: 950px) { .link { - display: flex; + display: block; } } diff --git a/apps/scandic-web/components/ContentType/DestinationPage/utils.ts b/apps/scandic-web/components/ContentType/DestinationPage/utils.ts index 83490af11..da1f3e117 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/utils.ts +++ b/apps/scandic-web/components/ContentType/DestinationPage/utils.ts @@ -4,7 +4,7 @@ import type { } from "@scandic-hotels/trpc/types/hotel" import type { IntlShape } from "react-intl" -export function getHeadingText( +export function getCityHeadingText( intl: IntlShape, location: string, allFilters: CategorizedHotelFilters, @@ -41,3 +41,41 @@ export function getHeadingText( { location } ) } + +export function getCountryHeadingText( + intl: IntlShape, + location: string, + allFilters: CategorizedHotelFilters, + filterFromUrl: HotelFilter | null +) { + if (filterFromUrl) { + const facilityFilter = allFilters.facilityFilters.find( + (f) => f.id === filterFromUrl.id + ) + const surroudingsFilter = allFilters.surroundingsFilters.find( + (f) => f.id === filterFromUrl.id + ) + + if (facilityFilter) { + return intl.formatMessage( + { + defaultMessage: "Destinations with {filter} in {location}", + }, + { location, filter: facilityFilter.name } + ) + } else if (surroudingsFilter) { + return intl.formatMessage( + { + defaultMessage: "Destinations near {filter} in {location}", + }, + { location, filter: surroudingsFilter.name } + ) + } + } + return intl.formatMessage( + { + defaultMessage: "Destinations in {location}", + }, + { location } + ) +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx index 1fd2a74f3..abd418d80 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelPage/Map/MapCard/index.tsx @@ -1,9 +1,8 @@ "use client" -import { useParams } from "next/navigation" -import { useEffect, useState } from "react" import { useIntl } from "react-intl" +import useSetMapView from "@scandic-hotels/common/hooks/map/useSetMapView" import ButtonLink from "@scandic-hotels/design-system/ButtonLink" import { PoiMarker } from "@scandic-hotels/design-system/Map/Markers/PoiMarker" import { Typography } from "@scandic-hotels/design-system/Typography" @@ -16,14 +15,7 @@ import type { MapCardProps } from "@/types/components/hotelPage/map/mapCard" export default function MapCard({ hotelName, pois }: MapCardProps) { const intl = useIntl() - const params = useParams() - const [mapUrl, setMapUrl] = useState(null) - - useEffect(() => { - const url = new URL(window.location.href) - url.searchParams.set("view", "map") - setMapUrl(url.toString()) - }, [params]) + const mapUrl = useSetMapView() return (
          diff --git a/apps/scandic-web/components/ContentType/HotelPage/Map/MobileMapToggle/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/Map/MobileMapToggle/index.tsx index cffa87c36..05ba38108 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/Map/MobileMapToggle/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelPage/Map/MobileMapToggle/index.tsx @@ -1,10 +1,9 @@ "use client" import { cx } from "class-variance-authority" import NextLink from "next/link" -import { useParams } from "next/navigation" -import { useEffect, useState } from "react" import { useIntl } from "react-intl" +import useSetMapView from "@scandic-hotels/common/hooks/map/useSetMapView" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { Typography } from "@scandic-hotels/design-system/Typography" @@ -14,14 +13,7 @@ import styles from "./mobileToggle.module.css" export default function MobileMapToggle() { const intl = useIntl() - const params = useParams() - const [mapUrl, setMapUrl] = useState(null) - - useEffect(() => { - const url = new URL(window.location.href) - url.searchParams.set("view", "map") - setMapUrl(url.toString()) - }, [params]) + const mapUrl = useSetMapView() if (!mapUrl) { return null diff --git a/apps/scandic-web/components/DestinationFilterAndSort/FilterAndSortButton/filterAndSort.module.css b/apps/scandic-web/components/DestinationFilterAndSort/FilterAndSortButton/filterAndSort.module.css new file mode 100644 index 000000000..2224ecdda --- /dev/null +++ b/apps/scandic-web/components/DestinationFilterAndSort/FilterAndSortButton/filterAndSort.module.css @@ -0,0 +1,20 @@ +.buttonWrapper { + display: flex; + gap: var(--Space-x1); + align-items: center; + width: 100%; +} + +.mapView { + width: fit-content; +} + +.button { + width: 100%; +} + +@media screen and (min-width: 949px) { + .buttonWrapper { + width: fit-content; + } +} diff --git a/apps/scandic-web/components/DestinationFilterAndSort/FilterAndSortButton/index.tsx b/apps/scandic-web/components/DestinationFilterAndSort/FilterAndSortButton/index.tsx new file mode 100644 index 000000000..66782fb7f --- /dev/null +++ b/apps/scandic-web/components/DestinationFilterAndSort/FilterAndSortButton/index.tsx @@ -0,0 +1,68 @@ +"use client" +import { cx } from "class-variance-authority" +import { useSearchParams } from "next/navigation" +import { useEffect, useState } from "react" +import { useIntl } from "react-intl" +import { useMediaQuery } from "usehooks-ts" + +import { Badge } from "@scandic-hotels/design-system/Badge" +import { Button } from "@scandic-hotels/design-system/Button" +import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" + +import styles from "./filterAndSort.module.css" + +interface FilterAndSortButtonProps { + filterLength: number +} + +export function FilterAndSortButton({ + filterLength, +}: FilterAndSortButtonProps) { + const intl = useIntl() + + const searchParams = useSearchParams() + const [isMapView, setIsMapView] = useState(false) + + useEffect(() => { + const isMapView = searchParams.get("view") === "map" + setIsMapView(isMapView) + setIsHydrated(true) + }, [searchParams]) + + const [isHydrated, setIsHydrated] = useState(false) + const isDesktop = useMediaQuery("(min-width: 950px)") + if (!isHydrated) return null + + const buttonProps: { + variant: "Text" | "Secondary" + size: "Small" | "Medium" + } = isDesktop + ? { + //Desktop + variant: "Text", + size: "Medium", + } + : { + //Mobile + variant: isMapView ? "Text" : "Secondary", + size: "Small", + } + + return ( +
          + +
          + ) +} diff --git a/apps/scandic-web/components/DestinationFilterAndSort/destinationFilterAndSort.module.css b/apps/scandic-web/components/DestinationFilterAndSort/destinationFilterAndSort.module.css index 08bed3a5d..d198606b7 100644 --- a/apps/scandic-web/components/DestinationFilterAndSort/destinationFilterAndSort.module.css +++ b/apps/scandic-web/components/DestinationFilterAndSort/destinationFilterAndSort.module.css @@ -25,23 +25,6 @@ border-bottom: 1px solid var(--Base-Border-Subtle); } -.buttonWrapper { - display: flex; - gap: var(--Spacing-x1); - align-items: center; -} - -.badge { - background-color: var(--Base-Text-Accent); - border-radius: var(--Corner-radius-xl); - width: 20px; - height: 20px; - color: var(--Base-Surface-Primary-light-Normal); - display: flex; - align-items: center; - justify-content: center; -} - .content { display: grid; gap: var(--Spacing-x4); diff --git a/apps/scandic-web/components/DestinationFilterAndSort/index.tsx b/apps/scandic-web/components/DestinationFilterAndSort/index.tsx index 56d2bef0b..a204b4cee 100644 --- a/apps/scandic-web/components/DestinationFilterAndSort/index.tsx +++ b/apps/scandic-web/components/DestinationFilterAndSort/index.tsx @@ -12,20 +12,20 @@ import { useIntl } from "react-intl" import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert" import { Alert } from "@scandic-hotels/design-system/Alert" +import { Button } from "@scandic-hotels/design-system/Button" import { Divider } from "@scandic-hotels/design-system/Divider" -import Footnote from "@scandic-hotels/design-system/Footnote" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton" import Subtitle from "@scandic-hotels/design-system/Subtitle" import { useDestinationDataStore } from "@/stores/destination-data" import Filter from "./Filter" +import { FilterAndSortButton } from "./FilterAndSortButton" import Sort from "./Sort" import styles from "./destinationFilterAndSort.module.css" -interface HotelFilterAndSortProps { +export interface HotelFilterAndSortProps { listType: "city" | "hotel" } @@ -127,23 +127,10 @@ export default function DestinationFilterAndSort({ resetPendingValues() } } - return ( <> -
          - - {activeFilters.length > 0 && ( - - {activeFilters.length} - - )} -
          +