diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts
index baddc740d..ee541bb7a 100644
--- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts
+++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts
@@ -95,14 +95,15 @@ export function getHotelPins(hotels: HotelData[]): HotelPin[] {
lng: hotel.hotelData.location.longitude,
},
name: hotel.hotelData.name,
- price: hotel.price
- ? `${Math.min(
- parseFloat(hotel.price.memberAmount ?? "Infinity"),
- parseFloat(hotel.price.regularAmount ?? "Infinity")
- )}`
- : "N/A",
- currency: hotel.price?.currency || "Unknown",
- image: "default-image-url",
+ publicPrice: hotel.price?.regularAmount ?? null,
+ memberPrice: hotel.price?.memberAmount ?? null,
+ currency: hotel.price?.currency || null,
+ images: [
+ hotel.hotelData.hotelContent.images,
+ ...(hotel.hotelData.gallery?.heroImages ?? []),
+ ],
+ amenities: hotel.hotelData.detailedFacilities.slice(0, 3),
+ ratings: hotel.hotelData.ratings?.tripAdvisor.rating ?? null,
}))
}
diff --git a/components/HotelReservation/HotelCard/hotelCard.module.css b/components/HotelReservation/HotelCard/hotelCard.module.css
index 629b52be6..74569c12f 100644
--- a/components/HotelReservation/HotelCard/hotelCard.module.css
+++ b/components/HotelReservation/HotelCard/hotelCard.module.css
@@ -67,7 +67,7 @@
}
@media screen and (min-width: 1367px) {
- .card.listing {
+ .card.pageListing {
grid-template-areas:
"image header"
"image hotel"
@@ -76,30 +76,30 @@
padding: 0;
}
- .listing .imageContainer {
+ .pageListing .imageContainer {
position: relative;
min-height: 200px;
width: 518px;
}
- .listing .tripAdvisor {
+ .pageListing .tripAdvisor {
position: absolute;
display: block;
left: 7px;
top: 7px;
}
- .listing .hotelInformation {
+ .pageListing .hotelInformation {
padding-top: var(--Spacing-x2);
padding-right: var(--Spacing-x2);
}
- .listing .hotel {
+ .pageListing .hotel {
gap: var(--Spacing-x2);
padding-right: var(--Spacing-x2);
}
- .listing .prices {
+ .pageListing .prices {
flex-direction: row;
align-items: center;
justify-content: space-between;
@@ -107,11 +107,11 @@
padding-bottom: var(--Spacing-x2);
}
- .listing .detailsButton {
+ .pageListing .detailsButton {
border-bottom: none;
}
- .listing .button {
+ .pageListing .button {
width: 160px;
}
}
diff --git a/components/HotelReservation/HotelCard/index.tsx b/components/HotelReservation/HotelCard/index.tsx
index 9ed97d961..9a08d0425 100644
--- a/components/HotelReservation/HotelCard/index.tsx
+++ b/components/HotelReservation/HotelCard/index.tsx
@@ -17,9 +17,13 @@ import { hotelCardVariants } from "./variants"
import styles from "./hotelCard.module.css"
+import { HotelCardListingType } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps"
-export default function HotelCard({ hotel, type = "listing" }: HotelCardProps) {
+export default function HotelCard({
+ hotel,
+ type = HotelCardListingType.PageListing,
+}: HotelCardProps) {
const intl = useIntl()
const { hotelData } = hotel
diff --git a/components/HotelReservation/HotelCard/variants.ts b/components/HotelReservation/HotelCard/variants.ts
index 3715e6509..e71cc44a1 100644
--- a/components/HotelReservation/HotelCard/variants.ts
+++ b/components/HotelReservation/HotelCard/variants.ts
@@ -5,11 +5,11 @@ import styles from "./hotelCard.module.css"
export const hotelCardVariants = cva(styles.card, {
variants: {
type: {
- listing: styles.listing,
- map: styles.map,
+ pageListing: styles.pageListing,
+ mapListing: styles.mapListing,
},
},
defaultVariants: {
- type: "listing",
+ type: "pageListing",
},
})
diff --git a/components/HotelReservation/HotelCardDialog/hotelCardDialog.module.css b/components/HotelReservation/HotelCardDialog/hotelCardDialog.module.css
new file mode 100644
index 000000000..13e295588
--- /dev/null
+++ b/components/HotelReservation/HotelCardDialog/hotelCardDialog.module.css
@@ -0,0 +1,70 @@
+.dialog {
+ padding-bottom: var(--Spacing-x1);
+ bottom: 32px;
+ left: 50%;
+ transform: translateX(-50%);
+ border: none;
+ background: transparent;
+}
+
+.dialogContainer {
+ border: 1px solid var(--Base-Border-Subtle);
+ border-radius: var(--Corner-radius-Medium);
+ width: 402px;
+ min-height: 227px;
+ background: var(--Base-Surface-Primary-light-Normal);
+ box-shadow: 0px 0px 8px 3px rgba(0, 0, 0, 0.1);
+ flex-direction: row;
+ display: flex;
+}
+
+.imageContainer {
+ position: relative;
+ min-height: 227px;
+ width: 177px;
+}
+
+.tripAdvisor {
+ display: none;
+}
+
+.imageContainer img {
+ object-fit: cover;
+}
+
+.content {
+ width: 100%;
+ padding: var(--Spacing-x-one-and-half);
+ gap: var(--Spacing-x1);
+ display: flex;
+ flex-direction: column;
+}
+
+.facilities {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--Spacing-x1);
+}
+
+.facilitiesItem {
+ display: flex;
+ align-items: center;
+ gap: var(--Spacing-x-half);
+}
+
+.prices {
+ border-radius: var(--Corner-radius-Medium);
+ padding: var(--Spacing-x-half) var(--Spacing-x1);
+ background: var(--Base-Surface-Secondary-light-Normal);
+ display: flex;
+ flex-direction: column;
+ gap: var(--Spacing-x-half);
+}
+
+.perNight {
+ color: var(--Base-Text-Subtle-light-Normal);
+}
+
+.button {
+ margin-top: auto;
+}
diff --git a/components/HotelReservation/HotelCardDialog/index.tsx b/components/HotelReservation/HotelCardDialog/index.tsx
new file mode 100644
index 000000000..9f121cf95
--- /dev/null
+++ b/components/HotelReservation/HotelCardDialog/index.tsx
@@ -0,0 +1,90 @@
+"use client"
+
+import { useIntl } from "react-intl"
+
+import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
+import TripAdvisorIcon from "@/components/Icons/TripAdvisor"
+import Image from "@/components/Image"
+import Button from "@/components/TempDesignSystem/Button"
+import Chip from "@/components/TempDesignSystem/Chip"
+import Body from "@/components/TempDesignSystem/Text/Body"
+import Caption from "@/components/TempDesignSystem/Text/Caption"
+import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
+
+import styles from "./hotelCardDialog.module.css"
+
+import { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
+
+export default function HotelCardDialog({
+ pin,
+ isOpen,
+}: {
+ isOpen: boolean
+ pin: HotelPin
+}) {
+ const intl = useIntl()
+
+ const {
+ name,
+ publicPrice,
+ memberPrice,
+ currency,
+ amenities,
+ images,
+ ratings,
+ } = pin
+
+ return (
+
+ )
+}
diff --git a/components/HotelReservation/HotelCardListing/index.tsx b/components/HotelReservation/HotelCardListing/index.tsx
index b51bd07bb..9a7b4eecf 100644
--- a/components/HotelReservation/HotelCardListing/index.tsx
+++ b/components/HotelReservation/HotelCardListing/index.tsx
@@ -8,11 +8,14 @@ import HotelCard from "../HotelCard"
import styles from "./hotelCardListing.module.css"
-import { HotelCardListingProps } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
+import {
+ HotelCardListingProps,
+ HotelCardListingType,
+} from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
export default function HotelCardListing({
hotelData,
- type = "listing",
+ type = HotelCardListingType.PageListing,
}: HotelCardListingProps) {
const searchParams = useSearchParams()
diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx
index 700ffaa71..2f5d9cb0b 100644
--- a/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx
+++ b/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx
@@ -4,12 +4,16 @@ import HotelCardListing from "@/components/HotelReservation/HotelCardListing"
import styles from "./hotelListing.module.css"
+import { HotelCardListingType } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { HotelListingProps } from "@/types/components/hotelReservation/selectHotel/map"
export default function HotelListing({ hotels }: HotelListingProps) {
return (
-
+
)
}
diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx
index eadd5f461..82887ea02 100644
--- a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx
+++ b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx
@@ -72,6 +72,7 @@ export default function SelectHotelMap({
closeButton={closeButton}
coordinates={coordinates}
hotelPins={hotelPins}
+ hotels={hotels}
activeHotelPin={activeHotelPin}
onActiveHotelPinChange={setActiveHotelPin}
mapId={mapId}
diff --git a/components/Maps/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css b/components/Maps/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css
index 2729d5e79..359edad50 100644
--- a/components/Maps/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css
+++ b/components/Maps/InteractiveMap/HotelListingMapContent/hotelListingMapContent.module.css
@@ -4,10 +4,8 @@
}
.advancedMarker.active {
- height: var(--Spacing-x5);
- width: var(
- --Spacing-x5
- ) !important; /* Overwriting the default width of the @vis.gl/react-google-maps AdvancedMarker */
+ height: 32px;
+ min-width: 109px !important; /* Overwriting the default width of the @vis.gl/react-google-maps AdvancedMarker */
}
.pin {
@@ -23,10 +21,11 @@
background-color: var(--Base-Surface-Primary-light-Normal);
box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.1);
gap: var(--Spacing-x1);
+ width: max-content;
}
.pin.active {
- padding-right: var(--Spacing-x-one-and-half);
+ background-color: var(--Primary-Dark-Surface-Normal);
}
.pinLabel {
@@ -49,3 +48,22 @@
justify-content: center;
background: var(--Primary-Dark-Surface-Normal);
}
+
+.pin.active .pinIcon {
+ background: var(--Base-Surface-Primary-light-Normal);
+}
+
+.card {
+ display: none;
+ position: absolute;
+ bottom: 32px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 402px;
+ height: 181px;
+ background-color: var(--Base-Surface-Primary-light-Normal);
+}
+
+.card.active {
+ display: block;
+}
diff --git a/components/Maps/InteractiveMap/HotelListingMapContent/index.tsx b/components/Maps/InteractiveMap/HotelListingMapContent/index.tsx
index 82ba1bc4e..bec6498ca 100644
--- a/components/Maps/InteractiveMap/HotelListingMapContent/index.tsx
+++ b/components/Maps/InteractiveMap/HotelListingMapContent/index.tsx
@@ -3,21 +3,31 @@ import {
AdvancedMarkerAnchorPoint,
} from "@vis.gl/react-google-maps"
+import HotelCardDialog from "@/components/HotelReservation/HotelCardDialog"
import Body from "@/components/TempDesignSystem/Text/Body"
-import HotelMarker from "../../Markers/Hotel"
+import HotelMarker from "../../Markers/HotelMarker"
import styles from "./hotelListingMapContent.module.css"
+import { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
export default function HotelListingMapContent({
activeHotelPin,
hotelPins,
+ hotels,
+ onActiveHotelPinChange,
}: {
activeHotelPin?: HotelPin["name"] | null
hotelPins: HotelPin[]
+ hotels?: HotelData[]
+ onActiveHotelPinChange?: (pinName: string | null) => void
}) {
+ function toggleActiveHotelPin(pinName: string) {
+ onActiveHotelPinChange?.(activeHotelPin === pinName ? null : pinName)
+ }
+
return (
{hotelPins.map((pin) => (
@@ -27,16 +37,27 @@ export default function HotelListingMapContent({
position={pin.coordinates}
anchorPoint={AdvancedMarkerAnchorPoint.CENTER}
zIndex={activeHotelPin === pin.name ? 2 : 0}
+ onMouseEnter={() => onActiveHotelPinChange?.(pin.name)}
+ onMouseLeave={() => onActiveHotelPinChange?.(null)}
+ onClick={() => toggleActiveHotelPin(pin.name)}
>
+
+
-
+
-
+
- {pin.price} {pin.currency}
+ {pin.memberPrice} {pin.currency}
diff --git a/components/Maps/InteractiveMap/index.tsx b/components/Maps/InteractiveMap/index.tsx
index 7fef29ae1..01681c268 100644
--- a/components/Maps/InteractiveMap/index.tsx
+++ b/components/Maps/InteractiveMap/index.tsx
@@ -18,6 +18,7 @@ export default function InteractiveMap({
activePoi,
hotelPins,
activeHotelPin,
+ hotels,
mapId,
closeButton,
onActivePoiChange,
@@ -54,6 +55,8 @@ export default function InteractiveMap({
)}
{pointsOfInterest && (
diff --git a/components/Maps/Markers/HotelMarker/hotelMarker.module.css b/components/Maps/Markers/HotelMarker/hotelMarker.module.css
new file mode 100644
index 000000000..852c26f84
--- /dev/null
+++ b/components/Maps/Markers/HotelMarker/hotelMarker.module.css
@@ -0,0 +1,7 @@
+.white * {
+ fill: var(--Base-Surface-Primary-light-Normal);
+}
+
+.burgundy * {
+ fill: var(--Scandic-Brand-Burgundy);
+}
diff --git a/components/Maps/Markers/Hotel.tsx b/components/Maps/Markers/HotelMarker/index.tsx
similarity index 89%
rename from components/Maps/Markers/Hotel.tsx
rename to components/Maps/Markers/HotelMarker/index.tsx
index e18c07483..896e2716d 100644
--- a/components/Maps/Markers/Hotel.tsx
+++ b/components/Maps/Markers/HotelMarker/index.tsx
@@ -1,10 +1,17 @@
+import { hotelMarkerVariants } from "./variants"
+
export default function HotelMarker({
className,
+ color,
...props
-}: React.SVGAttributes) {
+}: React.SVGAttributes & {
+ color?: "burgundy" | "white"
+}) {
+ const classNames = hotelMarkerVariants({ color, className })
+
return (