Merged in fix/BOOK-210-update-hotel-card-local-charges (pull request #2835)
fix(BOOK-210): add local charges for Finland and update design for hotel card * fix(BOOK-210): add local charges for Finland and update design for hotel card * feat(BOOK-210): change variant to conditional classname * fix(BOOK-210): update link with icon * fix(BOOK-210): update buttonlink tripadvisor * fix(BOOK-210): switch wrapper logic * fix(BOOK-210): update variants tripadvisor Approved-by: Erik Tiekstra
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./tripAdvisorLink.module.css"
|
||||
|
||||
import type { HotelTripAdvisor } from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
import { SidepeekSlugs } from "@/types/components/hotelPage/hotelPage"
|
||||
|
||||
interface TripAdvisorLinkProps {
|
||||
tripAdvisor: NonNullable<HotelTripAdvisor>
|
||||
}
|
||||
|
||||
export default async function TripAdvisorLink({
|
||||
tripAdvisor,
|
||||
}: TripAdvisorLinkProps) {
|
||||
const intl = await getIntl()
|
||||
const { rating, numberOfReviews, reviews } = tripAdvisor
|
||||
const hasTripAdvisorData = !!(rating && numberOfReviews)
|
||||
|
||||
if (!hasTripAdvisorData) {
|
||||
return null
|
||||
}
|
||||
|
||||
const formattedTripAdvisorText = intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{rating} ({count} reviews on Tripadvisor)",
|
||||
},
|
||||
{ rating, count: numberOfReviews }
|
||||
)
|
||||
|
||||
const hasTripAdvisorIframeSrc = !!reviews.widgetScriptEmbedUrlIframe
|
||||
const tripAdvisorHref = hasTripAdvisorIframeSrc
|
||||
? `?s=${SidepeekSlugs.tripAdvisor}`
|
||||
: null
|
||||
|
||||
if (!tripAdvisorHref) {
|
||||
return (
|
||||
<span className={styles.tripAdvisorText}>
|
||||
<TripadvisorIcon color="CurrentColor" />
|
||||
{formattedTripAdvisorText}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
variant="icon"
|
||||
textDecoration="underline"
|
||||
color="Text/Interactive/Secondary"
|
||||
size="small"
|
||||
href={tripAdvisorHref}
|
||||
>
|
||||
<TripadvisorIcon color="CurrentColor" size={20} />
|
||||
{formattedTripAdvisorText}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
.tripAdvisorText {
|
||||
display: flex;
|
||||
gap: var(--Space-x05);
|
||||
align-items: center;
|
||||
color: var(--Text-Secondary);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import ButtonLink from "@scandic-hotels/design-system/ButtonLink"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { TripAdvisorChip } from "@scandic-hotels/design-system/TripAdvisorChip"
|
||||
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./tripAdvisorSection.module.css"
|
||||
|
||||
import type { HotelTripAdvisor } from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
import { SidepeekSlugs } from "@/types/components/hotelPage/hotelPage"
|
||||
|
||||
interface TripAdvisorSectionProps {
|
||||
tripAdvisor: NonNullable<HotelTripAdvisor>
|
||||
}
|
||||
|
||||
export default async function TripAdvisorSection({
|
||||
tripAdvisor,
|
||||
}: TripAdvisorSectionProps) {
|
||||
const intl = await getIntl()
|
||||
const { rating, numberOfReviews, reviews } = tripAdvisor
|
||||
const hasTripAdvisorData = !!(rating && numberOfReviews)
|
||||
|
||||
if (!hasTripAdvisorData) {
|
||||
return null
|
||||
}
|
||||
|
||||
const formattedTripAdvisorText = intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{count} reviews",
|
||||
},
|
||||
{ count: numberOfReviews }
|
||||
)
|
||||
|
||||
const hasTripAdvisorIframeSrc = !!reviews.widgetScriptEmbedUrlIframe
|
||||
const tripAdvisorHref = hasTripAdvisorIframeSrc
|
||||
? `?s=${SidepeekSlugs.tripAdvisor}`
|
||||
: null
|
||||
|
||||
if (!tripAdvisorHref) {
|
||||
return (
|
||||
<TripAdvisorChip
|
||||
rating={tripAdvisor.rating}
|
||||
color="subtle"
|
||||
wrapper={false}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.tripAdvisorSection}>
|
||||
<TripAdvisorChip
|
||||
rating={tripAdvisor.rating}
|
||||
color="subtle"
|
||||
wrapper={false}
|
||||
/>
|
||||
<ButtonLink
|
||||
href={tripAdvisorHref}
|
||||
variant="Text"
|
||||
color="Primary"
|
||||
size="Small"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
wrapping={false}
|
||||
>
|
||||
{formattedTripAdvisorText}
|
||||
<MaterialIcon icon="chevron_right" color="CurrentColor" size={20} />
|
||||
</ButtonLink>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.tripAdvisorSection {
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
import { cx } from "class-variance-authority"
|
||||
|
||||
import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import ButtonLink from "@scandic-hotels/design-system/ButtonLink"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { Country } from "@scandic-hotels/trpc/types/country"
|
||||
|
||||
import LocalCallCharges from "@/components/LocalCallCharges"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import TripAdvisorLink from "./TripAdvisorLink"
|
||||
import TripAdvisorSection from "./TripAdvisorSection"
|
||||
|
||||
import styles from "./introSection.module.css"
|
||||
|
||||
@@ -37,7 +42,7 @@ export default async function IntroSection({
|
||||
phoneNumber,
|
||||
}: IntroSectionProps) {
|
||||
const intl = await getIntl()
|
||||
const { streetAddress, city } = address
|
||||
const { streetAddress, city, country } = address
|
||||
const { distanceToCentre } = location
|
||||
const formattedDistanceText = intl.formatMessage(
|
||||
{
|
||||
@@ -48,6 +53,8 @@ export default async function IntroSection({
|
||||
|
||||
const formattedLocationText = `${streetAddress}, ${city} (${formattedDistanceText})`
|
||||
|
||||
const showLocalCharges = country === Country.Finland
|
||||
|
||||
return (
|
||||
<section className={styles.introSection}>
|
||||
<div className={styles.mainContent}>
|
||||
@@ -63,7 +70,11 @@ export default async function IntroSection({
|
||||
<h1 className={styles.title}>{hotelName}</h1>
|
||||
</Typography>
|
||||
</div>
|
||||
<address className={styles.adressPhoneNumber}>
|
||||
<address
|
||||
className={cx(styles.addressPhoneNumber, {
|
||||
[styles.stacked]: showLocalCharges,
|
||||
})}
|
||||
>
|
||||
<span className={styles.location}>
|
||||
<span className={styles.address}>
|
||||
<MaterialIcon icon="location_on" color="CurrentColor" size={20} />
|
||||
@@ -71,16 +82,35 @@ export default async function IntroSection({
|
||||
<p>{formattedLocationText}</p>
|
||||
</Typography>
|
||||
</span>
|
||||
<Divider variant="vertical" color="Border/Divider/Default" />
|
||||
|
||||
{!showLocalCharges && (
|
||||
<Divider
|
||||
className={styles.divider}
|
||||
variant="vertical"
|
||||
color="Border/Divider/Default"
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
<Typography variant="Body/Underline/sm">
|
||||
<a href={`tel:${phoneNumber}`} className={styles.phoneNumber}>
|
||||
|
||||
<div className={styles.phoneWrapper}>
|
||||
<Link
|
||||
href={`tel:${phoneNumber}`}
|
||||
size="small"
|
||||
color="Text/Interactive/Secondary"
|
||||
textDecoration="underline"
|
||||
variant="icon"
|
||||
>
|
||||
<MaterialIcon icon="phone" color="CurrentColor" size={20} />
|
||||
{phoneNumber}
|
||||
</a>
|
||||
</Typography>
|
||||
</Link>
|
||||
<LocalCallCharges
|
||||
className={styles.localCharges}
|
||||
country={country}
|
||||
/>
|
||||
</div>
|
||||
</address>
|
||||
{tripAdvisor ? <TripAdvisorLink tripAdvisor={tripAdvisor} /> : null}
|
||||
|
||||
{tripAdvisor ? <TripAdvisorSection tripAdvisor={tripAdvisor} /> : null}
|
||||
</div>
|
||||
<div className={styles.subtitleContent}>
|
||||
<Typography variant="Body/Lead text">
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
max-width: var(--hotel-page-intro-section-width);
|
||||
}
|
||||
|
||||
.localCharges::before {
|
||||
content: "(";
|
||||
}
|
||||
|
||||
.localCharges::after {
|
||||
content: ")";
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
display: grid;
|
||||
gap: var(--Space-x15);
|
||||
@@ -31,20 +39,13 @@
|
||||
gap: var(--Space-x2);
|
||||
}
|
||||
|
||||
.adressPhoneNumber {
|
||||
.addressPhoneNumber {
|
||||
font-style: normal;
|
||||
display: grid;
|
||||
gap: var(--Space-x15);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.phoneNumber {
|
||||
color: var(--Text-Interactive-Default);
|
||||
display: flex;
|
||||
gap: var(--Space-x05);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.address {
|
||||
color: var(--Text-Secondary);
|
||||
gap: var(--Space-x05);
|
||||
@@ -58,14 +59,40 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.phoneWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Space-x15);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 767px) {
|
||||
.adressPhoneNumber {
|
||||
.addressPhoneNumber {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: var(--Space-x2);
|
||||
}
|
||||
|
||||
.addressPhoneNumber.stacked {
|
||||
display: grid;
|
||||
gap: var(--Space-x15);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.address {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.phoneWrapper {
|
||||
flex-direction: row;
|
||||
gap: var(--Space-x1);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,17 @@ import { getIntl } from "@/i18n"
|
||||
|
||||
interface LocalCallChargesProps {
|
||||
country: string
|
||||
className?: string
|
||||
}
|
||||
export default async function LocalCallCharges({
|
||||
country,
|
||||
className,
|
||||
}: LocalCallChargesProps) {
|
||||
const intl = await getIntl()
|
||||
|
||||
return country === Country.Finland ? (
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
<p className={className}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Price 0,16 €/min + local call charges",
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user