Merged in fix/refactor-hotel-details (pull request #2513)

- Use new tokens
- Make button text bold in parking information (as in Figma)
- Make local call charges a reusable component
- Adds mountain facility icon
- Hide “Follow us” when the hotel doesn’t have any linked socials, to avoid empty heading


Approved-by: Erik Tiekstra
This commit is contained in:
Matilda Landström
2025-07-04 06:57:52 +00:00
parent 9e1cc66f95
commit 55622f582c
11 changed files with 123 additions and 126 deletions

View File

@@ -1,13 +1,13 @@
.wrapper { .wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--Spacing-x-one-and-half); gap: var(--Space-x15);
} }
.information { .information {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
gap: var(--Spacing-x2); gap: var(--Space-x2);
grid-template-areas: grid-template-areas:
"address drivingDirections" "address drivingDirections"
"contact socials" "contact socials"
@@ -33,7 +33,7 @@
.socialIcons { .socialIcons {
display: flex; display: flex;
gap: var(--Spacing-x1); gap: var(--Space-x1);
align-items: center; align-items: center;
} }
@@ -44,5 +44,6 @@
.ecoLabel { .ecoLabel {
grid-area: ecoLabel; grid-area: ecoLabel;
display: flex; display: flex;
gap: var(--Spacing-x-one-and-half); gap: var(--Space-x15);
color: var(--Text-Secondary);
} }

View File

@@ -1,12 +1,9 @@
import Body from "@scandic-hotels/design-system/Body"
import Caption from "@scandic-hotels/design-system/Caption"
import FacebookIcon from "@scandic-hotels/design-system/Icons/FacebookIcon" import FacebookIcon from "@scandic-hotels/design-system/Icons/FacebookIcon"
import InstagramIcon from "@scandic-hotels/design-system/Icons/InstagramIcon" import InstagramIcon from "@scandic-hotels/design-system/Icons/InstagramIcon"
import Subtitle from "@scandic-hotels/design-system/Subtitle" import { Typography } from "@scandic-hotels/design-system/Typography"
import Title from "@scandic-hotels/design-system/Title"
import { Country } from "@scandic-hotels/trpc/types/country"
import Image from "@/components/Image" import Image from "@/components/Image"
import LocalCallCharges from "@/components/LocalCallCharges"
import Link from "@/components/TempDesignSystem/Link" import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext" import { getLang } from "@/i18n/serverContext"
@@ -29,29 +26,37 @@ export default async function ContactInformation({
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<Subtitle color="burgundy" asChild> <Typography variant="Title/Subtitle/lg">
<Title level="h3"> <h3>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Practical information", defaultMessage: "Practical information",
})} })}
</Title> </h3>
</Subtitle> </Typography>
<div className={styles.information}> <div className={styles.information}>
<div className={styles.address}> <div className={styles.address}>
<Body textTransform="bold"> <Typography variant="Body/Paragraph/mdBold">
{intl.formatMessage({ <p>
defaultMessage: "Address", {intl.formatMessage({
})} defaultMessage: "Address",
</Body> })}
<Body color="uiTextHighContrast">{hotelAddress.streetAddress}</Body> </p>
<Body color="uiTextHighContrast">{hotelAddress.city}</Body> </Typography>
<Typography variant="Body/Paragraph/mdRegular">
<span>
<p>{hotelAddress.streetAddress}</p>
<p>{hotelAddress.city}</p>
</span>
</Typography>
</div> </div>
<div className={styles.drivingDirections}> <div className={styles.drivingDirections}>
<Body textTransform="bold"> <Typography variant="Body/Paragraph/mdBold">
{intl.formatMessage({ <p>
defaultMessage: "Driving directions", {intl.formatMessage({
})} defaultMessage: "Driving directions",
</Body> })}
</p>
</Typography>
<Link <Link
href={directionsUrl} href={directionsUrl}
target="_blank" target="_blank"
@@ -64,53 +69,53 @@ export default async function ContactInformation({
</Link> </Link>
</div> </div>
<div className={styles.contact}> <div className={styles.contact}>
<Body textTransform="bold"> <Typography variant="Body/Paragraph/mdBold">
{intl.formatMessage({ <p>
defaultMessage: "Contact us",
})}
</Body>
<Body>
<Link
href={`tel:+${contact.phoneNumber}`}
color="Text/Interactive/Secondary"
textDecoration="underline"
>
{contact.phoneNumber}
</Link>
</Body>
{hotelAddress.country === Country.Finland ? (
<Caption>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Price 0,16 €/min + local call charges", defaultMessage: "Contact us",
})} })}
</Caption> </p>
) : null} </Typography>
<Link
href={`tel:+${contact.phoneNumber}`}
color="Text/Interactive/Secondary"
textDecoration="underline"
>
{contact.phoneNumber}
</Link>
<LocalCallCharges country={hotelAddress.country} />
</div> </div>
<div className={styles.socials}> {socials.instagram || socials.facebook ? (
<Body textTransform="bold"> <div className={styles.socials}>
{intl.formatMessage({ <Typography variant="Body/Paragraph/mdBold">
defaultMessage: "Follow us", <p>
})} {intl.formatMessage({
</Body> defaultMessage: "Follow us",
<div className={styles.socialIcons}> })}
{socials.instagram && ( </p>
<Link href={socials.instagram}> </Typography>
<InstagramIcon color="Icon/Interactive/Default" /> <div className={styles.socialIcons}>
</Link> {socials.instagram && (
)} <Link href={socials.instagram}>
{socials.facebook && ( <InstagramIcon color="Icon/Interactive/Default" />
<Link href={socials.facebook}> </Link>
<FacebookIcon color="Icon/Interactive/Default" /> )}
</Link> {socials.facebook && (
)} <Link href={socials.facebook}>
<FacebookIcon color="Icon/Interactive/Default" />
</Link>
)}
</div>
</div> </div>
</div> ) : null}
<div className={styles.email}> <div className={styles.email}>
<Body textTransform="bold"> <Typography variant="Body/Paragraph/mdBold">
{intl.formatMessage({ <p>
defaultMessage: "Email", {intl.formatMessage({
})} defaultMessage: "Email",
</Body> })}
</p>
</Typography>
<Link <Link
href={`mailto:${contact.email}`} href={`mailto:${contact.email}`}
color="Text/Interactive/Secondary" color="Text/Interactive/Secondary"
@@ -130,14 +135,16 @@ export default async function ContactInformation({
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`} src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
/> />
<div> <div>
<Caption color="uiTextPlaceholder"> <Typography variant="Body/Supporting text (caption)/smRegular">
{intl.formatMessage({ <span>
defaultMessage: "Nordic Swan Ecolabel", <p>
})} {intl.formatMessage({
</Caption> defaultMessage: "Nordic Swan Ecolabel",
<Caption color="uiTextPlaceholder"> })}
{ecoLabels.svanenEcoLabelCertificateNumber} </p>
</Caption> <p>{ecoLabels.svanenEcoLabelCertificateNumber}</p>
</span>
</Typography>
</div> </div>
</div> </div>
)} )}

View File

@@ -184,7 +184,7 @@ const facilityToIconMap: Record<FacilityEnum, IconName> = {
[FacilityEnum.MeetingRooms]: IconName.Business, [FacilityEnum.MeetingRooms]: IconName.Business,
[FacilityEnum.MinibarInRoom]: IconName.Minibar, [FacilityEnum.MinibarInRoom]: IconName.Minibar,
[FacilityEnum.MobileLift]: IconName.StarFilled, [FacilityEnum.MobileLift]: IconName.StarFilled,
[FacilityEnum.Mountains0To1Km]: IconName.StarFilled, [FacilityEnum.Mountains0To1Km]: IconName.Landscape,
[FacilityEnum.MovieChannelsInRoomAllScandic]: IconName.TVRemote, [FacilityEnum.MovieChannelsInRoomAllScandic]: IconName.TVRemote,
[FacilityEnum.MultipleExitsOnEachFloor]: IconName.StarFilled, [FacilityEnum.MultipleExitsOnEachFloor]: IconName.StarFilled,
[FacilityEnum.NonSmokingRoomsAllScandic]: IconName.NonSmoking, [FacilityEnum.NonSmokingRoomsAllScandic]: IconName.NonSmoking,

View File

@@ -1,6 +1,6 @@
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import { Country } from "@scandic-hotels/trpc/types/country"
import LocalCallCharges from "@/components/LocalCallCharges"
import Link from "@/components/TempDesignSystem/Link" import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
@@ -31,18 +31,7 @@ export default async function MeetingsSidebar({
</Typography> </Typography>
<div className={styles.contactDetails}> <div className={styles.contactDetails}>
<Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link> <Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link>
{country === Country.Finland ? ( <LocalCallCharges country={country} />
<Typography
variant="Body/Paragraph/mdRegular"
className={styles.text}
>
<p>
{intl.formatMessage({
defaultMessage: "Price 0,16 €/min + local call charges",
})}
</p>
</Typography>
) : null}
{email && ( {email && (
<Link textDecoration="underline" href={`mailto:${email}`}> <Link textDecoration="underline" href={`mailto:${email}`}>
{email} {email}

View File

@@ -1,6 +1,6 @@
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import { Country } from "@scandic-hotels/trpc/types/country"
import LocalCallCharges from "@/components/LocalCallCharges"
import Link from "@/components/TempDesignSystem/Link" import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
@@ -53,18 +53,7 @@ export default async function ParkingSidebar({
<Link href={`tel:${contactInformation.phoneNumber}`}> <Link href={`tel:${contactInformation.phoneNumber}`}>
{contactInformation.phoneNumber} {contactInformation.phoneNumber}
</Link> </Link>
{address.country === Country.Finland ? ( <LocalCallCharges country={address.country} />
<Typography
variant="Body/Paragraph/mdRegular"
className={styles.text}
>
<p>
{intl.formatMessage({
defaultMessage: "Price 0,16 €/min + local call charges",
})}
</p>
</Typography>
) : null}
<Link <Link
textDecoration="underline" textDecoration="underline"
href={`mailto:${contactInformation.email}`} href={`mailto:${contactInformation.email}`}

View File

@@ -1,7 +1,7 @@
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import { Country } from "@scandic-hotels/trpc/types/country"
import LocalCallCharges from "@/components/LocalCallCharges"
import OpeningHours from "@/components/OpeningHours" import OpeningHours from "@/components/OpeningHours"
import Button from "@/components/TempDesignSystem/Button" import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link" import Link from "@/components/TempDesignSystem/Link"
@@ -115,15 +115,7 @@ export default async function RestaurantSidebar({
{phoneNumber && ( {phoneNumber && (
<> <>
<Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link> <Link href={`tel:${phoneNumber}`}>{phoneNumber}</Link>
{hotelAddress.country === Country.Finland ? ( <LocalCallCharges country={hotelAddress.country} />
<Typography variant="Body/Paragraph/mdRegular">
<p>
{intl.formatMessage({
defaultMessage: "Price 0,16 €/min + local call charges",
})}
</p>
</Typography>
) : null}
</> </>
)} )}
{email && ( {email && (

View File

@@ -1,6 +1,6 @@
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import { Country } from "@scandic-hotels/trpc/types/country"
import LocalCallCharges from "@/components/LocalCallCharges"
import Link from "@/components/TempDesignSystem/Link" import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
@@ -80,18 +80,7 @@ export default async function WellnessSidebar({
<Link href={`tel:${contactInformation.phoneNumber}`}> <Link href={`tel:${contactInformation.phoneNumber}`}>
{contactInformation.phoneNumber} {contactInformation.phoneNumber}
</Link> </Link>
{address.country === Country.Finland ? ( <LocalCallCharges country={address.country} />
<Typography
variant="Body/Paragraph/mdRegular"
className={styles.text}
>
<p>
{intl.formatMessage({
defaultMessage: "Price 0,16 €/min + local call charges",
})}
</p>
</Typography>
) : null}
</div> </div>
</div> </div>
</> </>

View File

@@ -260,6 +260,8 @@ export function IconByIconName({
return <MaterialIcon icon="kayaking" {...props} /> return <MaterialIcon icon="kayaking" {...props} />
case IconName.Kettle: case IconName.Kettle:
return <MaterialIcon icon="kettle" {...props} /> return <MaterialIcon icon="kettle" {...props} />
case IconName.Landscape:
return <MaterialIcon icon="landscape" {...props} />
case IconName.Lamp: case IconName.Lamp:
return <MaterialIcon icon="floor_lamp" {...props} /> return <MaterialIcon icon="floor_lamp" {...props} />
case IconName.LaundryMachine: case IconName.LaundryMachine:

View File

@@ -106,6 +106,7 @@ export enum IconName {
Kettle = "Kettle", Kettle = "Kettle",
Kids = "Kids", Kids = "Kids",
KidsMocktail = "KidsMocktail", KidsMocktail = "KidsMocktail",
Landscape = "Landscape",
Lamp = "Lamp", Lamp = "Lamp",
LaptopSafe = "LaptopSafe", LaptopSafe = "LaptopSafe",
LaundryMachine = "LaundryMachine", LaundryMachine = "LaundryMachine",

View File

@@ -0,0 +1,23 @@
import { Typography } from "@scandic-hotels/design-system/Typography"
import { Country } from "@scandic-hotels/trpc/types/country"
import { getIntl } from "@/i18n"
interface LocalCallChargesProps {
country: string
}
export default async function LocalCallCharges({
country,
}: LocalCallChargesProps) {
const intl = await getIntl()
return country === Country.Finland ? (
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
defaultMessage: "Price 0,16 €/min + local call charges",
})}
</p>
</Typography>
) : null
}

View File

@@ -79,7 +79,11 @@ export default function ParkingInformation({
</div> </div>
</div> </div>
{parking.externalParkingUrl && showExternalParkingButton && ( {parking.externalParkingUrl && showExternalParkingButton && (
<ButtonLink href={parking.externalParkingUrl} target="_blank"> <ButtonLink
typography="Body/Paragraph/mdBold"
href={parking.externalParkingUrl}
target="_blank"
>
{intl.formatMessage({ defaultMessage: "Book parking" })} {intl.formatMessage({ defaultMessage: "Book parking" })}
<MaterialIcon icon="open_in_new" color="CurrentColor" /> <MaterialIcon icon="open_in_new" color="CurrentColor" />
</ButtonLink> </ButtonLink>