fix: add hotel header to enter details flow

This commit is contained in:
Christel Westerberg
2024-11-27 13:23:36 +01:00
parent 6f8092d6ec
commit f5990998db
9 changed files with 128 additions and 95 deletions

View File

@@ -13,8 +13,8 @@ import {
import BedType from "@/components/HotelReservation/EnterDetails/BedType" import BedType from "@/components/HotelReservation/EnterDetails/BedType"
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast" import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
import Details from "@/components/HotelReservation/EnterDetails/Details" import Details from "@/components/HotelReservation/EnterDetails/Details"
import HotelHeader from "@/components/HotelReservation/EnterDetails/Header"
import HistoryStateManager from "@/components/HotelReservation/EnterDetails/HistoryStateManager" import HistoryStateManager from "@/components/HotelReservation/EnterDetails/HistoryStateManager"
import HotelHeader from "@/components/HotelReservation/EnterDetails/HotelHeader"
import Payment from "@/components/HotelReservation/EnterDetails/Payment" import Payment from "@/components/HotelReservation/EnterDetails/Payment"
import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion" import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion"
import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom" import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom"
@@ -91,13 +91,13 @@ export default async function StepPage({
const packages = packageCodes const packages = packageCodes
? await getPackages({ ? await getPackages({
adults, adults,
children: children?.length, children: children?.length,
endDate: toDate, endDate: toDate,
hotelId, hotelId,
packageCodes, packageCodes,
startDate: fromDate, startDate: fromDate,
}) })
: null : null
const roomAvailability = await getSelectedRoomAvailability( const roomAvailability = await getSelectedRoomAvailability(
@@ -138,9 +138,9 @@ export default async function StepPage({
const memberPrice = roomAvailability.memberRate const memberPrice = roomAvailability.memberRate
? { ? {
price: roomAvailability.memberRate.localPrice.pricePerStay, price: roomAvailability.memberRate.localPrice.pricePerStay,
currency: roomAvailability.memberRate.localPrice.currency, currency: roomAvailability.memberRate.localPrice.currency,
} }
: undefined : undefined
return ( return (
@@ -158,7 +158,7 @@ export default async function StepPage({
user={user} user={user}
> >
<main> <main>
<HotelHeader hotel={hotelData.data.attributes} /> <HotelHeader hotelData={hotelData} />
<div className={styles.container}> <div className={styles.container}>
<div className={styles.content}> <div className={styles.content}>
<section> <section>

View File

@@ -0,0 +1,32 @@
"use client"
import { useIntl } from "react-intl"
import useSidePeekStore from "@/stores/sidepeek"
import ChevronRight from "@/components/Icons/ChevronRight"
import Button from "@/components/TempDesignSystem/Button"
import styles from "./header.module.css"
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
import { ToggleSidePeekProps } from "@/types/components/hotelReservation/toggleSidePeekProps"
export default function ToggleSidePeek({ hotelId }: ToggleSidePeekProps) {
const intl = useIntl()
const openSidePeek = useSidePeekStore((state) => state.openSidePeek)
return (
<Button
onClick={() => openSidePeek({ key: SidePeekEnum.hotelDetails, hotelId })}
theme="base"
size="small"
variant="icon"
intent="textInverted"
wrapping
className={styles.toggle}
>
{intl.formatMessage({ id: "See hotel details" })}
<ChevronRight height="14" color="white" />
</Button>
)
}

View File

@@ -0,0 +1,53 @@
.header {
position: relative;
overflow: hidden;
}
.hero {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
object-fit: cover;
}
.wrapper {
position: relative;
padding: var(--Spacing-x3) var(--Spacing-x2);
background-color: rgba(57, 57, 57, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: var(--Spacing-x2);
}
.titleContainer {
display: flex;
flex-direction: column;
gap: var(--Spacing-x-half);
}
.address {
display: flex;
gap: var(--Spacing-x-one-and-half);
font-style: normal;
}
.toggle {
padding: 0px !important;
}
@media (min-width: 768px) {
.wrapper {
padding: var(--Spacing-x3) var(--Spacing-x3);
}
}
@media screen and (min-width: 1367px) {
.wrapper {
padding: var(--Spacing-x6) var(--Spacing-x5);
}
}

View File

@@ -1,31 +1,40 @@
import Divider from "@/components/TempDesignSystem/Divider" import Image from "@/components/Image"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption" import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title" import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import getSingleDecimal from "@/utils/numberFormatting" import getSingleDecimal from "@/utils/numberFormatting"
import ToggleSidePeek from "./ToggleSidePeek"
import styles from "./header.module.css" import styles from "./header.module.css"
import type { HotelHeaderProps } from "@/types/components/hotelReservation/enterDetails/hotelHeader" import type { HotelHeaderProps } from "@/types/components/hotelReservation/enterDetails/hotelHeader"
export default async function HotelHeader({ hotel }: HotelHeaderProps) { export default async function HotelHeader({ hotelData }: HotelHeaderProps) {
const intl = await getIntl() const intl = await getIntl()
const hotel = hotelData.data.attributes
const image = hotel.hotelContent?.images
return ( return (
<header className={styles.header}> <header className={styles.header}>
<Image
className={styles.hero}
alt={image.metaData.altText || image.metaData.altText_En || ""}
src={image.imageSizes.large}
height={200}
width={1196}
/>
<div className={styles.wrapper}> <div className={styles.wrapper}>
<div className={styles.titleContainer}> <div className={styles.titleContainer}>
<Title as="h3" level="h1"> <Title as="h1" level="h1" color="white">
{hotel.name} {hotel.name}
</Title> </Title>
<address className={styles.address}> <address className={styles.address}>
<Caption color="textMediumContrast"> <Caption color="white">
{hotel.address.streetAddress}, {hotel.address.city} {hotel.address.streetAddress}, {hotel.address.city}
</Caption> </Caption>
<div> <Caption color="white"></Caption>
<Divider variant="vertical" color="subtle" /> <Caption color="white">
</div>
<Caption color="textMediumContrast">
{intl.formatMessage( {intl.formatMessage(
{ id: "Distance in km to city centre" }, { id: "Distance in km to city centre" },
{ {
@@ -37,14 +46,7 @@ export default async function HotelHeader({ hotel }: HotelHeaderProps) {
</Caption> </Caption>
</address> </address>
</div> </div>
<div className={styles.dividerContainer}> <ToggleSidePeek hotelId={hotel.operaId} />
<Divider variant="vertical" color="subtle" />
</div>
<div className={styles.descriptionContainer}>
<Body color="baseTextHighContrast">
{hotel.hotelContent.texts.descriptions.short}
</Body>
</div>
</div> </div>
</header> </header>
) )

View File

@@ -1,64 +0,0 @@
.header {
background-color: var(--Base-Surface-Subtle-Normal);
padding: var(--Spacing-x3) var(--Spacing-x2);
}
.wrapper {
display: flex;
flex-direction: column;
gap: var(--Spacing-x3);
justify-content: center;
}
.titleContainer {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
gap: var(--Spacing-x1);
}
.descriptionContainer {
display: flex;
flex-direction: column;
gap: var(--Spacing-x-one-and-half);
}
.address {
display: flex;
gap: var(--Spacing-x-one-and-half);
font-style: normal;
}
.dividerContainer {
display: none;
}
@media (min-width: 768px) {
.header {
padding: var(--Spacing-x4) 0;
}
.wrapper {
flex-direction: row;
gap: var(--Spacing-x6);
margin: 0 auto;
/* simulates padding on viewport smaller than --max-width-navigation */
width: min(
calc(100dvw - (var(--Spacing-x2) * 2)),
var(--max-width-navigation)
);
}
.titleContainer > h1 {
white-space: nowrap;
}
.dividerContainer {
display: block;
}
.address {
gap: var(--Spacing-x3);
}
}

View File

@@ -265,6 +265,10 @@ a.default {
color: var(--Base-Button-Text-On-Fill-Normal); color: var(--Base-Button-Text-On-Fill-Normal);
} }
.baseTextInverted {
color: var(--Base-Button-Primary-On-Fill-Normal);
}
.baseText:active, .baseText:active,
.baseText:focus, .baseText:focus,
.baseText:hover { .baseText:hover {

View File

@@ -10,6 +10,7 @@ export const buttonVariants = cva(styles.btn, {
secondary: styles.secondary, secondary: styles.secondary,
tertiary: styles.tertiary, tertiary: styles.tertiary,
text: styles.text, text: styles.text,
textInverted: styles.text,
}, },
size: { size: {
small: styles.small, small: styles.small,
@@ -140,5 +141,10 @@ export const buttonVariants = cva(styles.btn, {
intent: "text", intent: "text",
theme: "base", theme: "base",
}, },
{
className: styles.baseTextInverted,
intent: "textInverted",
theme: "base",
},
], ],
}) })

View File

@@ -3,5 +3,5 @@ import type { RouterOutput } from "@/lib/trpc/client"
type HotelDataGet = RouterOutput["hotel"]["hotelData"]["get"] type HotelDataGet = RouterOutput["hotel"]["hotelData"]["get"]
export interface HotelHeaderProps { export interface HotelHeaderProps {
hotel: NonNullable<HotelDataGet>["data"]["attributes"] hotelData: NonNullable<HotelDataGet>
} }

View File

@@ -1,4 +1,4 @@
export type ToggleSidePeekProps = { export type ToggleSidePeekProps = {
hotelId: string hotelId: string
roomTypeCode: string roomTypeCode?: string
} }