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 {
display: flex;
flex-direction: column;
gap: var(--Spacing-x-one-and-half);
gap: var(--Space-x15);
}
.information {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--Spacing-x2);
gap: var(--Space-x2);
grid-template-areas:
"address drivingDirections"
"contact socials"
@@ -33,7 +33,7 @@
.socialIcons {
display: flex;
gap: var(--Spacing-x1);
gap: var(--Space-x1);
align-items: center;
}
@@ -44,5 +44,6 @@
.ecoLabel {
grid-area: ecoLabel;
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 InstagramIcon from "@scandic-hotels/design-system/Icons/InstagramIcon"
import Subtitle from "@scandic-hotels/design-system/Subtitle"
import Title from "@scandic-hotels/design-system/Title"
import { Country } from "@scandic-hotels/trpc/types/country"
import { Typography } from "@scandic-hotels/design-system/Typography"
import Image from "@/components/Image"
import LocalCallCharges from "@/components/LocalCallCharges"
import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
@@ -29,29 +26,37 @@ export default async function ContactInformation({
return (
<div className={styles.wrapper}>
<Subtitle color="burgundy" asChild>
<Title level="h3">
<Typography variant="Title/Subtitle/lg">
<h3>
{intl.formatMessage({
defaultMessage: "Practical information",
})}
</Title>
</Subtitle>
</h3>
</Typography>
<div className={styles.information}>
<div className={styles.address}>
<Body textTransform="bold">
{intl.formatMessage({
defaultMessage: "Address",
})}
</Body>
<Body color="uiTextHighContrast">{hotelAddress.streetAddress}</Body>
<Body color="uiTextHighContrast">{hotelAddress.city}</Body>
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
defaultMessage: "Address",
})}
</p>
</Typography>
<Typography variant="Body/Paragraph/mdRegular">
<span>
<p>{hotelAddress.streetAddress}</p>
<p>{hotelAddress.city}</p>
</span>
</Typography>
</div>
<div className={styles.drivingDirections}>
<Body textTransform="bold">
{intl.formatMessage({
defaultMessage: "Driving directions",
})}
</Body>
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
defaultMessage: "Driving directions",
})}
</p>
</Typography>
<Link
href={directionsUrl}
target="_blank"
@@ -64,53 +69,53 @@ export default async function ContactInformation({
</Link>
</div>
<div className={styles.contact}>
<Body textTransform="bold">
{intl.formatMessage({
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>
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
defaultMessage: "Price 0,16 €/min + local call charges",
defaultMessage: "Contact us",
})}
</Caption>
) : null}
</p>
</Typography>
<Link
href={`tel:+${contact.phoneNumber}`}
color="Text/Interactive/Secondary"
textDecoration="underline"
>
{contact.phoneNumber}
</Link>
<LocalCallCharges country={hotelAddress.country} />
</div>
<div className={styles.socials}>
<Body textTransform="bold">
{intl.formatMessage({
defaultMessage: "Follow us",
})}
</Body>
<div className={styles.socialIcons}>
{socials.instagram && (
<Link href={socials.instagram}>
<InstagramIcon color="Icon/Interactive/Default" />
</Link>
)}
{socials.facebook && (
<Link href={socials.facebook}>
<FacebookIcon color="Icon/Interactive/Default" />
</Link>
)}
{socials.instagram || socials.facebook ? (
<div className={styles.socials}>
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
defaultMessage: "Follow us",
})}
</p>
</Typography>
<div className={styles.socialIcons}>
{socials.instagram && (
<Link href={socials.instagram}>
<InstagramIcon color="Icon/Interactive/Default" />
</Link>
)}
{socials.facebook && (
<Link href={socials.facebook}>
<FacebookIcon color="Icon/Interactive/Default" />
</Link>
)}
</div>
</div>
</div>
) : null}
<div className={styles.email}>
<Body textTransform="bold">
{intl.formatMessage({
defaultMessage: "Email",
})}
</Body>
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
defaultMessage: "Email",
})}
</p>
</Typography>
<Link
href={`mailto:${contact.email}`}
color="Text/Interactive/Secondary"
@@ -130,14 +135,16 @@ export default async function ContactInformation({
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
/>
<div>
<Caption color="uiTextPlaceholder">
{intl.formatMessage({
defaultMessage: "Nordic Swan Ecolabel",
})}
</Caption>
<Caption color="uiTextPlaceholder">
{ecoLabels.svanenEcoLabelCertificateNumber}
</Caption>
<Typography variant="Body/Supporting text (caption)/smRegular">
<span>
<p>
{intl.formatMessage({
defaultMessage: "Nordic Swan Ecolabel",
})}
</p>
<p>{ecoLabels.svanenEcoLabelCertificateNumber}</p>
</span>
</Typography>
</div>
</div>
)}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -106,6 +106,7 @@ export enum IconName {
Kettle = "Kettle",
Kids = "Kids",
KidsMocktail = "KidsMocktail",
Landscape = "Landscape",
Lamp = "Lamp",
LaptopSafe = "LaptopSafe",
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>
{parking.externalParkingUrl && showExternalParkingButton && (
<ButtonLink href={parking.externalParkingUrl} target="_blank">
<ButtonLink
typography="Body/Paragraph/mdBold"
href={parking.externalParkingUrl}
target="_blank"
>
{intl.formatMessage({ defaultMessage: "Book parking" })}
<MaterialIcon icon="open_in_new" color="CurrentColor" />
</ButtonLink>