diff --git a/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx index ea32a277c..f7cc836ea 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx @@ -1,20 +1,8 @@ -import { Suspense } from "react" - import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests" -import Header from "@/components/HotelReservation/BookingConfirmation/Header" -import HotelDetails from "@/components/HotelReservation/BookingConfirmation/HotelDetails" -import PaymentDetails from "@/components/HotelReservation/BookingConfirmation/PaymentDetails" -import Promos from "@/components/HotelReservation/BookingConfirmation/Promos" -import Receipt from "@/components/HotelReservation/BookingConfirmation/Receipt" -import Rooms from "@/components/HotelReservation/BookingConfirmation/Rooms" -import SidePanel from "@/components/HotelReservation/SidePanel" -import LoadingSpinner from "@/components/LoadingSpinner" -import Divider from "@/components/TempDesignSystem/Divider" +import BookingConfirmation from "@/components/HotelReservation/BookingConfirmation" import { setLang } from "@/i18n/serverContext" -import styles from "./page.module.css" - import type { LangParams, PageArgs } from "@/types/params" export default async function BookingConfirmationPage({ @@ -22,29 +10,12 @@ export default async function BookingConfirmationPage({ searchParams, }: PageArgs) { setLang(params.lang) - void getBookingConfirmation(searchParams.confirmationNumber) + const bookingConfirmationPromise = getBookingConfirmation( + searchParams.confirmationNumber + ) return ( -
- }> -
-
- - - - - -
- -
-
- - -
+ ) } diff --git a/app/api/web/revalidate/route.ts b/app/api/web/revalidate/route.ts index 42baad8d6..63a7b157b 100644 --- a/app/api/web/revalidate/route.ts +++ b/app/api/web/revalidate/route.ts @@ -73,6 +73,10 @@ export async function POST(request: NextRequest) { const entryLocale = entry.publish_details?.locale ?? entry.locale const refsTag = generateRefsResponseTag(entryLocale, entry.uid) + const contentEntryTag = generateRefsResponseTag( + entryLocale, + content_type.uid + ) const refTag = generateRefTag(entryLocale, content_type.uid, entry.uid) const tag = generateTag(entryLocale, entry.uid) const languageSwitcherTag = generateTag( @@ -97,6 +101,9 @@ export async function POST(request: NextRequest) { console.info(`Revalidating metadataTag: ${metadataTag}`) revalidateTag(metadataTag) + console.info(`Revalidating contentEntryTag: ${contentEntryTag}`) + revalidateTag(contentEntryTag) + if (entry.breadcrumbs) { const breadcrumbsRefsTag = generateRefsResponseTag( entryLocale, diff --git a/app/globals.css b/app/globals.css index a2d667892..6e2529da2 100644 --- a/app/globals.css +++ b/app/globals.css @@ -102,7 +102,7 @@ --max-width: 94.5rem; --max-width-content: 74.75rem; --max-width-text-block: 49.5rem; - --current-mobile-site-header-height: 70.047px; + --current-mobile-site-header-height: 52.41px; --max-width-navigation: 89.5rem; --max-width-spacing: calc(var(--Layout-Mobile-Margin-Margin-min) * 2); diff --git a/components/ContentType/HotelPage/Facilities/CardGrid/ActivitiesCardGrid.tsx b/components/ContentType/HotelPage/Facilities/CardGrid/ActivitiesCardGrid.tsx index c1bf12c31..dd865227e 100644 --- a/components/ContentType/HotelPage/Facilities/CardGrid/ActivitiesCardGrid.tsx +++ b/components/ContentType/HotelPage/Facilities/CardGrid/ActivitiesCardGrid.tsx @@ -20,7 +20,7 @@ export default function ActivitiesCardGrid(activitiesCard: ActivityCard) { theme: hasImage ? "image" : "primaryDark", primaryButton: hasImage ? { - href: activitiesCard.contentPage.href, + href: `?s=${activities[lang]}`, title: activitiesCard.ctaText, isExternal: false, } @@ -28,7 +28,7 @@ export default function ActivitiesCardGrid(activitiesCard: ActivityCard) { secondaryButton: hasImage ? undefined : { - href: activitiesCard.contentPage.href, + href: `?s=${activities[lang]}`, title: activitiesCard.ctaText, isExternal: false, }, diff --git a/components/ContentType/HotelPage/SidePeeks/Activities/activities.module.css b/components/ContentType/HotelPage/SidePeeks/Activities/activities.module.css new file mode 100644 index 000000000..87cb2cdc0 --- /dev/null +++ b/components/ContentType/HotelPage/SidePeeks/Activities/activities.module.css @@ -0,0 +1,9 @@ +.buttonContainer { + background-color: var(--Base-Background-Primary-Normal); + border-top: 1px solid var(--Base-Border-Subtle); + padding: var(--Spacing-x4) var(--Spacing-x2); + width: 100%; + position: absolute; + left: 0; + bottom: 0; +} diff --git a/components/ContentType/HotelPage/SidePeeks/Activities/index.tsx b/components/ContentType/HotelPage/SidePeeks/Activities/index.tsx new file mode 100644 index 000000000..573cdfc8e --- /dev/null +++ b/components/ContentType/HotelPage/SidePeeks/Activities/index.tsx @@ -0,0 +1,35 @@ +import { activities } from "@/constants/routes/hotelPageParams" + +import Button from "@/components/TempDesignSystem/Button" +import Link from "@/components/TempDesignSystem/Link" +import SidePeek from "@/components/TempDesignSystem/SidePeek" +import Preamble from "@/components/TempDesignSystem/Text/Preamble" +import { getIntl } from "@/i18n" +import { getLang } from "@/i18n/serverContext" + +import styles from "./activities.module.css" + +import type { ActivitiesSidePeekProps } from "@/types/components/hotelPage/sidepeek/activities" + +export default async function ActivitiesSidePeek({ + contentPage, +}: ActivitiesSidePeekProps) { + const lang = getLang() + const intl = await getIntl() + const { href, preamble } = contentPage + return ( + + {preamble} +
+ +
+
+ ) +} diff --git a/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/ParkingPrices/index.tsx b/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/ParkingPrices/index.tsx index b524c9896..3ca2bb527 100644 --- a/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/ParkingPrices/index.tsx +++ b/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/ParkingPrices/index.tsx @@ -9,7 +9,7 @@ import { } from "@/types/components/hotelPage/sidepeek/parking" export default async function ParkingPrices({ - data, + pricing, currency, freeParking, }: ParkingPricesProps) { @@ -31,7 +31,7 @@ export default async function ParkingPrices({ } } - const filteredPeriods = data?.filter((filter) => filter.period !== "Hour") + const filteredPeriods = pricing?.filter((filter) => filter.period !== "Hour") return (
diff --git a/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/index.tsx b/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/index.tsx index d706f03a8..697527048 100644 --- a/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/index.tsx +++ b/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/index.tsx @@ -1,5 +1,8 @@ +import { ExternalLinkIcon } from "@/components/Icons" import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem" +import Button from "@/components/TempDesignSystem/Button" import Divider from "@/components/TempDesignSystem/Divider" +import Link from "@/components/TempDesignSystem/Link" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" import { getIntl } from "@/i18n" @@ -12,7 +15,10 @@ import styles from "./parkingAmenity.module.css" import type { ParkingAmenityProps } from "@/types/components/hotelPage/sidepeek/parking" import { IconName } from "@/types/components/icon" -export default async function ParkingAmenity({ parking }: ParkingAmenityProps) { +export default async function ParkingAmenity({ + parking, + hasParkingPage, +}: ParkingAmenityProps) { const intl = await getIntl() return ( @@ -43,7 +49,7 @@ export default async function ParkingAmenity({ parking }: ParkingAmenityProps) { @@ -54,15 +60,41 @@ export default async function ParkingAmenity({ parking }: ParkingAmenityProps) {
+ {data.externalParkingUrl && ( + + )} ))} + {hasParkingPage && ( + + )} ) } diff --git a/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/parkingAmenity.module.css b/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/parkingAmenity.module.css index 7535e3543..b5fccc6cf 100644 --- a/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/parkingAmenity.module.css +++ b/components/ContentType/HotelPage/SidePeeks/Amenities/AccordionAmenities/Parking/parkingAmenity.module.css @@ -1,9 +1,9 @@ -.wrapper { +.wrapper, +.information { display: grid; gap: var(--Spacing-x3); } -.information, .list, .prices { display: grid; @@ -18,3 +18,7 @@ display: grid; gap: var(--Spacing-x1); } + +.parkingPageLink { + margin-top: var(--Spacing-x2); +} diff --git a/components/ContentType/HotelPage/SidePeeks/MeetingsAndConferences/index.tsx b/components/ContentType/HotelPage/SidePeeks/MeetingsAndConferences/index.tsx new file mode 100644 index 000000000..f1a1c5101 --- /dev/null +++ b/components/ContentType/HotelPage/SidePeeks/MeetingsAndConferences/index.tsx @@ -0,0 +1,80 @@ +import { meetingsAndConferences } from "@/constants/routes/hotelPageParams" + +import Image from "@/components/Image" +import Button from "@/components/TempDesignSystem/Button" +import Link from "@/components/TempDesignSystem/Link" +import SidePeek from "@/components/TempDesignSystem/SidePeek" +import Body from "@/components/TempDesignSystem/Text/Body" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import Title from "@/components/TempDesignSystem/Text/Title" +import { getIntl } from "@/i18n" +import { getLang } from "@/i18n/serverContext" + +import styles from "./meetingsAndConferences.module.css" + +import type { MeetingsAndConferencesSidePeekProps } from "@/types/components/hotelPage/sidepeek/meetingsAndConferences" + +export default async function MeetingsAndConferencesSidePeek({ + meetingFacilities, + descriptions, + link, +}: MeetingsAndConferencesSidePeekProps) { + const lang = getLang() + const intl = await getIntl() + const fallbackAlt = intl.formatMessage({ id: "Creative spaces for meetings" }) + + const primaryImage = meetingFacilities?.heroImages[0]?.imageSizes.medium + const primaryAltText = + meetingFacilities?.heroImages[0]?.metaData.altText || fallbackAlt + + const secondaryImage = meetingFacilities?.heroImages[1]?.imageSizes.medium + const secondaryAltText = + meetingFacilities?.heroImages[1]?.metaData.altText || fallbackAlt + + return ( + +
+ + + {intl.formatMessage({ id: "Creative spaces for meetings" })} + + + {primaryImage && ( +
+ {primaryAltText} + {secondaryImage && ( + {secondaryAltText} + )} +
+ )} + {descriptions?.medium && ( + {descriptions.medium} + )} + {link && ( +
+ +
+ )} +
+
+ ) +} diff --git a/components/ContentType/HotelPage/SidePeeks/MeetingsAndConferences/meetingsAndConferences.module.css b/components/ContentType/HotelPage/SidePeeks/MeetingsAndConferences/meetingsAndConferences.module.css new file mode 100644 index 000000000..ab19b9748 --- /dev/null +++ b/components/ContentType/HotelPage/SidePeeks/MeetingsAndConferences/meetingsAndConferences.module.css @@ -0,0 +1,44 @@ +.wrapper { + display: grid; + gap: var(--Spacing-x3); + margin-bottom: calc( + var(--Spacing-x4) * 2 + 80px + ); /* Creates space between the wrapper and buttonContainer */ +} + +.image { + width: 100%; + height: 300px; + object-fit: cover; + border-radius: var(--Corner-radius-Medium); +} + +.secondaryImage { + display: none; +} + +.buttonContainer { + background-color: var(--Base-Background-Primary-Normal); + border-top: 1px solid var(--Base-Border-Subtle); + padding: var(--Spacing-x4) var(--Spacing-x2); + width: 100%; + position: absolute; + left: 0; + bottom: 0; +} + +@media screen and (min-width: 768px) { + .imageContainer { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--Spacing-x2); + } + + .image { + height: 240px; + } + + .secondaryImage { + display: block; + } +} diff --git a/components/ContentType/HotelPage/SidePeeks/index.ts b/components/ContentType/HotelPage/SidePeeks/index.ts index 7eff75db2..f8de0f861 100644 --- a/components/ContentType/HotelPage/SidePeeks/index.ts +++ b/components/ContentType/HotelPage/SidePeeks/index.ts @@ -1,4 +1,6 @@ export { default as AboutTheHotelSidePeek } from "./AboutTheHotel" +export { default as ActivitiesSidePeek } from "./Activities" export { default as AmenitiesSidePeek } from "./Amenities" +export { default as MeetingsAndConferencesSidePeek } from "./MeetingsAndConferences" export { default as RoomSidePeek } from "./Room" export { default as WellnessAndExerciseSidePeek } from "./WellnessAndExercise" diff --git a/components/ContentType/HotelPage/index.tsx b/components/ContentType/HotelPage/index.tsx index 8910a7cd8..38002af81 100644 --- a/components/ContentType/HotelPage/index.tsx +++ b/components/ContentType/HotelPage/index.tsx @@ -1,10 +1,6 @@ import { notFound } from "next/navigation" -import { - activities, - meetingsAndConferences, - restaurantAndBar, -} from "@/constants/routes/hotelPageParams" +import { restaurantAndBar } from "@/constants/routes/hotelPageParams" import { env } from "@/env/server" import { getHotelData, getHotelPage } from "@/lib/trpc/memoizedRequests" @@ -29,7 +25,9 @@ import PreviewImages from "./PreviewImages" import { Rooms } from "./Rooms" import { AboutTheHotelSidePeek, + ActivitiesSidePeek, AmenitiesSidePeek, + MeetingsAndConferencesSidePeek, RoomSidePeek, WellnessAndExerciseSidePeek, } from "./SidePeeks" @@ -200,20 +198,13 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { Restaurant & Bar - - {/* TODO */} - Activities - - - {/* TODO */} - Meetings & Conferences - + {activitiesCard && ( + + )} + {roomCategories.map((room) => ( ))} diff --git a/components/Current/Header/BookingButton/bookingButton.module.css b/components/Current/Header/BookingButton/bookingButton.module.css index 797cd377b..7276221ae 100644 --- a/components/Current/Header/BookingButton/bookingButton.module.css +++ b/components/Current/Header/BookingButton/bookingButton.module.css @@ -6,7 +6,7 @@ line-height: 20px; border: 1px solid transparent; border-radius: 50px; - height: 32px; + height: 38px; line-height: 20px; font-size: 14px; font-family: Helvetica, Arial, sans-serif; @@ -17,6 +17,7 @@ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; + align-content: center; } .button:hover { diff --git a/components/Current/Header/HeaderFallback/index.tsx b/components/Current/Header/HeaderFallback/index.tsx index 7b6801a19..12ef4b9f7 100644 --- a/components/Current/Header/HeaderFallback/index.tsx +++ b/components/Current/Header/HeaderFallback/index.tsx @@ -1,49 +1,13 @@ -import { homeHrefs } from "@/constants/homeHrefs" -import { env } from "@/env/server" -import { getCurrentHeader } from "@/lib/trpc/memoizedRequests" - -import { getLang } from "@/i18n/serverContext" - -import { MainMenu } from "../MainMenu" -import OfflineBanner from "../OfflineBanner" -import TopMenu from "../TopMenu" +import { MainMenuSkeleton } from "../MainMenu" +import { TopMenuSkeleton } from "../TopMenu" import styles from "../header.module.css" export default async function HeaderFallback() { - const data = await getCurrentHeader(getLang()) - - if (!data?.header) { - return null - } - - const homeHref = homeHrefs[env.NODE_ENV][getLang()] - const { frontpageLinkText, logo, menu, topMenu } = data.header - - const topMenuMobileLinks = topMenu.links - .filter((link) => link.show_on_mobile) - .sort((a, b) => (a.sort_order_mobile < b.sort_order_mobile ? 1 : -1)) - return (
- - - + +
) } diff --git a/components/Current/Header/MainMenu/index.tsx b/components/Current/Header/MainMenu/index.tsx index 98ed2f19e..ac199287d 100644 --- a/components/Current/Header/MainMenu/index.tsx +++ b/components/Current/Header/MainMenu/index.tsx @@ -9,6 +9,7 @@ import useDropdownStore from "@/stores/main-menu" import Image from "@/components/Image" import LoginButton from "@/components/LoginButton" import Avatar from "@/components/MyPages/Avatar" +import SkeletonShimmer from "@/components/SkeletonShimmer" import Link from "@/components/TempDesignSystem/Link" import useLang from "@/hooks/useLang" import { trackClick } from "@/utils/tracking" @@ -227,3 +228,56 @@ export function MainMenu({ ) } + +export function MainMenuSkeleton() { + const intl = useIntl() + + const links = new Array(5).fill("") + return ( +
+
+ + +
+
+ ) +} diff --git a/components/Current/Header/MainMenu/mainMenu.module.css b/components/Current/Header/MainMenu/mainMenu.module.css index 0e19f88cf..943a41bbe 100644 --- a/components/Current/Header/MainMenu/mainMenu.module.css +++ b/components/Current/Header/MainMenu/mainMenu.module.css @@ -24,11 +24,9 @@ .navBar { display: grid; grid-template-columns: 1fr 80px 1fr; - grid-template-columns: auto auto 1fr auto; grid-template-areas: "expanderBtn logoLink . buttonContainer"; grid-template-rows: 100%; height: 100%; - padding: 0 var(--Spacing-x2); } .expanderBtn { @@ -47,7 +45,7 @@ background: #757575; border-radius: 2.3px; display: inline-block; - height: 3px; + height: 5px; position: relative; transition: 0.3s; width: 32px; @@ -104,7 +102,6 @@ align-items: center; height: 100%; width: 80px; - padding-left: var(--Spacing-x1); } .logo { @@ -238,6 +235,12 @@ display: none; } +.skeletonWrapper { + padding: 4px 10px; + height: 100%; + align-content: center; +} + @media (min-width: 1367px) { .navBar { grid-template-columns: 140px auto 1fr; diff --git a/components/Current/Header/TopMenu/index.tsx b/components/Current/Header/TopMenu/index.tsx index b33c44424..8f340e56b 100644 --- a/components/Current/Header/TopMenu/index.tsx +++ b/components/Current/Header/TopMenu/index.tsx @@ -3,6 +3,7 @@ import { overview } from "@/constants/routes/myPages" import { getName } from "@/lib/trpc/memoizedRequests" import LoginButton from "@/components/LoginButton" +import SkeletonShimmer from "@/components/SkeletonShimmer" import Link from "@/components/TempDesignSystem/Link" import { getIntl } from "@/i18n" import { getLang } from "@/i18n/serverContext" @@ -68,6 +69,8 @@ export default async function TopMenu({ position="hamburger menu" trackingId="loginStartTopMenu" className={`${styles.sessionLink} ${styles.loginLink}`} + variant="default" + size="small" > {intl.formatMessage({ id: "Log in" })} @@ -78,3 +81,32 @@ export default async function TopMenu({ ) } + +export async function TopMenuSkeleton() { + const intl = await getIntl() + const links = new Array(5).fill("") + return ( +
+
+
    + {links.map((link, i) => ( +
  • + +
  • + ))} +
  • + + {intl.formatMessage({ id: "Log in" })} + +
  • +
+
+
+ ) +} diff --git a/components/Current/Header/TopMenu/topMenu.module.css b/components/Current/Header/TopMenu/topMenu.module.css index 67be14a58..ab8c0733c 100644 --- a/components/Current/Header/TopMenu/topMenu.module.css +++ b/components/Current/Header/TopMenu/topMenu.module.css @@ -49,6 +49,12 @@ display: block; } +.skeletonWrapper { + padding: 4px 10px; + height: 30px; + align-content: center; +} + @media screen and (min-width: 768px) { .container { padding: 0 30px; diff --git a/components/DatePicker/Screen/mobile.module.css b/components/DatePicker/Screen/mobile.module.css index 4fba31592..d26ed3423 100644 --- a/components/DatePicker/Screen/mobile.module.css +++ b/components/DatePicker/Screen/mobile.module.css @@ -159,13 +159,13 @@ td.day[data-outside="true"] ~ td.day[data-disabled="true"] button.dayButton, } .weekDay { - color: var(--Base-Text-Medium-contrast); - font-family: var(--typography-Footnote-Labels-fontFamily); - font-size: var(--typography-Footnote-Labels-fontSize); - font-weight: var(--typography-Footnote-Labels-fontWeight); - letter-spacing: var(--typography-Footnote-Labels-letterSpacing); - line-height: var(--typography-Footnote-Labels-lineHeight); - text-decoration: var(--typography-Footnote-Labels-textDecoration); + color: var(--UI-Text-Placeholder); + font-family: var(--typography-Caption-Labels-fontFamily); + font-size: var(--typography-Caption-Labels-fontSize); + font-weight: var(--typography-Caption-Labels-fontWeight); + letter-spacing: var(--typography-Caption-Labels-letterSpacing); + line-height: var(--typography-Caption-Labels-lineHeight); + text-decoration: var(--typography-Caption-Labels-textDecoration); text-transform: uppercase; } diff --git a/components/Header/MainMenu/index.tsx b/components/Header/MainMenu/index.tsx index e1be0051f..9119ecb5e 100644 --- a/components/Header/MainMenu/index.tsx +++ b/components/Header/MainMenu/index.tsx @@ -56,6 +56,7 @@ function Logo({ alt }: { alt: string }) { className={styles.logo} height={22} src="/_static/img/scandic-logotype.svg" + priority width={103} /> diff --git a/components/HotelReservation/BookingConfirmation/Header/Actions/DownloadInvoice.tsx b/components/HotelReservation/BookingConfirmation/Header/Actions/DownloadInvoice.tsx index 3dea1f011..9fe883683 100644 --- a/components/HotelReservation/BookingConfirmation/Header/Actions/DownloadInvoice.tsx +++ b/components/HotelReservation/BookingConfirmation/Header/Actions/DownloadInvoice.tsx @@ -1,14 +1,18 @@ "use client" import { useIntl } from "react-intl" +import { useReactToPrint } from "react-to-print" import { DownloadIcon } from "@/components/Icons" import Button from "@/components/TempDesignSystem/Button" -export default function DownloadInvoice() { +import type { DownloadInvoiceProps } from "@/types/components/hotelReservation/bookingConfirmation/actions/downloadInvoice" + +export default function DownloadInvoice({ mainRef }: DownloadInvoiceProps) { const intl = useIntl() + const reactToPrintFn = useReactToPrint({ contentRef: mainRef }) function downloadBooking() { - window.print() + reactToPrintFn() } return ( diff --git a/components/HotelReservation/BookingConfirmation/Header/index.tsx b/components/HotelReservation/BookingConfirmation/Header/index.tsx index 6cb144202..0d2d08f8b 100644 --- a/components/HotelReservation/BookingConfirmation/Header/index.tsx +++ b/components/HotelReservation/BookingConfirmation/Header/index.tsx @@ -1,9 +1,9 @@ -import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests" +"use client" +import { useIntl } from "react-intl" import Link from "@/components/TempDesignSystem/Link" import Body from "@/components/TempDesignSystem/Text/Body" import Title from "@/components/TempDesignSystem/Text/Title" -import { getIntl } from "@/i18n" import AddToCalendar from "./Actions/AddToCalendar" import DownloadInvoice from "./Actions/DownloadInvoice" @@ -14,13 +14,14 @@ import styles from "./header.module.css" import type { EventAttributes } from "ics" -import type { BookingConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation" +import type { BookingConfirmationHeaderProps } from "@/types/components/hotelReservation/bookingConfirmation/header" -export default async function Header({ - confirmationNumber, -}: BookingConfirmationProps) { - const intl = await getIntl() - const { booking, hotel } = await getBookingConfirmation(confirmationNumber) +export default function Header({ + booking, + hotel, + mainRef, +}: BookingConfirmationHeaderProps) { + const intl = useIntl() const text = intl.formatMessage( { id: "booking.confirmation.text" }, @@ -70,7 +71,7 @@ export default async function Header({ hotelName={hotel.name} /> - + ) diff --git a/components/HotelReservation/BookingConfirmation/HotelDetails/index.tsx b/components/HotelReservation/BookingConfirmation/HotelDetails/index.tsx index dcef584a5..0c1b1dd06 100644 --- a/components/HotelReservation/BookingConfirmation/HotelDetails/index.tsx +++ b/components/HotelReservation/BookingConfirmation/HotelDetails/index.tsx @@ -1,20 +1,19 @@ -import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests" +"use client" +import { useIntl } from "react-intl" import Link from "@/components/TempDesignSystem/Link" import Body from "@/components/TempDesignSystem/Text/Body" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import { Toast } from "@/components/TempDesignSystem/Toasts" -import { getIntl } from "@/i18n" import styles from "./hotelDetails.module.css" -import type { BookingConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation" +import type { BookingConfirmationHotelDetailsProps } from "@/types/components/hotelReservation/bookingConfirmation/hotelDetails" -export default async function HotelDetails({ - confirmationNumber, -}: BookingConfirmationProps) { - const intl = await getIntl() - const { hotel } = await getBookingConfirmation(confirmationNumber) +export default function HotelDetails({ + hotel, +}: BookingConfirmationHotelDetailsProps) { + const intl = useIntl() return (
diff --git a/components/HotelReservation/BookingConfirmation/PaymentDetails/index.tsx b/components/HotelReservation/BookingConfirmation/PaymentDetails/index.tsx index 67f327455..500c7ed74 100644 --- a/components/HotelReservation/BookingConfirmation/PaymentDetails/index.tsx +++ b/components/HotelReservation/BookingConfirmation/PaymentDetails/index.tsx @@ -1,23 +1,23 @@ +"use client" +import { useIntl } from "react-intl" + import { dt } from "@/lib/dt" -import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests" import { CreditCardAddIcon } from "@/components/Icons" import Button from "@/components/TempDesignSystem/Button" import Body from "@/components/TempDesignSystem/Text/Body" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" -import { getIntl } from "@/i18n" -import { getLang } from "@/i18n/serverContext" +import useLang from "@/hooks/useLang" import styles from "./paymentDetails.module.css" -import type { BookingConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation" +import type { BookingConfirmationPaymentDetailsProps } from "@/types/components/hotelReservation/bookingConfirmation/paymentDetails" -export default async function PaymentDetails({ - confirmationNumber, -}: BookingConfirmationProps) { - const intl = await getIntl() - const lang = getLang() - const { booking } = await getBookingConfirmation(confirmationNumber) +export default function PaymentDetails({ + booking, +}: BookingConfirmationPaymentDetailsProps) { + const intl = useIntl() + const lang = useLang() return (
diff --git a/components/HotelReservation/BookingConfirmation/Promos/index.tsx b/components/HotelReservation/BookingConfirmation/Promos/index.tsx index d0692f917..4cf6d9076 100644 --- a/components/HotelReservation/BookingConfirmation/Promos/index.tsx +++ b/components/HotelReservation/BookingConfirmation/Promos/index.tsx @@ -1,11 +1,12 @@ -import { getIntl } from "@/i18n" +"use client" +import { useIntl } from "react-intl" import Promo from "./Promo" import styles from "./promos.module.css" -export default async function Promos() { - const intl = await getIntl() +export default function Promos() { + const intl = useIntl() return (
{intl.formatMessage({ id: "Summary" })}
- {roomAndBed.name} + {room.name} {booking.rateDefinition.isMemberRate ? (
@@ -82,9 +81,7 @@ export default async function Receipt({
- - {roomAndBed.bedType.description} - + {room.bedType.description} {intl.formatNumber(0, { currency: booking.currencyCode, diff --git a/components/HotelReservation/BookingConfirmation/Rooms/Room/index.tsx b/components/HotelReservation/BookingConfirmation/Rooms/Room/index.tsx index e721c3d8c..3d81e9511 100644 --- a/components/HotelReservation/BookingConfirmation/Rooms/Room/index.tsx +++ b/components/HotelReservation/BookingConfirmation/Rooms/Room/index.tsx @@ -1,3 +1,6 @@ +"use client" +import { useIntl } from "react-intl" + import { dt } from "@/lib/dt" import { @@ -10,16 +13,15 @@ import Link from "@/components/TempDesignSystem/Link" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" -import { getIntl } from "@/i18n" -import { getLang } from "@/i18n/serverContext" +import useLang from "@/hooks/useLang" import styles from "./room.module.css" -import type { RoomProps } from "@/types/components/hotelReservation/bookingConfirmation/room" +import type { RoomProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/room" -export default async function Room({ booking, img, roomName }: RoomProps) { - const intl = await getIntl() - const lang = getLang() +export default function Room({ booking, img, roomName }: RoomProps) { + const intl = useIntl() + const lang = useLang() const fromDate = dt(booking.checkInDate).locale(lang) const toDate = dt(booking.checkOutDate).locale(lang) diff --git a/components/HotelReservation/BookingConfirmation/Rooms/index.tsx b/components/HotelReservation/BookingConfirmation/Rooms/index.tsx index fdc973971..19954aec7 100644 --- a/components/HotelReservation/BookingConfirmation/Rooms/index.tsx +++ b/components/HotelReservation/BookingConfirmation/Rooms/index.tsx @@ -1,30 +1,23 @@ +"use client" + import { notFound } from "next/navigation" -import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests" - -import { getBookedHotelRoom } from "@/utils/getBookedHotelRoom" - import Room from "./Room" import styles from "./rooms.module.css" -import type { BookingConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation" +import type { BookingConfirmationRoomsProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms" -export default async function Rooms({ - confirmationNumber, -}: BookingConfirmationProps) { - const { booking, hotel } = await getBookingConfirmation(confirmationNumber) - const roomAndBed = getBookedHotelRoom(hotel, booking.roomTypeCode ?? "") - if (!roomAndBed) { +export default function Rooms({ + booking, + room, +}: BookingConfirmationRoomsProps) { + if (!room) { return notFound() } return (
- +
) } diff --git a/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.module.css b/components/HotelReservation/BookingConfirmation/confirmation.module.css similarity index 99% rename from app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.module.css rename to components/HotelReservation/BookingConfirmation/confirmation.module.css index 341c3b979..bba79b2d0 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.module.css +++ b/components/HotelReservation/BookingConfirmation/confirmation.module.css @@ -39,4 +39,4 @@ display: grid; grid-area: receipt; } -} \ No newline at end of file +} diff --git a/components/HotelReservation/BookingConfirmation/index.tsx b/components/HotelReservation/BookingConfirmation/index.tsx new file mode 100644 index 000000000..c97da8908 --- /dev/null +++ b/components/HotelReservation/BookingConfirmation/index.tsx @@ -0,0 +1,57 @@ +"use client" +import { use, useRef } from "react" + +import Header from "@/components/HotelReservation/BookingConfirmation/Header" +import HotelDetails from "@/components/HotelReservation/BookingConfirmation/HotelDetails" +import PaymentDetails from "@/components/HotelReservation/BookingConfirmation/PaymentDetails" +import Promos from "@/components/HotelReservation/BookingConfirmation/Promos" +import Receipt from "@/components/HotelReservation/BookingConfirmation/Receipt" +import Rooms from "@/components/HotelReservation/BookingConfirmation/Rooms" +import SidePanel from "@/components/HotelReservation/SidePanel" +import Divider from "@/components/TempDesignSystem/Divider" + +import styles from "./confirmation.module.css" + +import type { BookingConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation" + +export default function BookingConfirmation({ + bookingConfirmationPromise, +}: BookingConfirmationProps) { + const bookingConfirmation = use(bookingConfirmationPromise) + const mainRef = useRef(null) + return ( +
+
+
+ + + + + +
+ +
+
+ +
+ ) +} diff --git a/components/HotelReservation/Contact/contact.module.css b/components/HotelReservation/Contact/contact.module.css index e35862fed..01451a32f 100644 --- a/components/HotelReservation/Contact/contact.module.css +++ b/components/HotelReservation/Contact/contact.module.css @@ -4,6 +4,7 @@ grid-template-rows: auto; gap: var(--Spacing-x2); font-family: var(--typography-Body-Regular-fontFamily); + margin-bottom: var(--Spacing-x3); } .address, @@ -20,6 +21,7 @@ list-style-type: none; display: flex; flex-direction: column; + min-width: 0; } .soMeIcons { @@ -28,6 +30,19 @@ } .ecoLabel { + width: 38px; + height: auto; +} + +.ecoLabel img { + width: 100%; + height: auto; + flex-shrink: 0; + grid-column: 1 / 3; + grid-row: 4 / 4; +} + +.ecoContainer { display: flex; align-items: center; column-gap: var(--Spacing-x-one-and-half); @@ -38,10 +53,6 @@ margin-bottom: var(--Spacing-x1); } -.ecoLabel img { - flex-shrink: 0; -} - .ecoLabelText { display: flex; color: var(--UI-Text-Medium-contrast); @@ -49,8 +60,8 @@ justify-content: center; } -.googleMaps { - text-decoration: none; +.link { + text-decoration: underline; font-family: var(--typography-Body-Regular-fontFamily); - color: var(--Base-Text-Medium-contrast); + color: var(--Base-Text-High-contrast); } diff --git a/components/HotelReservation/Contact/index.tsx b/components/HotelReservation/Contact/index.tsx index 360831c94..d62305355 100644 --- a/components/HotelReservation/Contact/index.tsx +++ b/components/HotelReservation/Contact/index.tsx @@ -24,31 +24,27 @@ export default function Contact({ hotel }: ContactProps) { {intl.formatMessage({ id: "Address" })} - - {`${hotel.address.streetAddress}, ${hotel.address.city}`} - + {`${hotel.address.streetAddress}, `} + {hotel.address.city}
  • {intl.formatMessage({ id: "Driving directions" })} - - Google Maps - + Google Maps +
  • {intl.formatMessage({ id: "Contact us" })} - - {hotel.contactInformation.phoneNumber} + + + {hotel.contactInformation.phoneNumber} +
  • @@ -76,23 +72,24 @@ export default function Contact({ hotel }: ContactProps) { {intl.formatMessage({ id: "Email" })} - - {hotel.contactInformation.email} + + + {hotel.contactInformation.email} +
  • {hotel.hotelFacts.ecoLabels?.nordicEcoLabel ? ( -
    - {intl.formatMessage({ +
    +
    + {intl.formatMessage({ +
    {intl.formatMessage({ id: "Nordic Swan Ecolabel" })} diff --git a/components/HotelReservation/SelectRate/RoomFilter/index.tsx b/components/HotelReservation/SelectRate/RoomFilter/index.tsx index c800c3cc9..1d874ec6e 100644 --- a/components/HotelReservation/SelectRate/RoomFilter/index.tsx +++ b/components/HotelReservation/SelectRate/RoomFilter/index.tsx @@ -1,7 +1,7 @@ "use client" import { zodResolver } from "@hookform/resolvers/zod" -import { useCallback, useEffect, useMemo } from "react" +import { useCallback, useEffect, useMemo, useState } from "react" import { FormProvider, useForm } from "react-hook-form" import { useIntl } from "react-intl" import { useMediaQuery } from "usehooks-ts" @@ -27,7 +27,8 @@ export default function RoomFilter({ onFilter, filterOptions, }: RoomFilterProps) { - const isAboveMobile = useMediaQuery("(min-width: 768px)") + const isTabletAndUp = useMediaQuery("(min-width: 768px)") + const [isAboveMobile, setIsAboveMobile] = useState(false) const initialFilterValues = useMemo( () => @@ -71,6 +72,10 @@ export default function RoomFilter({ return () => subscription.unsubscribe() }, [handleSubmit, watch, submitFilter]) + useEffect(() => { + setIsAboveMobile(isTabletAndUp) + }, [isTabletAndUp]) + return (
    diff --git a/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx index e44c3312e..01e4890a5 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx +++ b/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx @@ -18,9 +18,7 @@ export default function FlexibilityOption({ name, paymentTerm, priceInformation, - roomType, roomTypeCode, - features, petRoomPackage, handleSelectRate, }: FlexibilityOptionProps) { @@ -45,10 +43,22 @@ export default function FlexibilityOption({ const { public: publicPrice, member: memberPrice } = product.productType - function onChange() { - handleSelectRate({ - publicRateCode: publicPrice.rateCode, - roomTypeCode: roomTypeCode, + const onClick: React.MouseEventHandler = (e) => { + handleSelectRate((prev) => { + if ( + prev && + prev.publicRateCode === publicPrice.rateCode && + prev.roomTypeCode === roomTypeCode + ) { + if (e.currentTarget?.checked) e.currentTarget.checked = false + return undefined + } else + return { + publicRateCode: publicPrice.rateCode, + roomTypeCode: roomTypeCode, + name: name, + paymentTerm: paymentTerm, + } }) } @@ -58,7 +68,7 @@ export default function FlexibilityOption({ type="radio" name="rateCode" value={publicPrice?.rateCode} - onChange={onChange} + onClick={onClick} />
    diff --git a/components/HotelReservation/SelectRate/RoomSelection/RateSummary/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/RateSummary/index.tsx index 222acef51..4322872dc 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RateSummary/index.tsx +++ b/components/HotelReservation/SelectRate/RoomSelection/RateSummary/index.tsx @@ -34,6 +34,7 @@ export default function RateSummary({ features, roomType, priceName, + priceTerm, } = rateSummary const priceToShow = isUserLoggedIn && member ? member : publicRate @@ -80,87 +81,93 @@ export default function RateSummary({
    )} -
    - {roomType} - {priceName} -
    -
    - {showMemberDiscountBanner && ( -
    - - {intl.formatMessage( - { - id: "To get the member price {amount} {currency}, log in or join when completing the booking.", - }, - { - span: (str) => ( - - {str} - - ), - amount: member.localPrice.pricePerStay, - currency: member.localPrice.currency, - } - )} - -
    - )} -
    - - {intl.formatMessage( - { id: "Total price (incl VAT)" }, - { b: (str) => {str} } - )} - - {summaryPriceTex} +
    +
    + {roomType} + {`${priceName}, ${priceTerm}`}
    -
    -
    - - {priceToShow?.localPrice.pricePerStay}{" "} - {priceToShow?.localPrice.currency} - - - {intl.formatMessage({ id: "Approx." })}{" "} - {priceToShow?.requestedPrice?.pricePerStay}{" "} - {priceToShow?.requestedPrice?.currency} - -
    -
    - - {intl.formatMessage({ id: "Total price" })} - - - {priceToShow?.localPrice.pricePerStay}{" "} - {priceToShow?.localPrice.currency} - - - {summaryPriceTex} - -
    - {isPetRoomSelected && ( -
    - - + {petRoomPrice} {petRoomCurrency} - - - {intl.formatMessage({ id: "Pet charge" })} - +
    + {showMemberDiscountBanner && ( +
    + + {intl.formatMessage( + { + id: "To get the member price {amount} {currency}, log in or join when completing the booking.", + }, + { + span: (str) => ( + + {str} + + ), + amount: member.localPrice.pricePerStay, + currency: member.localPrice.currency, + } + )} +
    )} - +
    + + {intl.formatMessage( + { id: "Total price (incl VAT)" }, + { b: (str) => {str} } + )} + + {summaryPriceTex} +
    +
    +
    + + {priceToShow?.localPrice.pricePerStay}{" "} + {priceToShow?.localPrice.currency} + + + {intl.formatMessage({ id: "Approx." })}{" "} + {priceToShow?.requestedPrice?.pricePerStay}{" "} + {priceToShow?.requestedPrice?.currency} + +
    +
    + + {intl.formatMessage({ id: "Total price" })} + + + {priceToShow?.localPrice.pricePerStay}{" "} + {priceToShow?.localPrice.currency} + + + {summaryPriceTex} + +
    + {isPetRoomSelected && ( +
    + + + {petRoomPrice} {petRoomCurrency} + + + {intl.formatMessage({ id: "Pet charge" })} + +
    + )} + +
    diff --git a/components/HotelReservation/SelectRate/RoomSelection/RateSummary/rateSummary.module.css b/components/HotelReservation/SelectRate/RoomSelection/RateSummary/rateSummary.module.css index 4c49741c5..3271969ae 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RateSummary/rateSummary.module.css +++ b/components/HotelReservation/SelectRate/RoomSelection/RateSummary/rateSummary.module.css @@ -6,12 +6,19 @@ right: 0; background-color: var(--Base-Surface-Primary-light-Normal); padding: 0 0 var(--Spacing-x5); + align-items: center; + border-top: 1px solid var(--Base-Border-Subtle); + transition: bottom 300ms ease-in-out; +} + +.content { + width: 100%; + max-width: var(--max-width-navigation); + margin: 0 auto; display: flex; flex-direction: column; justify-content: space-between; align-items: center; - border-top: 1px solid var(--Base-Border-Subtle); - transition: bottom 300ms ease-in-out; } .summary[data-visible="true"] { @@ -80,7 +87,9 @@ @media (min-width: 768px) { .summary { - padding: var(--Spacing-x3) var(--Spacing-x2) var(--Spacing-x5); + padding: var(--Spacing-x3) var(--Spacing-x7) var(--Spacing-x5); + } + .content { flex-direction: row; } .petInfo, @@ -102,5 +111,6 @@ .summaryPriceContainer { width: auto; padding: 0; + align-items: center; } } diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx index a5b21e10d..4b8c47928 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx @@ -210,9 +210,7 @@ export default function RoomCard({ product={findProductForRate(rate)} priceInformation={getRateDefinitionForRate(rate)?.generalTerms} handleSelectRate={handleSelectRate} - roomType={roomConfiguration.roomType} roomTypeCode={roomConfiguration.roomTypeCode} - features={roomConfiguration.features} petRoomPackage={petRoomPackage} /> ))} diff --git a/components/HotelReservation/SelectRate/Rooms/index.tsx b/components/HotelReservation/SelectRate/Rooms/index.tsx index 857256e28..584e0195a 100644 --- a/components/HotelReservation/SelectRate/Rooms/index.tsx +++ b/components/HotelReservation/SelectRate/Rooms/index.tsx @@ -14,7 +14,10 @@ import { type RoomPackageCodes, } from "@/types/components/hotelReservation/selectRate/roomFilter" import type { SelectRateProps } from "@/types/components/hotelReservation/selectRate/roomSelection" -import type { Rate } from "@/types/components/hotelReservation/selectRate/selectRate" +import type { + Rate, + RateCode, +} from "@/types/components/hotelReservation/selectRate/selectRate" import type { RoomConfiguration } from "@/server/routers/hotels/output" export default function Rooms({ @@ -25,9 +28,9 @@ export default function Rooms({ }: SelectRateProps) { const visibleRooms: RoomConfiguration[] = filterDuplicateRoomTypesByLowestPrice(roomsAvailability.roomConfigurations) - const [selectedRate, setSelectedRate] = useState< - { publicRateCode: string; roomTypeCode: string } | undefined - >(undefined) + const [selectedRate, setSelectedRate] = useState( + undefined + ) const [selectedPackages, setSelectedPackages] = useState( [] ) @@ -115,17 +118,30 @@ export default function Rooms({ ) )?.features + const roomType = roomCategories.find((roomCategory) => + roomCategory.roomTypes.some( + (roomType) => roomType.code === room.roomTypeCode + ) + ) + const rateSummary: Rate = { features: petRoomPackage && features ? features : [], - priceName: room.roomType, + priceName: selectedRate?.name, + priceTerm: selectedRate?.paymentTerm, public: product.productType.public, member: product.productType.member, - roomType: room.roomType, + roomType: roomType?.name || room.roomType, roomTypeCode: room.roomTypeCode, } return rateSummary - }, [filteredRooms, availablePackages, selectedPackages, selectedRate]) + }, [ + filteredRooms, + availablePackages, + selectedPackages, + selectedRate, + roomCategories, + ]) useEffect(() => { if (rateSummary) return diff --git a/components/Icons/ExternalLink.tsx b/components/Icons/ExternalLink.tsx new file mode 100644 index 000000000..b58260209 --- /dev/null +++ b/components/Icons/ExternalLink.tsx @@ -0,0 +1,27 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function ExternalLinkIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + ) +} diff --git a/components/Icons/get-icon-by-icon-name.ts b/components/Icons/get-icon-by-icon-name.ts index 7ba60f321..ed24e0377 100644 --- a/components/Icons/get-icon-by-icon-name.ts +++ b/components/Icons/get-icon-by-icon-name.ts @@ -36,6 +36,7 @@ import { ElectricBikeIcon, ElectricCarIcon, EmailIcon, + ExternalLinkIcon, EyeHideIcon, EyeShowIcon, FacebookIcon, @@ -176,6 +177,8 @@ export function getIconByIconName( return ElectricCarIcon case IconName.Email: return EmailIcon + case IconName.ExternalLink: + return ExternalLinkIcon case IconName.EyeHide: return EyeHideIcon case IconName.EyeShow: diff --git a/components/Icons/index.tsx b/components/Icons/index.tsx index f56e5128f..580e941cd 100644 --- a/components/Icons/index.tsx +++ b/components/Icons/index.tsx @@ -61,6 +61,7 @@ export { default as ElectricBikeIcon } from "./ElectricBike" export { default as ElectricCarIcon } from "./ElectricCar" export { default as EmailIcon } from "./Email" export { default as ErrorCircleIcon } from "./ErrorCircle" +export { default as ExternalLinkIcon } from "./ExternalLink" export { default as EyeHideIcon } from "./EyeHide" export { default as EyeShowIcon } from "./EyeShow" export { default as FacebookIcon } from "./Facebook" diff --git a/components/ImageGallery/index.tsx b/components/ImageGallery/index.tsx index d26ed0007..007785ad8 100644 --- a/components/ImageGallery/index.tsx +++ b/components/ImageGallery/index.tsx @@ -6,7 +6,8 @@ import { useIntl } from "react-intl" import { GalleryIcon } from "@/components/Icons" import Image from "@/components/Image" import Lightbox from "@/components/Lightbox" -import Footnote from "@/components/TempDesignSystem/Text/Footnote" + +import Caption from "../TempDesignSystem/Text/Caption" import styles from "./imageGallery.module.css" @@ -44,9 +45,9 @@ function ImageGallery({ />
    - + {images.length} - +
    {accessibilityElevatorPitchText} diff --git a/components/SidePeeks/HotelSidePeek/Accordions/CheckInCheckOut.tsx b/components/SidePeeks/HotelSidePeek/Accordions/CheckInCheckOut.tsx index d005e6688..6848bc801 100644 --- a/components/SidePeeks/HotelSidePeek/Accordions/CheckInCheckOut.tsx +++ b/components/SidePeeks/HotelSidePeek/Accordions/CheckInCheckOut.tsx @@ -13,6 +13,7 @@ export default function CheckinCheckOut({ checkin }: CheckInCheckOutProps) { {intl.formatMessage({ id: "Hours" })} {`${intl.formatMessage({ id: "Check in from" })}: ${checkin.checkInTime}`} diff --git a/components/SidePeeks/HotelSidePeek/Accordions/MeetingsAndConferences.tsx b/components/SidePeeks/HotelSidePeek/Accordions/MeetingsAndConferences.tsx index 558046d4b..8168a764f 100644 --- a/components/SidePeeks/HotelSidePeek/Accordions/MeetingsAndConferences.tsx +++ b/components/SidePeeks/HotelSidePeek/Accordions/MeetingsAndConferences.tsx @@ -14,6 +14,7 @@ export default function MeetingsAndConferences({ {meetingDescription} diff --git a/components/SidePeeks/HotelSidePeek/Accordions/Parking.tsx b/components/SidePeeks/HotelSidePeek/Accordions/Parking.tsx index 0e5ffcec0..ba4ee33f7 100644 --- a/components/SidePeeks/HotelSidePeek/Accordions/Parking.tsx +++ b/components/SidePeeks/HotelSidePeek/Accordions/Parking.tsx @@ -16,6 +16,7 @@ export default function Parking({ parking }: ParkingProps) { title={intl.formatMessage({ id: "Parking" })} icon={IconName.Parking} className={styles.parking} + variant="sidepeek" > {parking.map((p) => (
    diff --git a/components/SidePeeks/HotelSidePeek/Accordions/Restaurant.tsx b/components/SidePeeks/HotelSidePeek/Accordions/Restaurant.tsx index a8d1cd047..d35a30304 100644 --- a/components/SidePeeks/HotelSidePeek/Accordions/Restaurant.tsx +++ b/components/SidePeeks/HotelSidePeek/Accordions/Restaurant.tsx @@ -15,6 +15,7 @@ export default function Restaurant({ {restaurantsContentDescriptionMedium} diff --git a/components/SidePeeks/HotelSidePeek/Accordions/sidePeekAccordion.module.css b/components/SidePeeks/HotelSidePeek/Accordions/sidePeekAccordion.module.css index bd2ae8933..0134e2165 100644 --- a/components/SidePeeks/HotelSidePeek/Accordions/sidePeekAccordion.module.css +++ b/components/SidePeeks/HotelSidePeek/Accordions/sidePeekAccordion.module.css @@ -10,6 +10,7 @@ align-items: center; gap: var(--Spacing-x1); padding-left: var(--Spacing-x1); + justify-items: flex-start; } .list li svg { diff --git a/components/SidePeeks/HotelSidePeek/hotelSidePeek.module.css b/components/SidePeeks/HotelSidePeek/hotelSidePeek.module.css index 23b92b792..481e6b47d 100644 --- a/components/SidePeeks/HotelSidePeek/hotelSidePeek.module.css +++ b/components/SidePeeks/HotelSidePeek/hotelSidePeek.module.css @@ -9,13 +9,24 @@ gap: var(--Spacing-x2); } -.amenity { - font-family: var(--typography-Body-Regular-fontFamily); - border-bottom: 1px solid var(--Base-Border-Subtle); - /* padding set to align with AccordionItem which has a different composition */ - padding: calc(var(--Spacing-x1) + var(--Spacing-x-one-and-half)) - var(--Spacing-x3); +.content:last-child { + gap: 0; +} + +.content > p { + margin-bottom: var(--Spacing-x-one-and-half); +} + +.content > ul > li:first-child { + border-top: 1px solid var(--Base-Border-Subtle); +} + +.amenity > p { + border-top: 1px solid var(--Base-Border-Subtle); + padding: calc(var(--Spacing-x-one-and-half) + var(--Spacing-x1)) + var(--Spacing-x1); display: flex; + align-items: center; gap: var(--Spacing-x1); } diff --git a/components/SidePeeks/HotelSidePeek/index.tsx b/components/SidePeeks/HotelSidePeek/index.tsx index 4fc5bab8c..dad75e7b3 100644 --- a/components/SidePeeks/HotelSidePeek/index.tsx +++ b/components/SidePeeks/HotelSidePeek/index.tsx @@ -71,24 +71,21 @@ export default function HotelSidePeek({ } /> )} + +
    {amenitiesList.map((amenity) => { const Icon = mapFacilityToIcon(amenity.id) return ( -
    + {Icon && ( - + )} - - {amenity.name} - -
    + {amenity.name} + ) })} - +
    + {/* TODO: handle linking to Hotel Page */} {/* {showCTA && (
    {primary_button && ( -