fix(SW-1241): Adjusted amenities sidepeek on hotel pages and booking flow
Approved-by: Michael Zetterberg Approved-by: Matilda Landström
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x3);
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import OpeningHours from "@/components/OpeningHours"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import type { BreakfastAmenityProps } from "@/types/components/hotelPage/sidepeek/amenities"
|
||||
import { HotelTypeEnum } from "@/types/enums/hotelType"
|
||||
|
||||
export default async function BreakfastAmenity({
|
||||
openingHours,
|
||||
alternateOpeningHours,
|
||||
hotelType,
|
||||
}: BreakfastAmenityProps) {
|
||||
const intl = await getIntl()
|
||||
|
||||
const accordionContent =
|
||||
hotelType === HotelTypeEnum.ScandicGo ? (
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "All-day breakfast",
|
||||
})}
|
||||
</Body>
|
||||
) : (
|
||||
<OpeningHours
|
||||
openingHours={openingHours!}
|
||||
alternateOpeningHours={alternateOpeningHours!}
|
||||
heading={intl.formatMessage({
|
||||
defaultMessage: "Opening hours",
|
||||
})}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Breakfast",
|
||||
})}
|
||||
iconName={IconName.CoffeeAlt}
|
||||
variant="sidepeek"
|
||||
trackingId="amenities:breakfast"
|
||||
>
|
||||
{accordionContent}
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import type { CheckInAmenityProps } from "@/types/components/hotelPage/sidepeek/checkIn"
|
||||
|
||||
export default async function CheckInAmenity({
|
||||
checkInInformation,
|
||||
}: CheckInAmenityProps) {
|
||||
const intl = await getIntl()
|
||||
const { checkInTime, checkOutTime } = checkInInformation
|
||||
return (
|
||||
<AccordionItem
|
||||
title={`${intl.formatMessage({
|
||||
defaultMessage: "Check-in",
|
||||
})}/${intl.formatMessage({
|
||||
defaultMessage: "Check-out",
|
||||
})}`}
|
||||
iconName={IconName.Business}
|
||||
variant="sidepeek"
|
||||
trackingId="amenities:check-in"
|
||||
>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Times",
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Check in from: {checkInTime}",
|
||||
},
|
||||
{ checkInTime }
|
||||
)}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Check out at latest: {checkOutTime}",
|
||||
},
|
||||
{ checkOutTime }
|
||||
)}
|
||||
</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
.wrapper {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x3);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export { default as AccessibilityAmenity } from "./Accessibility"
|
||||
export { default as BreakfastAmenity } from "./Breakfast"
|
||||
export { default as CheckInAmenity } from "./CheckIn"
|
||||
export { default as ParkingAmenity } from "./Parking"
|
||||
@@ -1,44 +0,0 @@
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import { FacilityToIcon } from "../../../data"
|
||||
|
||||
import styles from "./filteredAmenities.module.css"
|
||||
|
||||
import type { FilteredAmenitiesProps } from "@/types/components/hotelPage/sidepeek/amenities"
|
||||
|
||||
export default function FilteredAmenities({
|
||||
filteredAmenities,
|
||||
}: FilteredAmenitiesProps) {
|
||||
return (
|
||||
<>
|
||||
{filteredAmenities?.map((amenity) => {
|
||||
const Icon = (
|
||||
<FacilityToIcon
|
||||
id={amenity.id}
|
||||
color="Icon/Interactive/Default"
|
||||
size={24}
|
||||
/>
|
||||
)
|
||||
return (
|
||||
<li key={amenity.name} className={styles.wrapper}>
|
||||
<div className={styles.amenity}>
|
||||
{Icon ? (
|
||||
Icon
|
||||
) : (
|
||||
<MaterialIcon
|
||||
icon="favorite"
|
||||
color="Icon/Interactive/Default"
|
||||
/>
|
||||
)}
|
||||
<Subtitle color="burgundy" type="two">
|
||||
{amenity.name}
|
||||
</Subtitle>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,19 +1,14 @@
|
||||
import AccessibilityAccordionItem from "@/components/SidePeeks/AmenitiesSidepeekContent/Accordions/Accessibility"
|
||||
import BreakfastAccordionItem from "@/components/SidePeeks/AmenitiesSidepeekContent/Accordions/Breakfast"
|
||||
import CheckInCheckOutAccordionItem from "@/components/SidePeeks/AmenitiesSidepeekContent/Accordions/CheckInCheckOut"
|
||||
import ParkingAccordionItem from "@/components/SidePeeks/AmenitiesSidepeekContent/Accordions/Parking"
|
||||
import AdditionalAmenities from "@/components/SidePeeks/AmenitiesSidepeekContent/AdditionalAmenities"
|
||||
import Accordion from "@/components/TempDesignSystem/Accordion"
|
||||
import SidePeek from "@/components/TempDesignSystem/SidePeek"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import {
|
||||
AccessibilityAmenity,
|
||||
BreakfastAmenity,
|
||||
CheckInAmenity,
|
||||
ParkingAmenity,
|
||||
} from "./AccordionAmenities"
|
||||
import FilteredAmenities from "./FilteredAmenities"
|
||||
|
||||
import { SidepeekSlugs } from "@/types/components/hotelPage/hotelPage"
|
||||
import type { AmenitiesSidePeekProps } from "@/types/components/hotelPage/sidepeek/amenities"
|
||||
import { FacilityEnum } from "@/types/enums/facilities"
|
||||
import { HotelTypeEnum } from "@/types/enums/hotelType"
|
||||
|
||||
export default async function AmenitiesSidePeek({
|
||||
amenitiesList,
|
||||
@@ -25,35 +20,6 @@ export default async function AmenitiesSidePeek({
|
||||
}: AmenitiesSidePeekProps) {
|
||||
const intl = await getIntl()
|
||||
|
||||
const amenitiesToRemove = [
|
||||
FacilityEnum.ParkingAdditionalCost,
|
||||
FacilityEnum.ParkingElectricCharging,
|
||||
FacilityEnum.ParkingFreeParking,
|
||||
FacilityEnum.ParkingGarage,
|
||||
FacilityEnum.ParkingOutdoor,
|
||||
FacilityEnum.MeetingArea,
|
||||
FacilityEnum.ServesBreakfastAlwaysIncluded,
|
||||
FacilityEnum.LateCheckOutUntil1400Guaranteed,
|
||||
]
|
||||
|
||||
const filteredAmenities = amenitiesList.filter(
|
||||
(amenity) => !amenitiesToRemove.includes(amenity.id)
|
||||
)
|
||||
|
||||
const breakfastOpeningHours = restaurants
|
||||
?.map((restaurant) => {
|
||||
const breakfastDetail = restaurant.openingDetails.find(
|
||||
(details) =>
|
||||
details.openingHours.name === "Breakfast" ||
|
||||
details.openingHours.name ===
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Breakfast",
|
||||
})
|
||||
)
|
||||
return breakfastDetail
|
||||
})
|
||||
.filter(Boolean)[0]
|
||||
|
||||
return (
|
||||
<SidePeek
|
||||
contentKey={SidepeekSlugs.amenities}
|
||||
@@ -62,27 +28,21 @@ export default async function AmenitiesSidePeek({
|
||||
})}
|
||||
>
|
||||
<Accordion>
|
||||
<ParkingAmenity
|
||||
<ParkingAccordionItem
|
||||
parking={parking.parking}
|
||||
parkingElevatorPitch={parking.parkingElevatorPitch}
|
||||
elevatorPitch={parking.parkingElevatorPitch}
|
||||
parkingPageUrl={parking.parkingPageUrl}
|
||||
/>
|
||||
{(breakfastOpeningHours || hotelType === HotelTypeEnum.ScandicGo) && (
|
||||
<BreakfastAmenity
|
||||
openingHours={breakfastOpeningHours?.openingHours}
|
||||
alternateOpeningHours={breakfastOpeningHours?.alternateOpeningHours}
|
||||
hotelType={hotelType}
|
||||
/>
|
||||
)}
|
||||
<CheckInAmenity checkInInformation={checkInInformation} />
|
||||
{(accessibility.elevatorPitch ||
|
||||
accessibility.accessibilityPageUrl) && (
|
||||
<AccessibilityAmenity
|
||||
accessibilityPageUrl={accessibility.accessibilityPageUrl}
|
||||
elevatorPitch={accessibility.elevatorPitch}
|
||||
/>
|
||||
)}
|
||||
<FilteredAmenities filteredAmenities={filteredAmenities} />
|
||||
<BreakfastAccordionItem
|
||||
restaurants={restaurants}
|
||||
hotelType={hotelType}
|
||||
/>
|
||||
<CheckInCheckOutAccordionItem checkInData={checkInInformation} />
|
||||
<AccessibilityAccordionItem
|
||||
accessibilityPageUrl={accessibility.accessibilityPageUrl}
|
||||
elevatorPitch={accessibility.elevatorPitch}
|
||||
/>
|
||||
<AdditionalAmenities amenities={amenitiesList} />
|
||||
</Accordion>
|
||||
</SidePeek>
|
||||
)
|
||||
|
||||
@@ -38,6 +38,7 @@ import styles from "./hotelCard.module.css"
|
||||
|
||||
import { HotelCardListingTypeEnum } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import type { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps"
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import { RateTypeEnum } from "@/types/enums/rateType"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
|
||||
@@ -173,6 +174,7 @@ function HotelCard({
|
||||
hotelId={hotel.operaId}
|
||||
hotel={hotel}
|
||||
showCTA={true}
|
||||
sidePeekKey={SidePeekEnum.hotelDetails}
|
||||
/>
|
||||
</section>
|
||||
<div className={styles.prices}>
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import useSidePeekStore from "@/stores/sidepeek"
|
||||
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
|
||||
import styles from "./readMore.module.css"
|
||||
|
||||
import type { ReadMoreProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
export default function ReadMore({ label, hotelId, showCTA }: ReadMoreProps) {
|
||||
export default function ReadMore({
|
||||
label,
|
||||
hotelId,
|
||||
showCTA,
|
||||
sidePeekKey,
|
||||
}: ReadMoreProps) {
|
||||
const openSidePeek = useSidePeekStore((state) => state.openSidePeek)
|
||||
return (
|
||||
<Button
|
||||
onPress={() => {
|
||||
openSidePeek({ key: SidePeekEnum.hotelDetails, hotelId, showCTA })
|
||||
openSidePeek({ key: sidePeekKey, hotelId, showCTA })
|
||||
}}
|
||||
intent="text"
|
||||
theme="base"
|
||||
wrapping
|
||||
className={styles.detailsButton}
|
||||
variant="Text"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
{label}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
.detailsButton {
|
||||
align-self: start;
|
||||
border-radius: 0;
|
||||
height: auto;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
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: var(--Spacing-x2)
|
||||
calc(var(--Spacing-x1) + var(--Spacing-x-one-and-half));
|
||||
}
|
||||
|
||||
.list {
|
||||
font-family: var(--typography-Body-Regular-fontFamily);
|
||||
list-style: inside;
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import TripAdvisorChip from "../../TripAdvisorChip"
|
||||
import styles from "./hotelInfoCard.module.css"
|
||||
|
||||
import type { HotelInfoCardProps } from "@/types/components/hotelReservation/selectRate/hotelInfoCard"
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
export default async function HotelInfoCard({ hotel }: HotelInfoCardProps) {
|
||||
const intl = await getIntl()
|
||||
@@ -88,6 +89,7 @@ export default async function HotelInfoCard({ hotel }: HotelInfoCardProps) {
|
||||
hotelId={hotel.operaId}
|
||||
hotel={hotel}
|
||||
showCTA={false}
|
||||
sidePeekKey={SidePeekEnum.amenities}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { trpc } from "@/lib/trpc/client"
|
||||
import useSidePeekStore from "@/stores/sidepeek"
|
||||
|
||||
import AmenitiesSidePeek from "@/components/SidePeeks/AmenitiesSidePeek"
|
||||
import BookedRoomSidePeek from "@/components/SidePeeks/BookedRoomSidePeek"
|
||||
import HotelSidePeek from "@/components/SidePeeks/HotelSidePeek"
|
||||
import RoomSidePeek from "@/components/SidePeeks/RoomSidePeek"
|
||||
@@ -39,13 +40,23 @@ export default function HotelReservationSidePeek() {
|
||||
return (
|
||||
<>
|
||||
{hotelData && (
|
||||
<HotelSidePeek
|
||||
additionalHotelData={hotelData.additionalData}
|
||||
hotel={hotelData.hotel}
|
||||
activeSidePeek={activeSidePeek}
|
||||
close={close}
|
||||
showCTA={showCTA}
|
||||
/>
|
||||
<>
|
||||
<HotelSidePeek
|
||||
additionalHotelData={hotelData.additionalData}
|
||||
hotel={hotelData.hotel}
|
||||
restaurants={hotelData.restaurants}
|
||||
activeSidePeek={activeSidePeek}
|
||||
close={close}
|
||||
showCTA={showCTA}
|
||||
/>
|
||||
<AmenitiesSidePeek
|
||||
hotel={hotelData.hotel}
|
||||
restaurants={hotelData.restaurants}
|
||||
additionalHotelData={hotelData.additionalData}
|
||||
activeSidePeek={activeSidePeek}
|
||||
close={close}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{selectedRoom && (
|
||||
<RoomSidePeek
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import { getGroupedOpeningHours } from "../utils"
|
||||
|
||||
@@ -13,10 +16,10 @@ interface AlternateOpeningHoursProps {
|
||||
alternateOpeningHours: RestaurantOpeningHours
|
||||
}
|
||||
|
||||
export default async function AlternateOpeningHours({
|
||||
export default function AlternateOpeningHours({
|
||||
alternateOpeningHours,
|
||||
}: AlternateOpeningHoursProps) {
|
||||
const intl = await getIntl()
|
||||
const intl = useIntl()
|
||||
const groupedAlternateOpeningHours = alternateOpeningHours
|
||||
? getGroupedOpeningHours(alternateOpeningHours, intl)
|
||||
: null
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
"use client"
|
||||
|
||||
import { getIntl } from "@/i18n"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import Divider from "../TempDesignSystem/Divider"
|
||||
import AlternateOpeningHours from "./AlternateOpeningHours"
|
||||
@@ -8,14 +10,20 @@ import { getGroupedOpeningHours } from "./utils"
|
||||
|
||||
import styles from "./openingHours.module.css"
|
||||
|
||||
import type { OpeningHoursProps } from "@/types/components/hotelPage/sidepeek/openingHours"
|
||||
import type { RestaurantOpeningHours } from "@/types/hotel"
|
||||
|
||||
export default async function OpeningHours({
|
||||
interface OpeningHoursProps {
|
||||
openingHours: RestaurantOpeningHours
|
||||
alternateOpeningHours?: RestaurantOpeningHours
|
||||
heading?: string
|
||||
}
|
||||
|
||||
export default function OpeningHours({
|
||||
openingHours,
|
||||
alternateOpeningHours,
|
||||
heading,
|
||||
}: OpeningHoursProps) {
|
||||
const intl = await getIntl()
|
||||
const intl = useIntl()
|
||||
const groupedOpeningHours = getGroupedOpeningHours(openingHours, intl)
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import { getIntl } from "@/i18n"
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import styles from "./parkingList.module.css"
|
||||
|
||||
import type { ParkingListProps } from "@/types/components/hotelPage/sidepeek/parking"
|
||||
|
||||
export default async function ParkingList({
|
||||
export default function ParkingList({
|
||||
numberOfChargingSpaces,
|
||||
canMakeReservation,
|
||||
numberOfParkingSpots,
|
||||
distanceToHotel,
|
||||
address,
|
||||
}: ParkingListProps) {
|
||||
const intl = await getIntl()
|
||||
const intl = useIntl()
|
||||
|
||||
const canMakeReservationYesMsg = intl.formatMessage({
|
||||
defaultMessage: "Parking can be reserved in advance: Yes",
|
||||
@@ -22,7 +25,7 @@ export default async function ParkingList({
|
||||
})
|
||||
|
||||
return (
|
||||
<Body color="uiTextHighContrast" asChild>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<ul className={styles.listStyling}>
|
||||
{numberOfChargingSpaces ? (
|
||||
<li>
|
||||
@@ -71,6 +74,6 @@ export default async function ParkingList({
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
</Body>
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import { getIntl } from "@/i18n"
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { formatPrice } from "@/utils/numberFormatting"
|
||||
|
||||
import { getPeriod } from "./utils"
|
||||
@@ -11,28 +15,28 @@ import {
|
||||
Periods,
|
||||
} from "@/types/components/hotelPage/sidepeek/parking"
|
||||
|
||||
export default async function ParkingPrices({
|
||||
export default function ParkingPrices({
|
||||
currency = "",
|
||||
freeParking,
|
||||
pricing,
|
||||
}: ParkingPricesProps) {
|
||||
const intl = await getIntl()
|
||||
const intl = useIntl()
|
||||
|
||||
return freeParking ? (
|
||||
<Body textTransform="bold" color="uiTextHighContrast">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Free parking",
|
||||
})}
|
||||
</Body>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p className={styles.wrapper}>
|
||||
{intl.formatMessage({ defaultMessage: "Free parking" })}
|
||||
</p>
|
||||
</Typography>
|
||||
) : (
|
||||
<dl className={styles.wrapper}>
|
||||
{pricing?.map((parking) => (
|
||||
<div key={parking.period} className={styles.period}>
|
||||
<div className={styles.information}>
|
||||
<Body textTransform="bold" color="uiTextHighContrast" asChild>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<dt>{getPeriod(intl, parking.period)}</dt>
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast" asChild>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<dd>
|
||||
{parking.amount
|
||||
? formatPrice(intl, parking.amount, currency)
|
||||
@@ -40,24 +44,17 @@ export default async function ParkingPrices({
|
||||
defaultMessage: "At a cost",
|
||||
})}
|
||||
</dd>
|
||||
</Body>
|
||||
</Typography>
|
||||
</div>
|
||||
{parking.startTime &&
|
||||
parking.endTime &&
|
||||
parking.period !== Periods.allDay && (
|
||||
<div className={styles.information}>
|
||||
<Body color="uiTextHighContrast" asChild>
|
||||
<dt>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "From",
|
||||
})}
|
||||
</dt>
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast" asChild>
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<div className={styles.information}>
|
||||
<dt>{intl.formatMessage({ defaultMessage: "From" })}</dt>
|
||||
<dd>{`${parking.startTime}-${parking.endTime}`}</dd>
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
display: grid;
|
||||
row-gap: var(--Spacing-x1);
|
||||
margin: 0;
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.period {
|
||||
@@ -13,3 +14,7 @@
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.priceHeading {
|
||||
color: var(--Text-Secondary);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import Link from "next/link"
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { getIntl } from "@/i18n"
|
||||
import ButtonLink from "@/components/ButtonLink"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
|
||||
import Button from "../TempDesignSystem/Button"
|
||||
import Divider from "../TempDesignSystem/Divider"
|
||||
import Caption from "../TempDesignSystem/Text/Caption"
|
||||
import Subtitle from "../TempDesignSystem/Text/Subtitle"
|
||||
import ParkingList from "./ParkingList"
|
||||
import ParkingPrices from "./ParkingPrices"
|
||||
|
||||
@@ -20,17 +20,19 @@ interface ParkingInformationProps {
|
||||
showExternalParkingButton?: boolean
|
||||
}
|
||||
|
||||
export default async function ParkingInformation({
|
||||
export default function ParkingInformation({
|
||||
parking,
|
||||
showExternalParkingButton = true,
|
||||
}: ParkingInformationProps) {
|
||||
const intl = await getIntl()
|
||||
const intl = useIntl()
|
||||
const title = `${parking.type}${parking.name ? ` (${parking.name})` : ""}`
|
||||
|
||||
return (
|
||||
<div className={styles.parkingInformation}>
|
||||
<div className={styles.list}>
|
||||
<Subtitle type="two" asChild>
|
||||
<h4>{parking.type}</h4>
|
||||
</Subtitle>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h4 className={styles.heading}>{title}</h4>
|
||||
</Typography>
|
||||
<ParkingList
|
||||
numberOfChargingSpaces={parking.numberOfChargingSpaces}
|
||||
canMakeReservation={parking.canMakeReservation}
|
||||
@@ -40,19 +42,17 @@ export default async function ParkingInformation({
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.prices}>
|
||||
<Subtitle type="two" asChild>
|
||||
<h5>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Prices",
|
||||
})}
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<h5 className={styles.heading}>
|
||||
{intl.formatMessage({ defaultMessage: "Prices" })}
|
||||
</h5>
|
||||
</Subtitle>
|
||||
</Typography>
|
||||
<div className={styles.priceWrapper}>
|
||||
<Caption color="uiTextMediumContrast" textTransform="uppercase">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Weekday prices",
|
||||
})}
|
||||
</Caption>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h6 className={styles.priceHeading}>
|
||||
{intl.formatMessage({ defaultMessage: "Weekday prices" })}
|
||||
</h6>
|
||||
</Typography>
|
||||
<Divider color="baseSurfaceSubtleHover" />
|
||||
{parking.pricing.localCurrency ? (
|
||||
<ParkingPrices
|
||||
@@ -63,11 +63,11 @@ export default async function ParkingInformation({
|
||||
) : null}
|
||||
</div>
|
||||
<div className={styles.priceWrapper}>
|
||||
<Caption color="uiTextMediumContrast" textTransform="uppercase">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Weekend prices",
|
||||
})}
|
||||
</Caption>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h6 className={styles.priceHeading}>
|
||||
{intl.formatMessage({ defaultMessage: "Weekend prices" })}
|
||||
</h6>
|
||||
</Typography>
|
||||
<Divider color="baseSurfaceSubtleHover" />
|
||||
{parking.pricing.localCurrency ? (
|
||||
<ParkingPrices
|
||||
@@ -79,14 +79,10 @@ export default async function ParkingInformation({
|
||||
</div>
|
||||
</div>
|
||||
{parking.externalParkingUrl && showExternalParkingButton && (
|
||||
<Button theme="base" intent="primary" variant="icon" asChild>
|
||||
<Link href={parking.externalParkingUrl} target="_blank">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Book parking",
|
||||
})}
|
||||
<MaterialIcon icon="open_in_new" color="CurrentColor" />
|
||||
</Link>
|
||||
</Button>
|
||||
<ButtonLink href={parking.externalParkingUrl} target="_blank">
|
||||
{intl.formatMessage({ defaultMessage: "Book parking" })}
|
||||
<MaterialIcon icon="open_in_new" color="CurrentColor" />
|
||||
</ButtonLink>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -16,3 +16,11 @@
|
||||
display: grid;
|
||||
gap: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.heading {
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.priceHeading {
|
||||
color: var(--Text-Secondary);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import AdditionalAmenities from "@/components/SidePeeks/AmenitiesSidepeekContent/AdditionalAmenities"
|
||||
import Accordion from "@/components/TempDesignSystem/Accordion"
|
||||
import SidePeek from "@/components/TempDesignSystem/SidePeek"
|
||||
|
||||
import AccessibilityAccordionItem from "../AmenitiesSidepeekContent/Accordions/Accessibility"
|
||||
import BreakfastAccordionItem from "../AmenitiesSidepeekContent/Accordions/Breakfast"
|
||||
import CheckInCheckOutAccordionItem from "../AmenitiesSidepeekContent/Accordions/CheckInCheckOut"
|
||||
import ParkingAccordionItem from "../AmenitiesSidepeekContent/Accordions/Parking"
|
||||
|
||||
import type { AmenitiesSidePeekProps } from "@/types/components/hotelReservation/amenitiesSidePeek"
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
export default function AmenitiesSidePeek({
|
||||
hotel,
|
||||
restaurants,
|
||||
additionalHotelData,
|
||||
activeSidePeek,
|
||||
close,
|
||||
}: AmenitiesSidePeekProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<SidePeek
|
||||
title={intl.formatMessage({ defaultMessage: "Amenities" })}
|
||||
isOpen={activeSidePeek === SidePeekEnum.amenities}
|
||||
handleClose={close}
|
||||
>
|
||||
<Accordion>
|
||||
<ParkingAccordionItem
|
||||
parking={hotel.parking}
|
||||
elevatorPitch={additionalHotelData?.hotelParking.elevatorPitch}
|
||||
/>
|
||||
<BreakfastAccordionItem
|
||||
restaurants={restaurants}
|
||||
hotelType={hotel.hotelType}
|
||||
/>
|
||||
<CheckInCheckOutAccordionItem checkInData={hotel.hotelFacts.checkin} />
|
||||
<AccessibilityAccordionItem
|
||||
elevatorPitch={additionalHotelData?.hotelSpecialNeeds.elevatorPitch}
|
||||
/>
|
||||
<AdditionalAmenities amenities={hotel.detailedFacilities} />
|
||||
</Accordion>
|
||||
</SidePeek>
|
||||
)
|
||||
}
|
||||
@@ -1,20 +1,26 @@
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import ButtonLink from "@/components/ButtonLink"
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./accessibilityAmenity.module.css"
|
||||
import styles from "./sidePeekAccordion.module.css"
|
||||
|
||||
import type { AccessibilityAmenityProps } from "@/types/components/hotelPage/sidepeek/accessibility"
|
||||
import type { AccessibilityAccordionItemProps } from "@/types/components/sidePeeks/amenities"
|
||||
|
||||
export default async function AccessibilityAmenity({
|
||||
export default function AccessibilityAccordionItem({
|
||||
elevatorPitch,
|
||||
accessibilityPageUrl,
|
||||
}: AccessibilityAmenityProps) {
|
||||
const intl = await getIntl()
|
||||
}: AccessibilityAccordionItemProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
if (!elevatorPitch && !accessibilityPageUrl) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
@@ -22,13 +28,14 @@ export default async function AccessibilityAmenity({
|
||||
defaultMessage: "Accessibility",
|
||||
})}
|
||||
iconName={IconName.Accessibility}
|
||||
className={styles.accordionItem}
|
||||
variant="sidepeek"
|
||||
trackingId="amenities:accessibility"
|
||||
>
|
||||
<div className={styles.wrapper}>
|
||||
{elevatorPitch && (
|
||||
<Body color="uiTextHighContrast">{elevatorPitch}</Body>
|
||||
)}
|
||||
<div className={styles.accessibilityContent}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{elevatorPitch}</p>
|
||||
</Typography>
|
||||
{accessibilityPageUrl && (
|
||||
<ButtonLink
|
||||
href={`/${accessibilityPageUrl}`}
|
||||
@@ -38,11 +45,7 @@ export default async function AccessibilityAmenity({
|
||||
typography="Body/Paragraph/mdBold"
|
||||
appendToCurrentPath
|
||||
>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "About accessibility",
|
||||
})}
|
||||
|
||||
<MaterialIcon icon="arrow_forward" color="CurrentColor" />
|
||||
{intl.formatMessage({ defaultMessage: "About accessibility" })}
|
||||
</ButtonLink>
|
||||
)}
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { isDefined } from "@/server/utils"
|
||||
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import OpeningHours from "@/components/OpeningHours"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
|
||||
import styles from "./sidePeekAccordion.module.css"
|
||||
|
||||
import type { BreakfastAccordionItemProps } from "@/types/components/sidePeeks/amenities"
|
||||
import { HotelTypeEnum } from "@/types/enums/hotelType"
|
||||
|
||||
export default function BreakfastAccordionItem({
|
||||
restaurants,
|
||||
hotelType,
|
||||
}: BreakfastAccordionItemProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
const openingHours = restaurants
|
||||
?.map((restaurant) => {
|
||||
const breakfastDetail = restaurant.openingDetails.find(
|
||||
(details) =>
|
||||
details.openingHours.name === "Breakfast" ||
|
||||
details.openingHours.name ===
|
||||
intl.formatMessage({ defaultMessage: "Breakfast" })
|
||||
)
|
||||
return breakfastDetail
|
||||
})
|
||||
.filter(isDefined)[0]
|
||||
|
||||
if (!openingHours && hotelType !== HotelTypeEnum.ScandicGo) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ defaultMessage: "Breakfast" })}
|
||||
iconName={IconName.CoffeeAlt}
|
||||
variant="sidepeek"
|
||||
className={styles.accordionItem}
|
||||
trackingId="amenities:breakfast"
|
||||
>
|
||||
{openingHours ? (
|
||||
<OpeningHours
|
||||
openingHours={openingHours.openingHours}
|
||||
alternateOpeningHours={openingHours.alternateOpeningHours}
|
||||
heading={intl.formatMessage({ defaultMessage: "Opening hours" })}
|
||||
/>
|
||||
) : (
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{intl.formatMessage({ defaultMessage: "All-day breakfast" })}</p>
|
||||
</Typography>
|
||||
)}
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
|
||||
import styles from "./sidePeekAccordion.module.css"
|
||||
|
||||
import type { CheckInCheckOutAccordionItemProps } from "@/types/components/sidePeeks/amenities"
|
||||
|
||||
export default function CheckInCheckOutAccordionItem({
|
||||
checkInData,
|
||||
}: CheckInCheckOutAccordionItemProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
const { checkInTime, checkOutTime } = checkInData
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ defaultMessage: "Check-in/Check-out" })}
|
||||
iconName={IconName.Business}
|
||||
variant="sidepeek"
|
||||
className={styles.accordionItem}
|
||||
trackingId="amenities:check-in"
|
||||
>
|
||||
<div className={styles.checkInCheckOutContent}>
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h4 className={styles.subheading}>
|
||||
{intl.formatMessage({ defaultMessage: "Hours" })}
|
||||
</h4>
|
||||
</Typography>
|
||||
<Divider color="Border/Divider/Default" />
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<div>
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ defaultMessage: "Check in from: {checkInTime}" },
|
||||
{
|
||||
checkInTime,
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ defaultMessage: "Check out at latest: {checkOutTime}" },
|
||||
{
|
||||
checkOutTime,
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Typography>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,19 +1,24 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import ButtonLink from "@/components/ButtonLink"
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import ParkingInformation from "@/components/ParkingInformation"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./parkingAmenity.module.css"
|
||||
import styles from "./sidePeekAccordion.module.css"
|
||||
|
||||
import type { ParkingAmenityProps } from "@/types/components/hotelPage/sidepeek/parking"
|
||||
import type { ParkingAccordionItemProps } from "@/types/components/sidePeeks/amenities"
|
||||
|
||||
export default async function ParkingAmenity({
|
||||
export default function ParkingAccordionItem({
|
||||
parking,
|
||||
parkingElevatorPitch,
|
||||
elevatorPitch,
|
||||
parkingPageUrl,
|
||||
}: ParkingAmenityProps) {
|
||||
const intl = await getIntl()
|
||||
}: ParkingAccordionItemProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
@@ -22,10 +27,15 @@ export default async function ParkingAmenity({
|
||||
})}
|
||||
iconName={IconName.Parking}
|
||||
variant="sidepeek"
|
||||
className={styles.accordionItem}
|
||||
trackingId="amenities:parking"
|
||||
>
|
||||
<div className={styles.wrapper}>
|
||||
{parkingElevatorPitch}
|
||||
<div className={styles.parkingContent}>
|
||||
{elevatorPitch ? (
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{elevatorPitch}</p>
|
||||
</Typography>
|
||||
) : null}
|
||||
{parking.map((data) => (
|
||||
<ParkingInformation key={data.type} parking={data} />
|
||||
))}
|
||||
@@ -0,0 +1,26 @@
|
||||
.accordionItem {
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.parkingContent,
|
||||
.accessibilityContent {
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
}
|
||||
|
||||
.checkInCheckOutContent {
|
||||
display: grid;
|
||||
gap: var(--Space-x15);
|
||||
}
|
||||
|
||||
.checkInCheckOutContent {
|
||||
display: grid;
|
||||
padding: var(--Space-x2) var(--Space-x3);
|
||||
gap: var(--Space-x1);
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
background: var(--Surface-Secondary-Default);
|
||||
}
|
||||
|
||||
.subheading {
|
||||
color: var(--Text-Secondary);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
.wrapper {
|
||||
padding: var(--Spacing-x1) var(--Spacing-x0);
|
||||
border-bottom: 1px solid var(--Base-Border-Subtle);
|
||||
color: var(--Text-Interactive-Default);
|
||||
}
|
||||
|
||||
.amenity {
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { FacilityToIcon } from "../../../ContentType/HotelPage/data"
|
||||
|
||||
import styles from "./additionalAmenities.module.css"
|
||||
|
||||
import type { AdditionalAmenitiesProps } from "@/types/components/sidePeeks/amenities"
|
||||
import { FacilityEnum } from "@/types/enums/facilities"
|
||||
|
||||
export default function AdditionalAmenities({
|
||||
amenities,
|
||||
}: AdditionalAmenitiesProps) {
|
||||
const amenitiesToIgnore = [
|
||||
FacilityEnum.ParkingAdditionalCost,
|
||||
FacilityEnum.ParkingElectricCharging,
|
||||
FacilityEnum.ParkingFreeParking,
|
||||
FacilityEnum.ParkingGarage,
|
||||
FacilityEnum.ParkingOutdoor,
|
||||
FacilityEnum.MeetingArea,
|
||||
FacilityEnum.ServesBreakfastAlwaysIncluded,
|
||||
FacilityEnum.LateCheckOutUntil1400Guaranteed,
|
||||
]
|
||||
|
||||
const filteredAmenities = amenities.filter(
|
||||
(amenity) => !amenitiesToIgnore.includes(amenity.id)
|
||||
)
|
||||
|
||||
return filteredAmenities?.map((amenity) => (
|
||||
<Typography key={amenity.name} variant="Title/Subtitle/md">
|
||||
<li className={styles.wrapper}>
|
||||
<div className={styles.amenity}>
|
||||
<FacilityToIcon
|
||||
id={amenity.id}
|
||||
color="Icon/Interactive/Default"
|
||||
size={24}
|
||||
/>
|
||||
{amenity.name}
|
||||
</div>
|
||||
</li>
|
||||
</Typography>
|
||||
))
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import type { AccessibilityProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
|
||||
export default function Accessibility({
|
||||
elevatorPitchText,
|
||||
}: AccessibilityProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Accessibility",
|
||||
})}
|
||||
iconName={IconName.Accessibility}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body>{elevatorPitchText}</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import type { CheckInCheckOutProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
|
||||
export default function CheckinCheckOut({ checkin }: CheckInCheckOutProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Check-in/Check-out",
|
||||
})}
|
||||
iconName={IconName.Calendar}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Hours",
|
||||
})}
|
||||
</Body>
|
||||
<Body>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Check in from: {checkInTime}",
|
||||
},
|
||||
{
|
||||
checkInTime: checkin.checkInTime,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
<Body>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Check out at latest: {checkOutTime}",
|
||||
},
|
||||
{
|
||||
checkOutTime: checkin.checkOutTime,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import type { MeetingsAndConferencesProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
|
||||
export default function MeetingsAndConferences({
|
||||
meetingDescription,
|
||||
}: MeetingsAndConferencesProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Meetings & Conferences",
|
||||
})}
|
||||
iconName={IconName.Business}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body>{meetingDescription}</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import styles from "./sidePeekAccordion.module.css"
|
||||
|
||||
import type { ParkingProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
|
||||
export default function Parking({ parking }: ParkingProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Parking",
|
||||
})}
|
||||
iconName={IconName.Parking}
|
||||
className={styles.parking}
|
||||
variant="sidepeek"
|
||||
>
|
||||
{parking.map((p) => {
|
||||
const title = `${p.type}${p.name ? ` (${p.name})` : ""}`
|
||||
|
||||
return (
|
||||
<div key={p.name}>
|
||||
<Subtitle type="two">{title}</Subtitle>
|
||||
<ul className={styles.list}>
|
||||
{p.address !== undefined && (
|
||||
<li>
|
||||
<MaterialIcon icon="favorite" isFilled color="Icon/Accent" />
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Address: {address}",
|
||||
},
|
||||
{
|
||||
address: p.address,
|
||||
}
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
{p.numberOfParkingSpots !== undefined && (
|
||||
<li>
|
||||
<MaterialIcon icon="favorite" isFilled color="Icon/Accent" />
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Number of parking spots: {number}",
|
||||
},
|
||||
{ number: p.numberOfParkingSpots }
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
{p.numberOfChargingSpaces !== undefined && (
|
||||
<li>
|
||||
<MaterialIcon icon="favorite" isFilled color="Icon/Accent" />
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"Number of charging points for electric cars: {number}",
|
||||
},
|
||||
{ number: p.numberOfChargingSpaces }
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { IconName } from "@/components/Icons/iconName"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import type { RestaurantProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
|
||||
export default function Restaurant({
|
||||
restaurantsContentDescriptionMedium,
|
||||
}: RestaurantProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"{totalRestaurants, plural, one {Restaurant} other {Restaurants}}",
|
||||
},
|
||||
{ totalRestaurants: 1 }
|
||||
)}
|
||||
iconName={IconName.Restaurant}
|
||||
variant="sidepeek"
|
||||
>
|
||||
<Body>{restaurantsContentDescriptionMedium}</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
.list {
|
||||
font-family: var(--typography-Body-Regular-fontFamily);
|
||||
list-style-position: inside;
|
||||
list-style-type: none;
|
||||
margin-top: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.list li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--Spacing-x1);
|
||||
padding-left: var(--Spacing-x1);
|
||||
justify-items: flex-start;
|
||||
}
|
||||
|
||||
.list li svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.parking details > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
@@ -1,35 +1,5 @@
|
||||
.spacing {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.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);
|
||||
}
|
||||
|
||||
.noIcon {
|
||||
margin-left: var(--Spacing-x4);
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import Contact from "@/components/HotelReservation/Contact"
|
||||
import AdditionalAmenities from "@/components/SidePeeks/AmenitiesSidepeekContent/AdditionalAmenities"
|
||||
import Accordion from "@/components/TempDesignSystem/Accordion"
|
||||
import SidePeek from "@/components/TempDesignSystem/SidePeek"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import Accessibility from "./Accordions/Accessibility"
|
||||
import CheckinCheckOut from "./Accordions/CheckInCheckOut"
|
||||
import MeetingsAndConferences from "./Accordions/MeetingsAndConferences"
|
||||
import Parking from "./Accordions/Parking"
|
||||
import Restaurant from "./Accordions/Restaurant"
|
||||
import AccessibilityAccordionItem from "../AmenitiesSidepeekContent/Accordions/Accessibility"
|
||||
import BreakfastAccordionItem from "../AmenitiesSidepeekContent/Accordions/Breakfast"
|
||||
import CheckInCheckOutAccordionItem from "../AmenitiesSidepeekContent/Accordions/CheckInCheckOut"
|
||||
import ParkingAccordionItem from "../AmenitiesSidepeekContent/Accordions/Parking"
|
||||
|
||||
import styles from "./hotelSidePeek.module.css"
|
||||
|
||||
@@ -19,17 +21,12 @@ import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
export default function HotelSidePeek({
|
||||
hotel,
|
||||
restaurants,
|
||||
additionalHotelData,
|
||||
activeSidePeek,
|
||||
close,
|
||||
}: HotelSidePeekProps) {
|
||||
const intl = useIntl()
|
||||
const amenitiesList = hotel.detailedFacilities.filter(
|
||||
(facility) => facility.public
|
||||
)
|
||||
const parking = hotel.parking.filter(
|
||||
(p) => p?.numberOfParkingSpots || p?.numberOfChargingSpaces || p?.address
|
||||
)
|
||||
|
||||
return (
|
||||
<SidePeek
|
||||
@@ -38,61 +35,30 @@ export default function HotelSidePeek({
|
||||
handleClose={close}
|
||||
>
|
||||
<div className={styles.content}>
|
||||
<Subtitle color="baseTextHighContrast">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Practical information",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h3>
|
||||
{intl.formatMessage({ defaultMessage: "Practical information" })}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Contact hotel={hotel} />
|
||||
<Accordion>
|
||||
{parking?.length > 0 && <Parking parking={parking} />}
|
||||
{additionalHotelData?.restaurantsOverviewPage
|
||||
?.restaurantsContentDescriptionMedium && (
|
||||
<Restaurant
|
||||
restaurantsContentDescriptionMedium={
|
||||
additionalHotelData.restaurantsOverviewPage
|
||||
.restaurantsContentDescriptionMedium
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{additionalHotelData?.hotelSpecialNeeds.elevatorPitch && (
|
||||
<Accessibility
|
||||
elevatorPitchText={
|
||||
additionalHotelData.hotelSpecialNeeds.elevatorPitch
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{hotel.hotelFacts?.checkin && (
|
||||
<CheckinCheckOut checkin={hotel.hotelFacts.checkin} />
|
||||
)}
|
||||
{hotel.hotelContent.texts?.meetingDescription?.medium && (
|
||||
<MeetingsAndConferences
|
||||
meetingDescription={
|
||||
hotel.hotelContent.texts.meetingDescription.medium
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Accordion>
|
||||
<div className={styles.amenity}>
|
||||
{amenitiesList.map((amenity) => {
|
||||
const Icon = (
|
||||
<FacilityToIcon id={amenity.id} size={24} color="Icon/Intense" />
|
||||
)
|
||||
return (
|
||||
<Subtitle type="two" key={amenity.id} color="uiTextHighContrast">
|
||||
{Icon && Icon}
|
||||
{amenity.name}
|
||||
</Subtitle>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* TODO: handle linking to Hotel Page */}
|
||||
{/* {showCTA && (
|
||||
<Button theme="base" intent="secondary" size="large">
|
||||
Read more about the hotel
|
||||
</Button>
|
||||
)} */}
|
||||
<Accordion>
|
||||
<ParkingAccordionItem
|
||||
parking={hotel.parking}
|
||||
elevatorPitch={additionalHotelData?.hotelParking.elevatorPitch}
|
||||
/>
|
||||
<BreakfastAccordionItem
|
||||
restaurants={restaurants}
|
||||
hotelType={hotel.hotelType}
|
||||
/>
|
||||
<CheckInCheckOutAccordionItem
|
||||
checkInData={hotel.hotelFacts.checkin}
|
||||
/>
|
||||
<AccessibilityAccordionItem
|
||||
elevatorPitch={additionalHotelData?.hotelSpecialNeeds.elevatorPitch}
|
||||
/>
|
||||
<AdditionalAmenities amenities={hotel.detailedFacilities} />
|
||||
</Accordion>
|
||||
</div>
|
||||
</SidePeek>
|
||||
)
|
||||
|
||||
@@ -32,7 +32,11 @@ export default function AccordionItem({
|
||||
const IconComp = icon
|
||||
? icon
|
||||
: iconName && (
|
||||
<IconByIconName iconName={iconName} color="Icon/Interactive/Default" />
|
||||
<IconByIconName
|
||||
iconName={iconName}
|
||||
color="Icon/Interactive/Default"
|
||||
size={24}
|
||||
/>
|
||||
)
|
||||
|
||||
function toggleAccordion() {
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{
|
||||
"+2LakC": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Invalid membership number format"
|
||||
}
|
||||
],
|
||||
"+CC2q2": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -547,8 +553,7 @@
|
||||
"value": "Please enter the code sent to "
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
],
|
||||
"children": [],
|
||||
"type": 8,
|
||||
"value": "maskedContactInfo"
|
||||
},
|
||||
@@ -901,6 +906,12 @@
|
||||
"value": "Log in/Join"
|
||||
}
|
||||
],
|
||||
"5cIDjn": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Booking code is invalid"
|
||||
}
|
||||
],
|
||||
"5kfntb": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -1009,6 +1020,12 @@
|
||||
"value": "Continue with new price"
|
||||
}
|
||||
],
|
||||
"6TXxwM": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Last name can't contain any special characters"
|
||||
}
|
||||
],
|
||||
"6U6gjS": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -1779,8 +1796,7 @@
|
||||
"value": "Please enter the code sent to "
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
],
|
||||
"children": [],
|
||||
"type": 8,
|
||||
"value": "maskedContactInfo"
|
||||
},
|
||||
@@ -2170,6 +2186,12 @@
|
||||
"value": "Find"
|
||||
}
|
||||
],
|
||||
"FPcbu0": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Please enter a valid phone number"
|
||||
}
|
||||
],
|
||||
"FZI5xl": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -2420,6 +2442,12 @@
|
||||
"value": "About accessibility"
|
||||
}
|
||||
],
|
||||
"HRrOrP": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Bed choice is required"
|
||||
}
|
||||
],
|
||||
"HW+bLl": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -2849,6 +2877,12 @@
|
||||
"value": "points"
|
||||
}
|
||||
],
|
||||
"KaH0vJ": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "You cannot have more children in adults bed than adults in the room"
|
||||
}
|
||||
],
|
||||
"KgkOn/": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -3497,6 +3531,12 @@
|
||||
"value": "See details"
|
||||
}
|
||||
],
|
||||
"RS5Kmw": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "New password is required"
|
||||
}
|
||||
],
|
||||
"RT3W/7": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -3641,6 +3681,12 @@
|
||||
"value": "Go back to My Pages"
|
||||
}
|
||||
],
|
||||
"Seanpx": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Required"
|
||||
}
|
||||
],
|
||||
"SjHZ7g": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -4005,6 +4051,12 @@
|
||||
"value": "You have cancelled to process to guarantee your booking."
|
||||
}
|
||||
],
|
||||
"Vp6BHv": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Must be at least 18 years of age to continue"
|
||||
}
|
||||
],
|
||||
"W1IuVy": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -4335,8 +4387,7 @@
|
||||
"value": "Please enter the code sent to "
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
],
|
||||
"children": [],
|
||||
"type": 8,
|
||||
"value": "maskedContactInfo"
|
||||
},
|
||||
@@ -4387,6 +4438,12 @@
|
||||
"value": "Select a rate"
|
||||
}
|
||||
],
|
||||
"YqklRf": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Destination required"
|
||||
}
|
||||
],
|
||||
"Z+d8/1": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -4697,6 +4754,12 @@
|
||||
"value": "Where to?"
|
||||
}
|
||||
],
|
||||
"boU1pG": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Code and voucher is not available with reward night."
|
||||
}
|
||||
],
|
||||
"bsUwPW": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -5247,6 +5310,12 @@
|
||||
"value": " (incl VAT)"
|
||||
}
|
||||
],
|
||||
"gq4AYf": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Only digits are allowed"
|
||||
}
|
||||
],
|
||||
"gttxKw": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -5349,6 +5418,12 @@
|
||||
"value": "Your transaction"
|
||||
}
|
||||
],
|
||||
"iZMEZ+": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Age is required"
|
||||
}
|
||||
],
|
||||
"iwtnXO": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -5439,6 +5514,12 @@
|
||||
"value": " cm"
|
||||
}
|
||||
],
|
||||
"jlqOPq": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Country is required"
|
||||
}
|
||||
],
|
||||
"jvo0vs": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -5557,6 +5638,12 @@
|
||||
"value": "destination"
|
||||
}
|
||||
],
|
||||
"ktyBmE": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Current password is required"
|
||||
}
|
||||
],
|
||||
"kvOMtB": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -6700,6 +6787,12 @@
|
||||
"value": "Paid"
|
||||
}
|
||||
],
|
||||
"u8II6t": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "First name can't contain any special characters"
|
||||
}
|
||||
],
|
||||
"uDm4Mt": [
|
||||
{
|
||||
"type": 1,
|
||||
@@ -6740,6 +6833,12 @@
|
||||
"value": "By adding a card you also guarantee your room booking for late arrival."
|
||||
}
|
||||
],
|
||||
"uiFoFm": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Password is required"
|
||||
}
|
||||
],
|
||||
"ujX0MU": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -6920,6 +7019,12 @@
|
||||
"value": "View your details"
|
||||
}
|
||||
],
|
||||
"vzqS9m": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Phone is required"
|
||||
}
|
||||
],
|
||||
"w0LSDs": [
|
||||
{
|
||||
"type": 1,
|
||||
@@ -6964,6 +7069,12 @@
|
||||
"value": "Sign up bonus"
|
||||
}
|
||||
],
|
||||
"wRUsWd": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Retype new password does not match new password"
|
||||
}
|
||||
],
|
||||
"wSh+Ly": [
|
||||
{
|
||||
"type": 1,
|
||||
@@ -7195,6 +7306,12 @@
|
||||
"value": "value"
|
||||
}
|
||||
],
|
||||
"yNJhk3": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Retype new password is required"
|
||||
}
|
||||
],
|
||||
"yP9SR1": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -7243,12 +7360,24 @@
|
||||
"value": "Last name is required"
|
||||
}
|
||||
],
|
||||
"yr+Os9": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Date of birth is required"
|
||||
}
|
||||
],
|
||||
"yxguVq": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Discard changes"
|
||||
}
|
||||
],
|
||||
"z7+EXa": [
|
||||
{
|
||||
"type": 0,
|
||||
"value": "Zip code is required"
|
||||
}
|
||||
],
|
||||
"zA7LuX": [
|
||||
{
|
||||
"type": 0,
|
||||
@@ -7359,4 +7488,4 @@
|
||||
"value": "Map"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
export type AccessibilityAmenityProps = {
|
||||
elevatorPitch?: string
|
||||
accessibilityPageUrl?: string
|
||||
}
|
||||
@@ -1,22 +1,19 @@
|
||||
import type { Hotel, Restaurant, RestaurantOpeningHours } from "@/types/hotel"
|
||||
import type { AccessibilityAmenityProps } from "./accessibility"
|
||||
import type {
|
||||
CheckInData,
|
||||
DetailedFacility,
|
||||
Hotel,
|
||||
Restaurant,
|
||||
} from "@/types/hotel"
|
||||
import type { ParkingAmenityProps } from "./parking"
|
||||
|
||||
export type AmenitiesSidePeekProps = {
|
||||
amenitiesList: Hotel["detailedFacilities"]
|
||||
amenitiesList: DetailedFacility[]
|
||||
parking: ParkingAmenityProps
|
||||
checkInInformation: Hotel["hotelFacts"]["checkin"]
|
||||
accessibility: AccessibilityAmenityProps
|
||||
checkInInformation: CheckInData
|
||||
accessibility: {
|
||||
elevatorPitch?: string
|
||||
accessibilityPageUrl?: string
|
||||
}
|
||||
restaurants: Restaurant[]
|
||||
hotelType: Hotel["hotelType"]
|
||||
}
|
||||
|
||||
export type FilteredAmenitiesProps = {
|
||||
filteredAmenities: Hotel["detailedFacilities"]
|
||||
}
|
||||
|
||||
export interface BreakfastAmenityProps {
|
||||
openingHours?: RestaurantOpeningHours
|
||||
alternateOpeningHours?: RestaurantOpeningHours
|
||||
hotelType: Hotel["hotelType"]
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import type { Hotel } from "@/types/hotel"
|
||||
|
||||
export type CheckInAmenityProps = {
|
||||
checkInInformation: Hotel["hotelFacts"]["checkin"]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import type { RestaurantOpeningHours } from "@/types/hotel"
|
||||
|
||||
export interface OpeningHoursProps {
|
||||
openingHours: RestaurantOpeningHours
|
||||
alternateOpeningHours?: RestaurantOpeningHours
|
||||
heading?: string
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import type { AdditionalData, Hotel, Restaurant } from "@/types/hotel"
|
||||
|
||||
export type AmenitiesSidePeekProps = {
|
||||
hotel: Hotel
|
||||
restaurants: Restaurant[]
|
||||
additionalHotelData: AdditionalData | undefined
|
||||
activeSidePeek: SidePeekEnum
|
||||
close: () => void
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import type { AdditionalData, Hotel } from "@/types/hotel"
|
||||
import type { AdditionalData, Hotel, Restaurant } from "@/types/hotel"
|
||||
|
||||
export type HotelSidePeekProps = {
|
||||
hotel: Hotel
|
||||
restaurants: Restaurant[]
|
||||
additionalHotelData: AdditionalData | undefined
|
||||
activeSidePeek: SidePeekEnum
|
||||
close: () => void
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { CheckInData, Hotel, Parking } from "@/types/hotel"
|
||||
import type { Hotel } from "@/types/hotel"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
import type { SidePeekEnum } from "../sidePeek"
|
||||
import type {
|
||||
AlternativeHotelsSearchParams,
|
||||
SelectHotelSearchParams,
|
||||
@@ -15,32 +16,13 @@ export interface ReadMoreProps {
|
||||
hotelId: string
|
||||
hotel: Hotel
|
||||
showCTA: boolean
|
||||
sidePeekKey: SidePeekEnum
|
||||
}
|
||||
|
||||
export interface ContactProps {
|
||||
hotel: Hotel
|
||||
}
|
||||
|
||||
export interface ParkingProps {
|
||||
parking: Parking[]
|
||||
}
|
||||
|
||||
export interface AccessibilityProps {
|
||||
elevatorPitchText: string
|
||||
}
|
||||
|
||||
export interface RestaurantProps {
|
||||
restaurantsContentDescriptionMedium: string
|
||||
}
|
||||
|
||||
export interface CheckInCheckOutProps {
|
||||
checkin: CheckInData
|
||||
}
|
||||
|
||||
export interface MeetingsAndConferencesProps {
|
||||
meetingDescription: string
|
||||
}
|
||||
|
||||
export interface SelectHotelProps {
|
||||
params: {
|
||||
lang: Lang
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export enum SidePeekEnum {
|
||||
hotelDetails = "hotel-detail-side-peek",
|
||||
amenities = "amenities-side-peek",
|
||||
roomDetails = "room-detail-side-peek",
|
||||
bookedRoomDetails = "booked-room-detail-side-peek",
|
||||
}
|
||||
|
||||
30
apps/scandic-web/types/components/sidePeeks/amenities.ts
Normal file
30
apps/scandic-web/types/components/sidePeeks/amenities.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import type {
|
||||
CheckInData,
|
||||
DetailedFacility,
|
||||
Parking,
|
||||
Restaurant,
|
||||
} from "@/types/hotel"
|
||||
|
||||
export interface ParkingAccordionItemProps {
|
||||
parkingPageUrl?: string
|
||||
parking: Parking[]
|
||||
elevatorPitch?: string
|
||||
}
|
||||
|
||||
export interface BreakfastAccordionItemProps {
|
||||
restaurants?: Restaurant[]
|
||||
hotelType: string
|
||||
}
|
||||
|
||||
export interface CheckInCheckOutAccordionItemProps {
|
||||
checkInData: CheckInData
|
||||
}
|
||||
|
||||
export interface AccessibilityAccordionItemProps {
|
||||
elevatorPitch?: string
|
||||
accessibilityPageUrl?: string
|
||||
}
|
||||
|
||||
export interface AdditionalAmenitiesProps {
|
||||
amenities: DetailedFacility[]
|
||||
}
|
||||
Reference in New Issue
Block a user