Merged in feat/SW-1051-amenities-in-sidepeek (pull request #1007)
feat(SW-1051): fix sidepeek select hotel page * feat(SW-1051): fix sidepeek select hotel page Approved-by: Niclas Edenvin
This commit is contained in:
@@ -13,7 +13,7 @@ export default function FooterMainNav({ mainLinks }: FooterMainNavProps) {
|
||||
<ul className={styles.mainNavigationList}>
|
||||
{mainLinks.map((link) => (
|
||||
<li key={link.title} className={styles.mainNavigationItem}>
|
||||
<Subtitle color="baseTextMediumContrast" type="two" asChild>
|
||||
<Subtitle color="baseTextHighContrast" type="two" asChild>
|
||||
<Link
|
||||
color="burgundy"
|
||||
href={link.url}
|
||||
@@ -40,7 +40,7 @@ export function FooterMainNavSkeleton() {
|
||||
<ul className={styles.mainNavigationList}>
|
||||
{items.map((x) => (
|
||||
<li key={x} className={styles.mainNavigationItem}>
|
||||
<Subtitle color="baseTextMediumContrast" type="two" asChild>
|
||||
<Subtitle color="baseTextHighContrast" type="two" asChild>
|
||||
<span className={styles.mainNavigationLink}>
|
||||
<SkeletonShimmer width="80%" />
|
||||
<ArrowRightIcon color="peach80" />
|
||||
|
||||
@@ -22,10 +22,6 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.soMeIcons {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
@@ -35,14 +31,20 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: var(--Spacing-x-one-and-half);
|
||||
grid-column: 2 / 3;
|
||||
grid-row: 3 / 4;
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 4 / 4;
|
||||
font-size: var(--typography-Footnote-Regular-fontSize);
|
||||
line-height: ();
|
||||
margin-bottom: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.ecoLabel img {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ecoLabelText {
|
||||
display: flex;
|
||||
color: var(--UI-Text-Medium-contrast);
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useIntl } from "react-intl"
|
||||
import { FacebookIcon, InstagramIcon } from "@/components/Icons"
|
||||
import Image from "@/components/Image"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import styles from "./contact.module.css"
|
||||
@@ -20,17 +21,17 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
<address className={styles.address}>
|
||||
<ul className={styles.contactInfo}>
|
||||
<li>
|
||||
<span className={styles.heading}>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Address" })}
|
||||
</span>
|
||||
<span>
|
||||
</Body>
|
||||
<Body>
|
||||
{`${hotel.address.streetAddress}, ${hotel.address.city}`}
|
||||
</span>
|
||||
</Body>
|
||||
</li>
|
||||
<li>
|
||||
<span className={styles.heading}>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Driving directions" })}
|
||||
</span>
|
||||
</Body>
|
||||
<a
|
||||
href={`https://www.google.com/maps/dir/?api=1&destination=${hotel.location.latitude},${hotel.location.longitude}`}
|
||||
className={styles.googleMaps}
|
||||
@@ -40,20 +41,9 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<span className={styles.heading}>
|
||||
{intl.formatMessage({ id: "Email" })}
|
||||
</span>
|
||||
<Link
|
||||
href={`mailto:${hotel.contactInformation.email}`}
|
||||
color="peach80"
|
||||
>
|
||||
{hotel.contactInformation.email}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<span className={styles.heading}>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Contact us" })}
|
||||
</span>
|
||||
</Body>
|
||||
<Link
|
||||
href={`tel:${hotel.contactInformation.phoneNumber}`}
|
||||
color="peach80"
|
||||
@@ -62,25 +52,44 @@ export default function Contact({ hotel }: ContactProps) {
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<span className={styles.heading}>
|
||||
{intl.formatMessage({ id: "Follow us" })}
|
||||
</span>
|
||||
<div className={styles.soMeIcons}>
|
||||
<Link href="#" target="_blank">
|
||||
<InstagramIcon color="burgundy" />
|
||||
</Link>
|
||||
<Link href="#" target="_blank">
|
||||
<FacebookIcon color="burgundy" />
|
||||
</Link>
|
||||
</div>
|
||||
{(hotel.socialMedia.facebook || hotel.socialMedia.instagram) && (
|
||||
<>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Follow us" })}
|
||||
</Body>
|
||||
<div className={styles.soMeIcons}>
|
||||
{hotel.socialMedia.instagram && (
|
||||
<Link href={hotel.socialMedia.instagram} target="_blank">
|
||||
<InstagramIcon color="burgundy" />
|
||||
</Link>
|
||||
)}
|
||||
{hotel.socialMedia.facebook && (
|
||||
<Link href={hotel.socialMedia.facebook} target="_blank">
|
||||
<FacebookIcon color="burgundy" />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<Body textTransform="bold">
|
||||
{intl.formatMessage({ id: "Email" })}
|
||||
</Body>
|
||||
<Link
|
||||
href={`mailto:${hotel.contactInformation.email}`}
|
||||
color="peach80"
|
||||
>
|
||||
{hotel.contactInformation.email}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</address>
|
||||
{hotel.hotelFacts.ecoLabels.nordicEcoLabel ? (
|
||||
{hotel.hotelFacts.ecoLabels?.nordicEcoLabel ? (
|
||||
<div className={styles.ecoLabel}>
|
||||
<Image
|
||||
height={38}
|
||||
width={38}
|
||||
width={43}
|
||||
alt={intl.formatMessage({ id: "Nordic Swan Ecolabel" })}
|
||||
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
|
||||
/>
|
||||
|
||||
27
components/Icons/FilledHeart.tsx
Normal file
27
components/Icons/FilledHeart.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { iconVariants } from "./variants"
|
||||
|
||||
import type { IconProps } from "@/types/components/icon"
|
||||
|
||||
export default function FilledHeartIcon({
|
||||
className,
|
||||
color,
|
||||
...props
|
||||
}: IconProps) {
|
||||
const classNames = iconVariants({ className, color })
|
||||
return (
|
||||
<svg
|
||||
className={classNames}
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M8.00091 13.4171L7.23424 12.7255C6.1424 11.7524 5.24166 10.9189 4.53203 10.2249C3.82239 9.53081 3.26322 8.91489 2.85451 8.37709C2.44579 7.8393 2.16246 7.34774 2.00451 6.90241C1.84656 6.45708 1.76758 6.00088 1.76758 5.53379C1.76758 4.57813 2.09533 3.77255 2.75083 3.11704C3.40634 2.46154 4.21192 2.13379 5.16758 2.13379C5.70411 2.13379 6.22436 2.25046 6.72831 2.48379C7.23227 2.71712 7.65647 3.05046 8.00091 3.48379C8.36202 3.05046 8.7898 2.71712 9.28425 2.48379C9.77869 2.25046 10.2954 2.13379 10.8342 2.13379C11.7899 2.13379 12.5955 2.46154 13.251 3.11704C13.9065 3.77255 14.2342 4.57813 14.2342 5.53379C14.2342 6.00088 14.158 6.45153 14.0056 6.88574C13.8533 7.31996 13.5727 7.80319 13.164 8.33542C12.7553 8.86767 12.1933 9.48637 11.4781 10.1915C10.7629 10.8967 9.84831 11.7524 8.73425 12.7588L8.00091 13.4171Z"
|
||||
fill="#B05B65"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import { AccessibilityProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { IconName } from "@/types/components/icon"
|
||||
|
||||
export default function Accessibility({
|
||||
accessibilityElevatorPitchText,
|
||||
}: AccessibilityProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Accessibility" })}
|
||||
icon={IconName.Accessibility}
|
||||
>
|
||||
<Body>{accessibilityElevatorPitchText}</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import { CheckInCheckOutProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { IconName } from "@/types/components/icon"
|
||||
|
||||
export default function CheckinCheckOut({ checkin }: CheckInCheckOutProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Check-in/Check-out" })}
|
||||
icon={IconName.Calendar}
|
||||
>
|
||||
<Body textTransform="bold">{intl.formatMessage({ id: "Hours" })}</Body>
|
||||
<Body>{`${intl.formatMessage({ id: "Check in from" })}: ${checkin.checkInTime}`}</Body>
|
||||
<Body>{`${intl.formatMessage({ id: "Check out at latest" })}: ${checkin.checkOutTime}`}</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import { MeetingsAndConferencesProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { IconName } from "@/types/components/icon"
|
||||
|
||||
export default function MeetingsAndConferences({
|
||||
meetingDescription,
|
||||
}: MeetingsAndConferencesProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Meetings & Conferences" })}
|
||||
icon={IconName.Business}
|
||||
>
|
||||
<Body>{meetingDescription}</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
55
components/SidePeeks/HotelSidePeek/Accordions/Parking.tsx
Normal file
55
components/SidePeeks/HotelSidePeek/Accordions/Parking.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import FilledHeartIcon from "@/components/Icons/FilledHeart"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import styles from "./sidePeekAccordion.module.css"
|
||||
|
||||
import { ParkingProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { IconName } from "@/types/components/icon"
|
||||
|
||||
export default function Parking({ parking }: ParkingProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Parking" })}
|
||||
icon={IconName.Parking}
|
||||
className={styles.parking}
|
||||
>
|
||||
{parking.map((p) => (
|
||||
<div key={p.name}>
|
||||
<Subtitle type="two">
|
||||
{`${intl.formatMessage({ id: p.type })} ${p?.name ? ` (${p.name})` : ""}`}
|
||||
</Subtitle>
|
||||
<ul className={styles.list}>
|
||||
{p?.address && (
|
||||
<li>
|
||||
<FilledHeartIcon color="baseIconLowContrast" />
|
||||
{`${intl.formatMessage({ id: "Address" })}: ${p.address}`}
|
||||
</li>
|
||||
)}
|
||||
{p?.numberOfParkingSpots !== undefined && (
|
||||
<li>
|
||||
<FilledHeartIcon color="baseIconLowContrast" />
|
||||
{intl.formatMessage(
|
||||
{ id: "Number of parking spots" },
|
||||
{ number: p.numberOfParkingSpots }
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
{p?.numberOfChargingSpaces !== undefined && (
|
||||
<li>
|
||||
<FilledHeartIcon color="baseIconLowContrast" />
|
||||
{intl.formatMessage(
|
||||
{ id: "Number of charging points for electric cars" },
|
||||
{ number: p.numberOfChargingSpaces }
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
22
components/SidePeeks/HotelSidePeek/Accordions/Restaurant.tsx
Normal file
22
components/SidePeeks/HotelSidePeek/Accordions/Restaurant.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
|
||||
import { RestaurantProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { IconName } from "@/types/components/icon"
|
||||
|
||||
export default function Restaurant({
|
||||
restaurantsContentDescriptionMedium,
|
||||
}: RestaurantProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Restaurant" }, { count: 1 })}
|
||||
icon={IconName.Restaurant}
|
||||
>
|
||||
<Body>{restaurantsContentDescriptionMedium}</Body>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
.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);
|
||||
}
|
||||
|
||||
.list li svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.parking details > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
@@ -22,8 +22,3 @@
|
||||
.noIcon {
|
||||
margin-left: var(--Spacing-x4);
|
||||
}
|
||||
|
||||
.list {
|
||||
font-family: var(--typography-Body-Regular-fontFamily);
|
||||
list-style: inside;
|
||||
}
|
||||
|
||||
@@ -2,29 +2,21 @@ import { useIntl } from "react-intl"
|
||||
|
||||
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
||||
import Contact from "@/components/HotelReservation/Contact"
|
||||
import { AccessibilityIcon } from "@/components/Icons"
|
||||
import Accordion from "@/components/TempDesignSystem/Accordion"
|
||||
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import SidePeek from "@/components/TempDesignSystem/SidePeek"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
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 styles from "./hotelSidePeek.module.css"
|
||||
|
||||
import type { HotelSidePeekProps } from "@/types/components/hotelReservation/hotelSidePeek"
|
||||
import type { ParkingProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import { IconName } from "@/types/components/icon"
|
||||
import type { Amenities, Hotel } from "@/types/hotel"
|
||||
|
||||
function getAmenitiesList(hotel: Hotel) {
|
||||
const detailedAmenities: Amenities = hotel.detailedFacilities.filter(
|
||||
// Remove Parking facilities since parking accordion is based on hotel.parking
|
||||
(facility) => !facility.name.startsWith("Parking") && facility.public
|
||||
)
|
||||
return detailedAmenities
|
||||
}
|
||||
|
||||
export default function HotelSidePeek({
|
||||
hotel,
|
||||
@@ -33,7 +25,12 @@ export default function HotelSidePeek({
|
||||
showCTA,
|
||||
}: HotelSidePeekProps) {
|
||||
const intl = useIntl()
|
||||
const amenitiesList = getAmenitiesList(hotel)
|
||||
const amenitiesList = hotel.detailedFacilities.filter(
|
||||
(facility) => facility.public
|
||||
)
|
||||
const parking = hotel.parking.filter(
|
||||
(p) => p?.numberOfParkingSpots || p?.numberOfChargingSpaces || p?.address
|
||||
)
|
||||
|
||||
return (
|
||||
<SidePeek
|
||||
@@ -42,30 +39,38 @@ export default function HotelSidePeek({
|
||||
handleClose={close}
|
||||
>
|
||||
<div className={styles.content}>
|
||||
<Subtitle>
|
||||
<Subtitle color="baseTextHighContrast">
|
||||
{intl.formatMessage({ id: "Practical information" })}
|
||||
</Subtitle>
|
||||
<Contact hotel={hotel} />
|
||||
<Accordion>
|
||||
{/* parking */}
|
||||
{hotel.parking.length ? (
|
||||
<AccordionItem
|
||||
title={intl.formatMessage({ id: "Parking" })}
|
||||
icon={IconName.Parking}
|
||||
>
|
||||
{hotel.parking.map((p) => (
|
||||
<Parking key={p.name} parking={p} />
|
||||
))}
|
||||
</AccordionItem>
|
||||
) : null}
|
||||
<div className={styles.amenity}>
|
||||
<AccessibilityIcon
|
||||
width={24}
|
||||
height={24}
|
||||
color="uiTextMediumContrast"
|
||||
{parking?.length > 0 && <Parking parking={parking} />}
|
||||
{hotel.hotelContent?.restaurantsOverviewPage
|
||||
?.restaurantsContentDescriptionMedium && (
|
||||
<Restaurant
|
||||
restaurantsContentDescriptionMedium={
|
||||
hotel.hotelContent.restaurantsOverviewPage
|
||||
.restaurantsContentDescriptionMedium
|
||||
}
|
||||
/>
|
||||
{intl.formatMessage({ id: "Accessibility" })}
|
||||
</div>
|
||||
)}
|
||||
{hotel?.accessibilityElevatorPitchText && (
|
||||
<Accessibility
|
||||
accessibilityElevatorPitchText={
|
||||
hotel.accessibilityElevatorPitchText
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{hotel.hotelFacts?.checkin && (
|
||||
<CheckinCheckOut checkin={hotel.hotelFacts.checkin} />
|
||||
)}
|
||||
{hotel.hotelContent.texts?.meetingDescription?.medium && (
|
||||
<MeetingsAndConferences
|
||||
meetingDescription={
|
||||
hotel.hotelContent.texts.meetingDescription.medium
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{amenitiesList.map((amenity) => {
|
||||
const Icon = mapFacilityToIcon(amenity.id)
|
||||
return (
|
||||
@@ -84,54 +89,13 @@ export default function HotelSidePeek({
|
||||
)
|
||||
})}
|
||||
</Accordion>
|
||||
{showCTA && (
|
||||
/* TODO: handle linking to Hotel Page */
|
||||
<Button theme={"base"}>To the hotel</Button>
|
||||
)}
|
||||
{/* TODO: handle linking to Hotel Page */}
|
||||
{/* {showCTA && (
|
||||
<Button theme="base" intent="secondary" size="large">
|
||||
Read more about the hotel
|
||||
</Button>
|
||||
)} */}
|
||||
</div>
|
||||
</SidePeek>
|
||||
)
|
||||
}
|
||||
|
||||
function Parking({ parking }: ParkingProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<div>
|
||||
<Body>
|
||||
{`${intl.formatMessage({ id: parking.type })}${parking?.name ? ` (${parking.name})` : ""}`}
|
||||
</Body>
|
||||
<ul className={styles.list}>
|
||||
{parking?.numberOfChargingSpaces !== undefined && (
|
||||
<li>
|
||||
{intl.formatMessage(
|
||||
{ id: "Number of charging points for electric cars" },
|
||||
{ number: parking.numberOfChargingSpaces }
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
{parking?.canMakeReservation && (
|
||||
<li>{`${intl.formatMessage({ id: "Parking can be reserved in advance" })}: ${parking.canMakeReservation ? intl.formatMessage({ id: "Yes" }) : intl.formatMessage({ id: "No" })}`}</li>
|
||||
)}
|
||||
{parking?.numberOfParkingSpots !== undefined && (
|
||||
<li>
|
||||
{intl.formatMessage(
|
||||
{ id: "Number of parking spots" },
|
||||
{ number: parking.numberOfParkingSpots }
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
{parking?.distanceToHotel !== undefined && (
|
||||
<li>
|
||||
{intl.formatMessage(
|
||||
{ id: "Distance to hotel" },
|
||||
{ distance: parking.distanceToHotel }
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
{parking?.address && (
|
||||
<li>{`${intl.formatMessage({ id: "Address" })}: ${parking.address}`}</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import { useRef } from "react"
|
||||
import { ChevronDownIcon } from "@/components/Icons"
|
||||
import { getIconByIconName } from "@/components/Icons/get-icon-by-icon-name"
|
||||
|
||||
import Body from "../../Text/Body"
|
||||
import Subtitle from "../../Text/Subtitle"
|
||||
import { accordionItemVariants } from "./variants"
|
||||
|
||||
import styles from "./accordionItem.module.css"
|
||||
@@ -49,7 +51,23 @@ export default function AccordionItem({
|
||||
<details ref={detailsRef} onToggle={toggleAccordion}>
|
||||
<summary className={styles.summary}>
|
||||
{IconComp && <IconComp className={styles.icon} color="burgundy" />}
|
||||
<span className={styles.title}>{title}</span>
|
||||
{variant === "card" ? (
|
||||
<Body
|
||||
textTransform="bold"
|
||||
color="baseTextHighContrast"
|
||||
className={styles.title}
|
||||
>
|
||||
{title}
|
||||
</Body>
|
||||
) : (
|
||||
<Subtitle
|
||||
className={styles.title}
|
||||
type="two"
|
||||
color="baseTextHighContrast"
|
||||
>
|
||||
{title}
|
||||
</Subtitle>
|
||||
)}
|
||||
<ChevronDownIcon
|
||||
className={styles.chevron}
|
||||
color="burgundy"
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
color: var(--Scandic-Brand-Pale-Peach);
|
||||
}
|
||||
|
||||
.baseTextMediumContrast {
|
||||
.baseTextHighContrast {
|
||||
color: var(--Base-Text-High-contrast);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ const config = {
|
||||
burgundy: styles.burgundy,
|
||||
baseTextDisabled: styles.baseTextDisabled,
|
||||
pale: styles.pale,
|
||||
baseTextMediumContrast: styles.baseTextMediumContrast,
|
||||
baseTextHighContrast: styles.baseTextHighContrast,
|
||||
uiTextHighContrast: styles.uiTextHighContrast,
|
||||
uiTextMediumContrast: styles.uiTextMediumContrast,
|
||||
uiTextPlaceholder: styles.uiTextPlaceholder,
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"Check out": "Check ud",
|
||||
"Check out at latest": "Udtjekning senest",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Tjek de kreditkort, der er gemt på din profil. Betal med et gemt kort, når du er logget ind for en mere jævn weboplevelse.",
|
||||
"Check-in/Check-out": "Indtjekning/Udtjekning",
|
||||
"Children": "børn",
|
||||
"Choose room": "Vælg rum",
|
||||
"Cities": "Byer",
|
||||
@@ -164,6 +165,7 @@
|
||||
"Hotel surroundings": "Hotel omgivelser",
|
||||
"Hotel(s)": "{amount} {amount, plural, one {hotel} other {hoteller}}",
|
||||
"Hotels": "Hoteller",
|
||||
"Hours": "Tider",
|
||||
"How do you want to sleep?": "Hvordan vil du sove?",
|
||||
"How it works": "Hvordan det virker",
|
||||
"Hurry up and use them before they expire!": "Skynd dig og brug dem, før de udløber!",
|
||||
@@ -257,6 +259,7 @@
|
||||
"Open menu": "Åbn menuen",
|
||||
"Open my pages menu": "Åbn mine sider menuen",
|
||||
"Opening Hours": "Åbningstider",
|
||||
"Outdoor": "Udendørs",
|
||||
"OutdoorPool": "Udendørs pool",
|
||||
"Overview": "Oversigt",
|
||||
"PETR": "Kæledyr",
|
||||
@@ -305,7 +308,7 @@
|
||||
"Relax": "Slap af",
|
||||
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
|
||||
"Request bedtype": "Anmod om sengetype",
|
||||
"Restaurant": "{count, plural, one {#Restaurant} other {#Restaurants}}",
|
||||
"Restaurant": "{count, plural, one {Restaurant} other {Restauranter}}",
|
||||
"Restaurant & Bar": "Restaurant & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Gentag den nye adgangskode",
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"Check out": "Auschecken",
|
||||
"Check out at latest": "Check-out spätestens",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Sehen Sie sich die in Ihrem Profil gespeicherten Kreditkarten an. Bezahlen Sie mit einer gespeicherten Karte, wenn Sie angemeldet sind, für ein reibungsloseres Web-Erlebnis.",
|
||||
"Check-in/Check-out": "Einchecken/Auschecken",
|
||||
"Children": "Kinder",
|
||||
"Choose room": "Zimmer wählen",
|
||||
"Cities": "Städte",
|
||||
@@ -164,6 +165,7 @@
|
||||
"Hotel surroundings": "Umgebung des Hotels",
|
||||
"Hotel(s)": "{amount} {amount, plural, one {hotel} other {hotels}}",
|
||||
"Hotels": "Hotels",
|
||||
"Hours": "Zeiten",
|
||||
"How do you want to sleep?": "Wie möchtest du schlafen?",
|
||||
"How it works": "Wie es funktioniert",
|
||||
"Hurry up and use them before they expire!": "Beeilen Sie sich und nutzen Sie sie, bevor sie ablaufen!",
|
||||
@@ -256,6 +258,7 @@
|
||||
"Open menu": "Menü öffnen",
|
||||
"Open my pages menu": "Meine Seiten Menü öffnen",
|
||||
"Opening Hours": "Öffnungszeiten",
|
||||
"Outdoor": "Im Freien",
|
||||
"OutdoorPool": "Außenpool",
|
||||
"Overview": "Übersicht",
|
||||
"PETR": "Haustier",
|
||||
@@ -304,7 +307,7 @@
|
||||
"Relax": "Entspannen",
|
||||
"Remove card from member profile": "Karte aus dem Mitgliedsprofil entfernen",
|
||||
"Request bedtype": "Bettentyp anfragen",
|
||||
"Restaurant": "{count, plural, one {#Restaurant} other {#Restaurants}}",
|
||||
"Restaurant": "{count, plural, one {Restaurant} other {Restaurants}}",
|
||||
"Restaurant & Bar": "Restaurant & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Neues Passwort erneut eingeben",
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
"Check out at latest": "Check out at latest",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.",
|
||||
"Check-in": "Check-in",
|
||||
"Check-in/Check-out": "Check-in/Check-out",
|
||||
"Check-out": "Check-out",
|
||||
"Child age is required": "Child age is required",
|
||||
"Children": "Children",
|
||||
@@ -182,6 +183,7 @@
|
||||
"Hotel surroundings": "Hotel surroundings",
|
||||
"Hotel(s)": "{amount} {amount, plural, one {hotel} other {hotels}}",
|
||||
"Hotels": "Hotels",
|
||||
"Hours": "Hours",
|
||||
"How do you want to sleep?": "How do you want to sleep?",
|
||||
"How it works": "How it works",
|
||||
"Hurry up and use them before they expire!": "Hurry up and use them before they expire!",
|
||||
@@ -284,6 +286,7 @@
|
||||
"Open menu": "Open menu",
|
||||
"Open my pages menu": "Open my pages menu",
|
||||
"Opening Hours": "Opening Hours",
|
||||
"Outdoor": "Outdoor",
|
||||
"OutdoorPool": "Outdoor pool",
|
||||
"Overview": "Overview",
|
||||
"PETR": "Pet",
|
||||
@@ -344,7 +347,7 @@
|
||||
"Request bedtype": "Request bedtype",
|
||||
"Reservation number": "Reservation number",
|
||||
"Reservation policy": "Reservation policy",
|
||||
"Restaurant": "{count, plural, one {#Restaurant} other {#Restaurants}}",
|
||||
"Restaurant": "{count, plural, one {Restaurant} other {Restaurants}}",
|
||||
"Restaurant & Bar": "Restaurant & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Retype new password",
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"Check out": "Uloskirjautuminen",
|
||||
"Check out at latest": "Uloskirjautuminen viimeistään",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Tarkista profiiliisi tallennetut luottokortit. Maksa tallennetulla kortilla kirjautuneena, jotta verkkokokemus on sujuvampi.",
|
||||
"Check-in/Check-out": "Sisäänkirjautuminen/Uloskirjautuminen",
|
||||
"Children": "Lasta",
|
||||
"Choose room": "Valitse huone",
|
||||
"Cities": "Kaupungit",
|
||||
@@ -164,6 +165,7 @@
|
||||
"Hotel surroundings": "Hotellin ympäristö",
|
||||
"Hotel(s)": "{amount} {amount, plural, one {hotelli} other {hotellit}}",
|
||||
"Hotels": "Hotellit",
|
||||
"Hours": "Ajat",
|
||||
"How do you want to sleep?": "Kuinka haluat nukkua?",
|
||||
"How it works": "Kuinka se toimii",
|
||||
"Hurry up and use them before they expire!": "Ole nopea ja käytä ne ennen kuin ne vanhenevat!",
|
||||
@@ -257,6 +259,7 @@
|
||||
"Open menu": "Avaa valikko",
|
||||
"Open my pages menu": "Avaa omat sivut -valikko",
|
||||
"Opening Hours": "Aukioloajat",
|
||||
"Outdoor": "Ulkona",
|
||||
"OutdoorPool": "Ulkouima-allas",
|
||||
"Overview": "Yleiskatsaus",
|
||||
"PETR": "Lemmikki",
|
||||
@@ -305,7 +308,7 @@
|
||||
"Relax": "Rentoutua",
|
||||
"Remove card from member profile": "Poista kortti jäsenprofiilista",
|
||||
"Request bedtype": "Pyydä sänkytyyppiä",
|
||||
"Restaurant": "{count, plural, one {#Ravintola} other {#Restaurants}}",
|
||||
"Restaurant": "{count, plural, one {Ravintola} other {Ravintolat}}",
|
||||
"Restaurant & Bar": "Ravintola & Baari",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Kirjoita uusi salasana uudelleen",
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"Check out": "Sjekk ut",
|
||||
"Check out at latest": "Utsjekking senest",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Sjekk ut kredittkortene som er lagret på profilen din. Betal med et lagret kort når du er pålogget for en jevnere nettopplevelse.",
|
||||
"Check-in/Check-out": "Innsjekking/Utsjekking",
|
||||
"Children": "Barn",
|
||||
"Choose room": "Velg rom",
|
||||
"Cities": "Byer",
|
||||
@@ -163,6 +164,7 @@
|
||||
"Hotel surroundings": "Hotellomgivelser",
|
||||
"Hotel(s)": "{amount} {amount, plural, one {hotell} other {hoteller}}",
|
||||
"Hotels": "Hoteller",
|
||||
"Hours": "Tider",
|
||||
"How do you want to sleep?": "Hvordan vil du sove?",
|
||||
"How it works": "Hvordan det fungerer",
|
||||
"Hurry up and use them before they expire!": "Skynd deg og bruk dem før de utløper!",
|
||||
@@ -255,6 +257,7 @@
|
||||
"Open menu": "Åpne menyen",
|
||||
"Open my pages menu": "Åpne mine sider menyen",
|
||||
"Opening Hours": "Åpningstider",
|
||||
"Outdoor": "Utendørs",
|
||||
"OutdoorPool": "Utendørs basseng",
|
||||
"Overview": "Oversikt",
|
||||
"PETR": "Kjæledyr",
|
||||
@@ -303,7 +306,7 @@
|
||||
"Relax": "Slappe av",
|
||||
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
|
||||
"Request bedtype": "Be om sengetype",
|
||||
"Restaurant": "{count, plural, one {#Restaurant} other {#Restaurants}}",
|
||||
"Restaurant": "{count, plural, one {Restaurant} other {Restauranter}}",
|
||||
"Restaurant & Bar": "Restaurant & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Skriv inn nytt passord på nytt",
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"Check out": "Checka ut",
|
||||
"Check out at latest": "Utcheckning senast",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Kolla in kreditkorten som sparats i din profil. Betala med ett sparat kort när du är inloggad för en smidigare webbupplevelse.",
|
||||
"Check-in/Check-out": "Inchecking/Utcheckning",
|
||||
"Children": "Barn",
|
||||
"Choose room": "Välj rum",
|
||||
"Cities": "Städer",
|
||||
@@ -163,6 +164,7 @@
|
||||
"Hotel surroundings": "Hotellomgivning",
|
||||
"Hotel(s)": "{amount} hotell",
|
||||
"Hotels": "Hotell",
|
||||
"Hours": "Tider",
|
||||
"How do you want to sleep?": "Hur vill du sova?",
|
||||
"How it works": "Hur det fungerar",
|
||||
"Hurry up and use them before they expire!": "Skynda dig och använd dem innan de går ut!",
|
||||
@@ -255,6 +257,7 @@
|
||||
"Open menu": "Öppna menyn",
|
||||
"Open my pages menu": "Öppna mina sidor menyn",
|
||||
"Opening Hours": "Öppettider",
|
||||
"Outdoor": "Utomhus",
|
||||
"OutdoorPool": "Utomhuspool",
|
||||
"Overview": "Översikt",
|
||||
"PETR": "Husdjur",
|
||||
@@ -303,7 +306,7 @@
|
||||
"Relax": "Koppla av",
|
||||
"Remove card from member profile": "Ta bort kortet från medlemsprofilen",
|
||||
"Request bedtype": "Request bedtype",
|
||||
"Restaurant": "{count, plural, one {#Restaurang} other {#Restauranger}}",
|
||||
"Restaurant": "{count, plural, one {Restaurang} other {Restauranger}}",
|
||||
"Restaurant & Bar": "Restaurang & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Upprepa nytt lösenord",
|
||||
|
||||
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
BIN
public/_static/img/icons/swan-eco/swan_eco_dark_de.png
Normal file
BIN
public/_static/img/icons/swan-eco/swan_eco_dark_de.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
@@ -56,7 +56,7 @@ const contactInformationSchema = z.object({
|
||||
websiteUrl: z.string(),
|
||||
})
|
||||
|
||||
const checkinSchema = z.object({
|
||||
export const checkinSchema = z.object({
|
||||
checkInTime: z.string(),
|
||||
checkOutTime: z.string(),
|
||||
onlineCheckOutAvailableFrom: z.string().nullable().optional(),
|
||||
@@ -110,6 +110,12 @@ const hotelContentSchema = z.object({
|
||||
short: z.string(),
|
||||
medium: z.string(),
|
||||
}),
|
||||
meetingDescription: z
|
||||
.object({
|
||||
short: z.string().optional(),
|
||||
medium: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
restaurantsOverviewPage: z.object({
|
||||
restaurantsOverviewPageLinkText: z.string().optional(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Hotel, ParkingData } from "@/types/hotel"
|
||||
import { CheckInData, Hotel, ParkingData } from "@/types/hotel"
|
||||
|
||||
export enum AvailabilityEnum {
|
||||
Available = "Available",
|
||||
@@ -17,5 +17,21 @@ export interface ContactProps {
|
||||
}
|
||||
|
||||
export interface ParkingProps {
|
||||
parking: ParkingData
|
||||
parking: ParkingData[]
|
||||
}
|
||||
|
||||
export interface AccessibilityProps {
|
||||
accessibilityElevatorPitchText: string
|
||||
}
|
||||
|
||||
export interface RestaurantProps {
|
||||
restaurantsContentDescriptionMedium: string
|
||||
}
|
||||
|
||||
export interface CheckInCheckOutProps {
|
||||
checkin: CheckInData
|
||||
}
|
||||
|
||||
export interface MeetingsAndConferencesProps {
|
||||
meetingDescription: string
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import {
|
||||
checkinSchema,
|
||||
facilitySchema,
|
||||
getHotelDataSchema,
|
||||
imageSchema,
|
||||
@@ -23,6 +24,7 @@ export type HotelTripAdvisor =
|
||||
|
||||
export type RoomData = z.infer<typeof roomSchema>
|
||||
export type GalleryImage = z.infer<typeof imageSchema>
|
||||
export type CheckInData = z.infer<typeof checkinSchema>
|
||||
|
||||
export type PointOfInterest = z.output<typeof pointOfInterestSchema>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user