feat(SW-750): add about the hotel sidepeek
This commit is contained in:
@@ -0,0 +1,47 @@
|
|||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--Spacing-x-one-and-half);
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: var(--Spacing-x2);
|
||||||
|
grid-template-areas:
|
||||||
|
"address drivingDirections"
|
||||||
|
"contact socials"
|
||||||
|
"email email"
|
||||||
|
"ecoLabel ecoLabel";
|
||||||
|
}
|
||||||
|
|
||||||
|
.address {
|
||||||
|
grid-area: address;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drivingDirections {
|
||||||
|
grid-area: drivingDirections;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact {
|
||||||
|
grid-area: contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socials {
|
||||||
|
grid-area: socials;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socialIcons {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--Spacing-x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.email {
|
||||||
|
grid-area: email;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ecoLabel {
|
||||||
|
grid-area: ecoLabel;
|
||||||
|
display: flex;
|
||||||
|
gap: var(--Spacing-x-one-and-half);
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
import { InstagramIcon } from "@/components/Icons"
|
||||||
|
import FacebookIcon from "@/components/Icons/Facebook"
|
||||||
|
import Image from "@/components/Image"
|
||||||
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
|
import { getIntl } from "@/i18n"
|
||||||
|
import { getLang } from "@/i18n/serverContext"
|
||||||
|
|
||||||
|
import styles from "./contactInformation.module.css"
|
||||||
|
|
||||||
|
import type { ContactInformationProps } from "@/types/components/hotelPage/sidepeek/contactInformation"
|
||||||
|
|
||||||
|
export default async function ContactInformation({
|
||||||
|
adress,
|
||||||
|
coordinates,
|
||||||
|
contact,
|
||||||
|
socials,
|
||||||
|
ecoLabels,
|
||||||
|
}: ContactInformationProps) {
|
||||||
|
const intl = await getIntl()
|
||||||
|
const lang = getLang()
|
||||||
|
return (
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<Subtitle color="burgundy">
|
||||||
|
{intl.formatMessage({ id: "Practical information" })}
|
||||||
|
</Subtitle>
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<div className={styles.address}>
|
||||||
|
<Body textTransform="bold">
|
||||||
|
{intl.formatMessage({ id: "Address" })}
|
||||||
|
</Body>
|
||||||
|
<Body color="uiTextHighContrast">{adress.streetAddress}</Body>
|
||||||
|
<Body color="uiTextHighContrast">{adress.city}</Body>
|
||||||
|
</div>
|
||||||
|
<div className={styles.drivingDirections}>
|
||||||
|
<Body textTransform="bold">
|
||||||
|
{intl.formatMessage({ id: "Driving directions" })}
|
||||||
|
</Body>
|
||||||
|
<Link
|
||||||
|
href={`https://www.google.com/maps/dir/?api=1&destination=${coordinates.lat},${coordinates.lng}`}
|
||||||
|
target="_blank"
|
||||||
|
color="peach80"
|
||||||
|
textDecoration="underline"
|
||||||
|
>
|
||||||
|
Google Maps
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className={styles.contact}>
|
||||||
|
<Body textTransform="bold">
|
||||||
|
{intl.formatMessage({ id: "Contact us" })}
|
||||||
|
</Body>
|
||||||
|
<Body>
|
||||||
|
<Link
|
||||||
|
href={`tel:+${contact.phoneNumber}`}
|
||||||
|
color="peach80"
|
||||||
|
textDecoration="underline"
|
||||||
|
>
|
||||||
|
{contact.phoneNumber}
|
||||||
|
</Link>
|
||||||
|
</Body>
|
||||||
|
</div>
|
||||||
|
<div className={styles.socials}>
|
||||||
|
<Body textTransform="bold">
|
||||||
|
{intl.formatMessage({ id: "Follow us" })}
|
||||||
|
</Body>
|
||||||
|
<div className={styles.socialIcons}>
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
socials.instagram || "https://www.instagram.com/scandichotels/"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<InstagramIcon color="burgundy" />
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href={socials.facebook || "https://www.facebook.com/Scandic/"}
|
||||||
|
>
|
||||||
|
<FacebookIcon color="burgundy" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.email}>
|
||||||
|
<Body textTransform="bold">
|
||||||
|
{intl.formatMessage({ id: "Email" })}
|
||||||
|
</Body>
|
||||||
|
<Link
|
||||||
|
href={`mailto:${contact.email}`}
|
||||||
|
color="peach80"
|
||||||
|
textDecoration="underline"
|
||||||
|
>
|
||||||
|
{contact.email}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
{ecoLabels.nordicEcoLabel ? (
|
||||||
|
<div className={styles.ecoLabel}>
|
||||||
|
<Image
|
||||||
|
height={38}
|
||||||
|
width={38}
|
||||||
|
alt={intl.formatMessage({ id: "Nordic Swan Ecolabel" })}
|
||||||
|
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<Caption color="uiTextPlaceholder">
|
||||||
|
{intl.formatMessage({ id: "Nordic Swan Ecolabel" })}
|
||||||
|
</Caption>
|
||||||
|
<Caption color="uiTextPlaceholder">
|
||||||
|
{ecoLabels.svanenEcoLabelCertificateNumber}
|
||||||
|
</Caption>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--Spacing-x3);
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { about } from "@/constants/routes/hotelPageParams"
|
||||||
|
|
||||||
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
import Divider from "@/components/TempDesignSystem/Divider"
|
||||||
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
|
import SidePeek from "@/components/TempDesignSystem/SidePeek"
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
|
import Preamble from "@/components/TempDesignSystem/Text/Preamble"
|
||||||
|
import { getIntl } from "@/i18n"
|
||||||
|
import { getLang } from "@/i18n/serverContext"
|
||||||
|
|
||||||
|
import ContactInformation from "./ContactInformation"
|
||||||
|
|
||||||
|
import styles from "./aboutTheHotel.module.css"
|
||||||
|
|
||||||
|
import type { AboutTheHotelSidePeekProps } from "@/types/components/hotelPage/sidepeek/aboutTheHotel"
|
||||||
|
|
||||||
|
export default async function AboutTheHotelSidePeek({
|
||||||
|
hotelAdress,
|
||||||
|
coordinates,
|
||||||
|
contact,
|
||||||
|
socials,
|
||||||
|
ecoLabels,
|
||||||
|
descriptions,
|
||||||
|
}: AboutTheHotelSidePeekProps) {
|
||||||
|
const lang = getLang()
|
||||||
|
const intl = await getIntl()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SidePeek
|
||||||
|
contentKey={about[lang]}
|
||||||
|
title={intl.formatMessage({ id: "About the hotel" })}
|
||||||
|
>
|
||||||
|
<section className={styles.wrapper}>
|
||||||
|
<ContactInformation
|
||||||
|
adress={hotelAdress}
|
||||||
|
coordinates={coordinates}
|
||||||
|
contact={contact}
|
||||||
|
socials={socials}
|
||||||
|
ecoLabels={ecoLabels}
|
||||||
|
/>
|
||||||
|
<Divider color="baseSurfaceSutbleHover" />
|
||||||
|
<Preamble>{descriptions.short}</Preamble>
|
||||||
|
<Body>{descriptions.medium}</Body>
|
||||||
|
<Button fullWidth theme="base" intent="secondary" asChild>
|
||||||
|
<Link href="#" color="burgundy" weight="bold">
|
||||||
|
{intl.formatMessage({ id: "Read more about the hotel" })}
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</section>
|
||||||
|
</SidePeek>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ import MapCard from "./Map/MapCard"
|
|||||||
import MapWithCardWrapper from "./Map/MapWithCard"
|
import MapWithCardWrapper from "./Map/MapWithCard"
|
||||||
import MobileMapToggle from "./Map/MobileMapToggle"
|
import MobileMapToggle from "./Map/MobileMapToggle"
|
||||||
import StaticMap from "./Map/StaticMap"
|
import StaticMap from "./Map/StaticMap"
|
||||||
|
import AboutTheHotelSidePeek from "./SidePeeks/AboutTheHotel"
|
||||||
import WellnessAndExerciseSidePeek from "./SidePeeks/WellnessAndExercise"
|
import WellnessAndExerciseSidePeek from "./SidePeeks/WellnessAndExercise"
|
||||||
import AmenitiesList from "./AmenitiesList"
|
import AmenitiesList from "./AmenitiesList"
|
||||||
import Facilities from "./Facilities"
|
import Facilities from "./Facilities"
|
||||||
@@ -54,6 +55,9 @@ export default async function HotelPage() {
|
|||||||
faq,
|
faq,
|
||||||
alerts,
|
alerts,
|
||||||
healthFacilities,
|
healthFacilities,
|
||||||
|
contact,
|
||||||
|
socials,
|
||||||
|
ecoLabels,
|
||||||
} = hotelData
|
} = hotelData
|
||||||
|
|
||||||
const topThreePois = pointsOfInterest.slice(0, 3)
|
const topThreePois = pointsOfInterest.slice(0, 3)
|
||||||
@@ -80,7 +84,7 @@ export default async function HotelPage() {
|
|||||||
<div className={styles.introContainer}>
|
<div className={styles.introContainer}>
|
||||||
<IntroSection
|
<IntroSection
|
||||||
hotelName={hotelName}
|
hotelName={hotelName}
|
||||||
hotelDescription={hotelDescription}
|
hotelDescription={hotelDescription.short}
|
||||||
location={hotelLocation}
|
location={hotelLocation}
|
||||||
address={hotelAddress}
|
address={hotelAddress}
|
||||||
tripAdvisor={hotelRatings?.tripAdvisor}
|
tripAdvisor={hotelRatings?.tripAdvisor}
|
||||||
@@ -134,12 +138,14 @@ export default async function HotelPage() {
|
|||||||
{/* TODO: Render amenities as per the design. */}
|
{/* TODO: Render amenities as per the design. */}
|
||||||
Read more about the amenities here
|
Read more about the amenities here
|
||||||
</SidePeek>
|
</SidePeek>
|
||||||
<SidePeek
|
<AboutTheHotelSidePeek
|
||||||
contentKey={hotelPageParams.about[lang]}
|
hotelAdress={hotelAddress}
|
||||||
title={intl.formatMessage({ id: "Read more about the hotel" })}
|
coordinates={coordinates}
|
||||||
>
|
contact={contact}
|
||||||
Some additional information about the hotel
|
socials={socials}
|
||||||
</SidePeek>
|
ecoLabels={ecoLabels}
|
||||||
|
descriptions={hotelDescription}
|
||||||
|
/>
|
||||||
<SidePeek
|
<SidePeek
|
||||||
contentKey={hotelPageParams.restaurantAndBar[lang]}
|
contentKey={hotelPageParams.restaurantAndBar[lang]}
|
||||||
title={intl.formatMessage({ id: "Restaurant & Bar" })}
|
title={intl.formatMessage({ id: "Restaurant & Bar" })}
|
||||||
|
|||||||
@@ -51,3 +51,7 @@
|
|||||||
.opacity8 {
|
.opacity8 {
|
||||||
opacity: 0.08;
|
opacity: 0.08;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.baseSurfaceSubtleHover {
|
||||||
|
background-color: var(--Base-Surface-Subtle-Hover);
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const dividerVariants = cva(styles.divider, {
|
|||||||
primaryLightSubtle: styles.primaryLightSubtle,
|
primaryLightSubtle: styles.primaryLightSubtle,
|
||||||
subtle: styles.subtle,
|
subtle: styles.subtle,
|
||||||
white: styles.white,
|
white: styles.white,
|
||||||
|
baseSurfaceSutbleHover: styles.baseSurfaceSubtleHover,
|
||||||
},
|
},
|
||||||
opacity: {
|
opacity: {
|
||||||
100: styles.opacity100,
|
100: styles.opacity100,
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ export const hotelQueryRouter = router({
|
|||||||
return {
|
return {
|
||||||
hotelId,
|
hotelId,
|
||||||
hotelName: hotelAttributes.name,
|
hotelName: hotelAttributes.name,
|
||||||
hotelDescription: hotelAttributes.hotelContent.texts.descriptions.short,
|
hotelDescription: hotelAttributes.hotelContent.texts.descriptions,
|
||||||
hotelLocation: hotelAttributes.location,
|
hotelLocation: hotelAttributes.location,
|
||||||
hotelAddress: hotelAttributes.address,
|
hotelAddress: hotelAttributes.address,
|
||||||
hotelRatings: hotelAttributes.ratings,
|
hotelRatings: hotelAttributes.ratings,
|
||||||
@@ -355,6 +355,9 @@ export const hotelQueryRouter = router({
|
|||||||
alerts: hotelAlerts,
|
alerts: hotelAlerts,
|
||||||
faq: contentstackData?.faq,
|
faq: contentstackData?.faq,
|
||||||
healthFacilities: hotelAttributes.healthFacilities,
|
healthFacilities: hotelAttributes.healthFacilities,
|
||||||
|
contact: hotelAttributes.contactInformation,
|
||||||
|
socials: hotelAttributes.socialMedia,
|
||||||
|
ecoLabels: hotelAttributes.hotelFacts.ecoLabels,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
availability: router({
|
availability: router({
|
||||||
|
|||||||
13
types/components/hotelPage/sidepeek/aboutTheHotel.ts
Normal file
13
types/components/hotelPage/sidepeek/aboutTheHotel.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import type { Hotel, HotelAddress } from "@/types/hotel"
|
||||||
|
|
||||||
|
export type AboutTheHotelSidePeekProps = {
|
||||||
|
hotelAdress: HotelAddress
|
||||||
|
coordinates: {
|
||||||
|
lat: number
|
||||||
|
lng: number
|
||||||
|
}
|
||||||
|
contact: Hotel["contactInformation"]
|
||||||
|
socials: Hotel["socialMedia"]
|
||||||
|
ecoLabels: Hotel["hotelFacts"]["ecoLabels"]
|
||||||
|
descriptions: Hotel["hotelContent"]["texts"]["descriptions"]
|
||||||
|
}
|
||||||
12
types/components/hotelPage/sidepeek/contactInformation.ts
Normal file
12
types/components/hotelPage/sidepeek/contactInformation.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import type { Hotel, HotelAddress } from "@/types/hotel"
|
||||||
|
|
||||||
|
export type ContactInformationProps = {
|
||||||
|
adress: HotelAddress
|
||||||
|
coordinates: {
|
||||||
|
lat: number
|
||||||
|
lng: number
|
||||||
|
}
|
||||||
|
contact: Hotel["contactInformation"]
|
||||||
|
socials: Hotel["socialMedia"]
|
||||||
|
ecoLabels: Hotel["hotelFacts"]["ecoLabels"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user