diff --git a/components/HotelReservation/HotelCard/hotelCard.module.css b/components/HotelReservation/HotelCard/hotelCard.module.css index 0ffa5b150..587feb29a 100644 --- a/components/HotelReservation/HotelCard/hotelCard.module.css +++ b/components/HotelReservation/HotelCard/hotelCard.module.css @@ -14,15 +14,16 @@ .imageContainer { grid-area: image; + position: relative; + height: 100%; + width: 116px; } .tripAdvisor { display: none; } -.image { - height: 100%; - width: 116px; +.imageContainer img { object-fit: cover; } @@ -77,6 +78,8 @@ .imageContainer { position: relative; + min-height: 200px; + width: 518px; } .tripAdvisor { @@ -86,10 +89,6 @@ top: 7px; } - .image { - width: 518px; - } - .hotelInformation { padding-top: var(--Spacing-x2); padding-right: var(--Spacing-x2); diff --git a/components/HotelReservation/HotelCard/index.tsx b/components/HotelReservation/HotelCard/index.tsx index 67ce49f17..9300771e9 100644 --- a/components/HotelReservation/HotelCard/index.tsx +++ b/components/HotelReservation/HotelCard/index.tsx @@ -11,10 +11,11 @@ import Title from "@/components/TempDesignSystem/Text/Title" import { getIntl } from "@/i18n" import ReadMore from "../ReadMore" +import ImageGallery from "../SelectRate/ImageGallery" import styles from "./hotelCard.module.css" -import { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps" +import type { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps" export default async function HotelCard({ hotel }: HotelCardProps) { const intl = await getIntl() @@ -27,13 +28,15 @@ export default async function HotelCard({ hotel }: HotelCardProps) { return (
- {hotelData.hotelContent.images.metaData.altText} + {hotelData.gallery && ( + + )}
diff --git a/components/HotelReservation/SelectRate/HotelInfoCard/hotelInfoCard.module.css b/components/HotelReservation/SelectRate/HotelInfoCard/hotelInfoCard.module.css index 1482bf4c9..aacdf0449 100644 --- a/components/HotelReservation/SelectRate/HotelInfoCard/hotelInfoCard.module.css +++ b/components/HotelReservation/SelectRate/HotelInfoCard/hotelInfoCard.module.css @@ -12,10 +12,6 @@ gap: var(--Spacing-x2); } -.image { - border-radius: var(--Corner-radius-Medium); -} - .imageWrapper { position: relative; overflow: hidden; @@ -24,6 +20,10 @@ width: 100%; } +.imageWrapper img { + border-radius: var(--Corner-radius-Medium); +} + .tripAdvisor { display: flex; align-items: center; diff --git a/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx b/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx index 1ec58dd07..120c0385d 100644 --- a/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx +++ b/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx @@ -10,6 +10,7 @@ import Caption from "@/components/TempDesignSystem/Text/Caption" import Title from "@/components/TempDesignSystem/Text/Title" import ReadMore from "../../ReadMore" +import ImageGallery from "../ImageGallery" import styles from "./hotelInfoCard.module.css" @@ -28,12 +29,6 @@ export default function HotelInfoCard({ hotelData }: HotelInfoCardProps) { {hotelAttributes && (
- {hotelAttributes.hotelContent.images.metaData.altText} {hotelAttributes.ratings?.tripAdvisor && (
@@ -42,7 +37,15 @@ export default function HotelInfoCard({ hotelData }: HotelInfoCardProps) {
)} - {/* TODO: gallery icon and image carousel */} + {hotelAttributes.gallery && ( + + )}
diff --git a/components/HotelReservation/SelectRate/ImageGallery/imageGallery.module.css b/components/HotelReservation/SelectRate/ImageGallery/imageGallery.module.css new file mode 100644 index 000000000..5d156f77a --- /dev/null +++ b/components/HotelReservation/SelectRate/ImageGallery/imageGallery.module.css @@ -0,0 +1,17 @@ +.galleryIcon { + position: absolute; + bottom: 16px; + right: 16px; + max-height: 32px; + width: 48px; + background-color: rgba(0, 0, 0, 0.6); + padding: var(--Spacing-x-quarter) var(--Spacing-x-half); + border-radius: var(--Corner-radius-Small); + display: flex; + align-items: center; + gap: var(--Spacing-x-quarter); +} + +.triggerArea { + cursor: pointer; +} diff --git a/components/HotelReservation/SelectRate/ImageGallery/index.tsx b/components/HotelReservation/SelectRate/ImageGallery/index.tsx new file mode 100644 index 000000000..778c2d45e --- /dev/null +++ b/components/HotelReservation/SelectRate/ImageGallery/index.tsx @@ -0,0 +1,36 @@ +import { GalleryIcon } from "@/components/Icons" +import Image from "@/components/Image" +import Lightbox from "@/components/Lightbox" +import Footnote from "@/components/TempDesignSystem/Text/Footnote" + +import styles from "./imageGallery.module.css" + +import type { ImageGalleryProps } from "@/types/components/hotelReservation/selectRate/imageGallery" + +export default function ImageGallery({ images, title }: ImageGalleryProps) { + return ( + ({ + url: image.imageSizes.small, + alt: image.metaData.altText, + title: image.metaData.title, + }))} + dialogTitle={title} + > +
+ {images[0].metaData.altText} +
+ + + {images.length} + +
+
+
+ ) +} diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx index 87b0143b5..444968ce1 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx @@ -5,18 +5,18 @@ import { useIntl } from "react-intl" import { RateDefinition } from "@/server/routers/hotels/output" import FlexibilityOption from "@/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption" -import { ChevronRightSmallIcon, GalleryIcon } from "@/components/Icons" -import Image from "@/components/Image" -import Lightbox from "@/components/Lightbox" +import { ChevronRightSmallIcon } from "@/components/Icons" import Button from "@/components/TempDesignSystem/Button" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" import Footnote from "@/components/TempDesignSystem/Text/Footnote" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import ImageGallery from "../../ImageGallery" + import styles from "./roomCard.module.css" -import { RoomCardProps } from "@/types/components/hotelReservation/selectRate/roomCard" +import type { RoomCardProps } from "@/types/components/hotelReservation/selectRate/roomCard" export default function RoomCard({ rateDefinitions, @@ -25,7 +25,6 @@ export default function RoomCard({ handleSelectRate, }: RoomCardProps) { const intl = useIntl() - const saveRate = rateDefinitions.find( // TODO: Update string when API has decided (rate) => rate.cancellationRule === "NonCancellable" @@ -153,26 +152,8 @@ export default function RoomCard({ )} {/*NOTE: images from the test API are hosted on test3.scandichotels.com, which can't be accessed unless on Scandic's Wifi or using Citrix. */} - {mainImage.metaData.altText} {images && ( - ({ - url: image.imageSizes.small, - alt: image.metaData.altText, - title: image.metaData.title, - }))} - dialogTitle={roomConfiguration.roomType} - > -
- - {images.length} -
-
+ )}
)} diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css index 25add23b5..ef5d9b8fc 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css @@ -77,17 +77,3 @@ min-height: 185px; position: relative; } - -.galleryIcon { - position: absolute; - bottom: 16px; - right: 16px; - height: 24px; - background-color: rgba(64, 57, 55, 0.9); - padding: 0 var(--Spacing-x-half); - border-radius: var(--Corner-radius-Small); - cursor: pointer; - display: flex; - align-items: center; - gap: var(--Spacing-x-quarter); -} diff --git a/server/routers/hotels/output.ts b/server/routers/hotels/output.ts index 803ae012f..0f545d673 100644 --- a/server/routers/hotels/output.ts +++ b/server/routers/hotels/output.ts @@ -162,6 +162,21 @@ export const facilitySchema = z.object({ ), }) +export const gallerySchema = z.object({ + heroImages: z.array( + z.object({ + metaData: imageMetaDataSchema, + imageSizes: imageSizesSchema, + }) + ), + smallerImages: z.array( + z.object({ + metaData: imageMetaDataSchema, + imageSizes: imageSizesSchema, + }) + ), +}) + const healthFacilitySchema = z.object({ type: z.string(), content: z.object({ @@ -441,6 +456,7 @@ export const getHotelDataSchema = z.object({ conferencesAndMeetings: facilitySchema.optional(), healthAndWellness: facilitySchema.optional(), restaurantImages: facilitySchema.optional(), + gallery: gallerySchema.optional(), }), relationships: relationshipsSchema, }), diff --git a/types/components/hotelReservation/selectRate/imageGallery.ts b/types/components/hotelReservation/selectRate/imageGallery.ts new file mode 100644 index 000000000..333ff2d94 --- /dev/null +++ b/types/components/hotelReservation/selectRate/imageGallery.ts @@ -0,0 +1,3 @@ +import type { GalleryImages } from "@/types/hotel" + +export type ImageGalleryProps = { images: GalleryImages; title: string } diff --git a/types/hotel.ts b/types/hotel.ts index a60204720..972c6459e 100644 --- a/types/hotel.ts +++ b/types/hotel.ts @@ -2,6 +2,7 @@ import { z } from "zod" import { facilitySchema, + gallerySchema, getHotelDataSchema, parkingSchema, pointOfInterestSchema, @@ -13,7 +14,6 @@ export type HotelData = z.infer export type Hotel = HotelData["data"]["attributes"] export type HotelAddress = HotelData["data"]["attributes"]["address"] export type HotelLocation = HotelData["data"]["attributes"]["location"] - export type Amenities = HotelData["data"]["attributes"]["detailedFacilities"] type HotelRatings = HotelData["data"]["attributes"]["ratings"] @@ -22,6 +22,8 @@ export type HotelTripAdvisor = | undefined export type RoomData = z.infer +export type GallerySchema = z.infer +export type GalleryImages = GallerySchema["heroImages"] export type PointOfInterest = z.output