Merged in feat/SW-3002-new-hotel-move-tripadvisor (pull request #2375)
feat: SW-3002 Changed tripadvisor review subpage to Sidepeek * feat: SW-3002 Changed tripadvisor review subpage to Sidepeek * feat: SW-3002 Optimised styles Approved-by: Erik Tiekstra
This commit is contained in:
@@ -2,10 +2,10 @@ import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon
|
||||
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { appendSlugToPathname } from "@/utils/appendSlugToPathname"
|
||||
|
||||
import styles from "./tripAdvisorLink.module.css"
|
||||
|
||||
import { SidepeekSlugs } from "@/types/components/hotelPage/hotelPage"
|
||||
import type { HotelTripAdvisor } from "@/types/hotel"
|
||||
|
||||
interface TripAdvisorLinkProps {
|
||||
@@ -32,7 +32,7 @@ export default async function TripAdvisorLink({
|
||||
|
||||
const hasTripAdvisorIframeSrc = !!reviews.widgetScriptEmbedUrlIframe
|
||||
const tripAdvisorHref = hasTripAdvisorIframeSrc
|
||||
? await appendSlugToPathname("reviews")
|
||||
? `?s=${SidepeekSlugs.tripAdvisor}`
|
||||
: null
|
||||
|
||||
if (!tripAdvisorHref) {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import Image from "@/components/Image"
|
||||
import SidePeek from "@/components/TempDesignSystem/SidePeek"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { getLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./tripAdvisor.module.css"
|
||||
|
||||
import { SidepeekSlugs } from "@/types/components/hotelPage/hotelPage"
|
||||
import type { HotelRatings } from "@/types/hotel"
|
||||
|
||||
type TripAdvisorSidePeekProps = {
|
||||
hotelName: string
|
||||
hotelRatings: HotelRatings
|
||||
showNordicEcoLabel?: boolean
|
||||
}
|
||||
|
||||
export default async function TripAdvisorSidePeek({
|
||||
hotelName,
|
||||
hotelRatings,
|
||||
showNordicEcoLabel,
|
||||
}: TripAdvisorSidePeekProps) {
|
||||
const intl = await getIntl()
|
||||
const lang = await getLang()
|
||||
|
||||
const tripAdvisorData = hotelRatings?.tripAdvisor
|
||||
if (!tripAdvisorData?.reviews.widgetScriptEmbedUrlIframe) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const awardsLogos = tripAdvisorData.awards
|
||||
.map((award) => ({
|
||||
imageUrl: award.images.small,
|
||||
altText: award.displayName,
|
||||
}))
|
||||
.filter((award) => !!award.imageUrl)
|
||||
|
||||
const hotelHasAwards = showNordicEcoLabel || awardsLogos.length > 0
|
||||
|
||||
return (
|
||||
<SidePeek contentKey={SidepeekSlugs.tripAdvisor} title={hotelName}>
|
||||
<section className={styles.container}>
|
||||
{hotelHasAwards ? (
|
||||
<div className={styles.awards}>
|
||||
{showNordicEcoLabel ? (
|
||||
<Image
|
||||
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
|
||||
alt={intl.formatMessage({
|
||||
defaultMessage: "Nordic Swan Ecolabel",
|
||||
})}
|
||||
className={styles.logo}
|
||||
height={100}
|
||||
width={100}
|
||||
/>
|
||||
) : null}
|
||||
{awardsLogos?.map((award) => (
|
||||
<Image
|
||||
src={award.imageUrl}
|
||||
alt={award.altText}
|
||||
className={styles.logo}
|
||||
width={100}
|
||||
height={100}
|
||||
key={award.imageUrl}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
<main className={styles.main}>
|
||||
<iframe
|
||||
className={styles.iframe}
|
||||
src={tripAdvisorData.reviews.widgetScriptEmbedUrlIframe}
|
||||
loading="lazy"
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Ratings and reviews for {hotelName}",
|
||||
},
|
||||
{
|
||||
hotelName: hotelName,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</main>
|
||||
</section>
|
||||
</SidePeek>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.awards {
|
||||
border-radius: var(--Corner-radius-lg);
|
||||
background: var(--Surface-Primary-Default);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: var(--Space-x2) var(--Space-x15);
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
margin-bottom: var(--Space-x3);
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.iframe {
|
||||
width: 100%;
|
||||
border-width: 0;
|
||||
border-radius: var(--Corner-radius-lg);
|
||||
|
||||
/* Adjustments for devices with tiny screen height */
|
||||
min-height: max(50dvh, 300px);
|
||||
padding-bottom: var(--Space-x4);
|
||||
margin-bottom: calc(0% - var(--Space-x4));
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 100%;
|
||||
max-width: 120px;
|
||||
height: 100px;
|
||||
object-fit: contain;
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import AmenitiesSidePeek from "./SidePeeks/Amenities"
|
||||
import MeetingsAndConferencesSidePeek from "./SidePeeks/MeetingsAndConferences"
|
||||
import RestaurantBarSidePeek from "./SidePeeks/RestaurantBar"
|
||||
import RoomSidePeek from "./SidePeeks/Room"
|
||||
import TripAdvisorSidePeek from "./SidePeeks/Tripadvisor"
|
||||
import WellnessAndExerciseSidePeek from "./SidePeeks/WellnessAndExercise"
|
||||
import AmenitiesList from "./AmenitiesList"
|
||||
import DialogshiftWidget from "./DialogshiftWidget"
|
||||
@@ -222,6 +223,11 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
|
||||
</aside>
|
||||
<MobileMapToggle />
|
||||
<SidePeeks hotelId={hotelId}>
|
||||
<TripAdvisorSidePeek
|
||||
hotelName={hotel.name}
|
||||
hotelRatings={hotel.ratings}
|
||||
showNordicEcoLabel={hotel.hotelFacts?.ecoLabels.nordicEcoLabel}
|
||||
/>
|
||||
<AmenitiesSidePeek
|
||||
amenitiesList={detailedFacilities}
|
||||
parking={{
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
import { notFound } from "next/navigation"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import Breadcrumbs from "@/components/Breadcrumbs"
|
||||
import Image from "@/components/Image"
|
||||
import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { getLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./reviewsSubpage.module.css"
|
||||
|
||||
import type { Hotel } from "@/types/hotel"
|
||||
|
||||
interface ReviewsSubpageProps {
|
||||
hotel: Hotel
|
||||
}
|
||||
|
||||
export default async function ReviewsSubpage({ hotel }: ReviewsSubpageProps) {
|
||||
const intl = await getIntl()
|
||||
const lang = await getLang()
|
||||
const tripAdvisorData = hotel.ratings?.tripAdvisor
|
||||
|
||||
if (!tripAdvisorData?.reviews.widgetScriptEmbedUrlIframe) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const awardsLogos = tripAdvisorData.awards
|
||||
.map((award) => ({
|
||||
imageUrl: award.images.small,
|
||||
altText: award.displayName,
|
||||
}))
|
||||
.filter((award) => !!award.imageUrl)
|
||||
const showNordicEcoLabel = !!hotel.hotelFacts?.ecoLabels.nordicEcoLabel
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className={styles.reviewsSubpage}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<BreadcrumbsSkeleton
|
||||
size="contentWidth"
|
||||
color="Surface/Secondary/Default"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Breadcrumbs
|
||||
subpageTitle={intl.formatMessage({
|
||||
defaultMessage: "Reviews",
|
||||
})}
|
||||
size="contentWidth"
|
||||
color="Surface/Secondary/Default"
|
||||
/>
|
||||
</Suspense>
|
||||
<header className={styles.header}>
|
||||
<Typography variant="Title/md">
|
||||
<h1 className={styles.heading}>{hotel.name}</h1>
|
||||
</Typography>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<p className={styles.subheading}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Ratings and reviews",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</header>
|
||||
|
||||
<div className={styles.contentContainer}>
|
||||
<aside className={styles.sidebar}>
|
||||
<Typography variant="Title/xs">
|
||||
<h2 className={styles.sidebarHeading}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Awards and certifications",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
<div className={styles.sidebarContent}>
|
||||
{showNordicEcoLabel ? (
|
||||
<Image
|
||||
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
|
||||
alt={intl.formatMessage({
|
||||
defaultMessage: "Nordic Swan Ecolabel",
|
||||
})}
|
||||
className={styles.logo}
|
||||
height={100}
|
||||
width={100}
|
||||
/>
|
||||
) : null}
|
||||
{awardsLogos?.map((award) => (
|
||||
<Image
|
||||
src={award.imageUrl}
|
||||
alt={award.altText}
|
||||
className={styles.logo}
|
||||
width={100}
|
||||
height={100}
|
||||
key={award.imageUrl}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</aside>
|
||||
<main className={styles.mainContent}>
|
||||
<iframe
|
||||
className={styles.iframe}
|
||||
src={tripAdvisorData.reviews.widgetScriptEmbedUrlIframe}
|
||||
loading="lazy"
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Ratings and reviews for {hotelName}",
|
||||
},
|
||||
{
|
||||
hotelName: hotel.name,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
.reviewsSubpage {
|
||||
padding-bottom: var(--Space-x9);
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.header {
|
||||
width: var(--max-width-content);
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
padding: var(--Space-x4) 0;
|
||||
}
|
||||
|
||||
.heading,
|
||||
.sidebarHeading {
|
||||
color: var(--Text-Heading);
|
||||
}
|
||||
|
||||
.contentContainer {
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
width: var(--max-width-content);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: grid;
|
||||
gap: var(--Space-x3);
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.sidebarContent {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--Space-x7);
|
||||
padding: var(--Space-x5) var(--Space-x15);
|
||||
background-color: var(--Background-Secondary);
|
||||
border-radius: var(--Corner-radius-lg);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.iframe {
|
||||
width: 100%;
|
||||
height: 50dvh;
|
||||
border-width: 0;
|
||||
border-radius: var(--Corner-radius-lg);
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 100%;
|
||||
max-width: 120px;
|
||||
height: 100px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.iframe {
|
||||
height: 1150px; /* Maximum(ish) content height on desktop without the need of scrolling */
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1366px) {
|
||||
.subheading,
|
||||
.sidebarHeading {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.contentContainer {
|
||||
grid-template-columns: var(--max-width-text-block) 1fr;
|
||||
grid-template-areas: "main sidebar";
|
||||
gap: var(--Space-x9);
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
grid-area: main;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
grid-area: sidebar;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import AccessibilitySubpage from "./AccessibilitySubpage"
|
||||
import MeetingsSubpage from "./MeetingsSubpage"
|
||||
import ParkingSubpage from "./ParkingSubpage"
|
||||
import RestaurantSubpage from "./RestaurantSubpage"
|
||||
import ReviewsSubpage from "./ReviewsSubpage"
|
||||
import { verifySubpageShouldExist } from "./utils"
|
||||
import WellnessSubpage from "./WellnessSubpage"
|
||||
|
||||
@@ -71,8 +70,6 @@ export default async function HotelSubpage({
|
||||
additionalData={additionalData}
|
||||
/>
|
||||
)
|
||||
case "reviews":
|
||||
return <ReviewsSubpage hotel={hotel} />
|
||||
default:
|
||||
notFound()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ export enum SidepeekSlugs {
|
||||
restaurant = "restaurants",
|
||||
meetings = "meetings",
|
||||
wellness = "wellness",
|
||||
tripAdvisor = "tripAdvisor",
|
||||
}
|
||||
|
||||
export type HotelHashValue =
|
||||
|
||||
Reference in New Issue
Block a user