Merged in fix/SW-2290-ui-for-signup (pull request #2224)

Fix/SW-2290 new ui for signup on enter details page

* fix(SW-2290): New UI for join card


Approved-by: Michael Zetterberg
Approved-by: Tobias Johansson
Approved-by: Bianca Widstam
This commit is contained in:
Niclas Edenvin
2025-06-05 07:41:46 +00:00
committed by Linus Flood
parent 0383a332ad
commit d3ba9d4a99
9 changed files with 150 additions and 188 deletions

View File

@@ -8,7 +8,7 @@
display: grid;
gap: var(--Spacing-x2);
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
width: min(700px, 100%);
width: min(696px, 100%);
}
.iconContainer {

View File

@@ -8,5 +8,5 @@
display: grid;
gap: var(--Spacing-x2);
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
width: min(700px, 100%);
width: min(696px, 100%);
}

View File

@@ -2,11 +2,15 @@
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { membershipTermsAndConditions } from "@/constants/webHrefs"
import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Link from "@/components/TempDesignSystem/Link"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import { useRoomContext } from "@/contexts/Details/Room"
import useLang from "@/hooks/useLang"
import { formatPrice } from "@/utils/numberFormatting"
import styles from "./joinScandicFriendsCard.module.css"
@@ -17,6 +21,7 @@ import { CurrencyEnum } from "@/types/enums/currency"
export default function JoinScandicFriendsCard({
name = "join",
}: JoinScandicFriendsCardProps) {
const lang = useLang()
const intl = useIntl()
const {
room,
@@ -32,72 +37,69 @@ export default function JoinScandicFriendsCard({
return null
}
const list = [
{
title: intl.formatMessage({
defaultMessage: "Earn bonus nights & points",
}),
},
{
title: intl.formatMessage({
defaultMessage: "Get member benefits & offers",
}),
},
{
title: intl.formatMessage({
defaultMessage: "Join at no cost",
}),
},
]
const saveOnJoiningLabel = intl.formatMessage(
{
defaultMessage: "Pay the member price of {amount} for Room {roomNr}",
},
{
amount: formatPrice(
intl,
room.roomRate.member.localPrice.pricePerStay ?? 0,
room.roomRate.member.localPrice.currency ?? CurrencyEnum.Unknown
),
roomNr,
}
)
return (
<div className={styles.cardContainer}>
<Typography variant="Title/Subtitle/md">
<h2 className={styles.priceContainer}>
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${intl.formatMessage({
defaultMessage: "Get the member room price",
})}: `}
</span>
<span className={styles.price}>
{intl.formatMessage(
{
defaultMessage: "{amount} for room {roomNr}",
},
{
amount: formatPrice(
intl,
room.roomRate.member.localPrice.pricePerStay ?? 0,
room.roomRate.member.localPrice.currency ??
CurrencyEnum.Unknown
),
roomNr,
}
)}
</span>
</h2>
</Typography>
<Checkbox
name={name}
className={styles.checkBox}
registerOptions={{ onChange, value: room.guest.join }}
>
<div>
<Caption type="label" textTransform="uppercase" color="red">
{saveOnJoiningLabel}
</Caption>
<Caption color="uiTextHighContrast">
<Typography variant="Body/Paragraph/mdRegular">
<div>
{intl.formatMessage({
defaultMessage: "Join Scandic Friends",
defaultMessage: "Join Scandic Friends before check-in",
})}
</Caption>
</div>
</div>
</Typography>
</Checkbox>
<div className={styles.list}>
{list.map((item) => (
<Caption
key={item.title}
className={styles.listItem}
color="uiTextPlaceholder"
>
<MaterialIcon
icon="check"
size={20}
color="Icon/Interactive/Placeholder"
/>
{item.title}
</Caption>
))}
<div className={styles.terms}>
<Footnote color="uiTextPlaceholder">
{intl.formatMessage(
{
defaultMessage:
"By joining you accept the <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. The Scandic Friends Membership is valid until further notice, but can at any time be terminated by contacting Scandic Customer Service.",
},
{
termsAndConditionsLink: (str) => (
<Link
textDecoration="underline"
size="tiny"
target="_blank"
href={membershipTermsAndConditions[lang]}
>
{str}
</Link>
),
}
)}
</Footnote>
</div>
</div>
)

View File

@@ -1,35 +1,48 @@
.cardContainer {
align-self: flex-start;
background-color: var(--Base-Surface-Primary-light-Normal);
border: 1px solid var(--Base-Border-Subtle);
background-color: var(--Surface-Primary-Hover-Accent);
border-radius: var(--Corner-radius-lg);
display: grid;
gap: var(--Spacing-x-one-and-half);
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
width: min(100%, 600px);
gap: var(--Space-x2);
padding: var(--Space-x2);
grid-template-areas:
"price"
"checkbox"
"terms";
width: min(100%, 696px);
}
.priceContainer {
grid-area: price;
margin-bottom: var(--Space-x1);
}
.price {
color: var(--Text-Accent-Primary);
}
.checkBox {
align-self: center;
grid-area: checkbox;
}
.list {
display: flex;
gap: var(--Spacing-x1);
flex-direction: column;
}
.listItem {
display: flex;
.terms {
grid-area: terms;
}
@media screen and (min-width: 768px) {
.cardContainer {
gap: var(--Spacing-x1);
grid-template-columns: 1fr auto;
grid-template-rows: auto auto;
gap: var(--Space-x3);
grid-template-areas:
"price checkbox"
"terms terms";
}
.list {
flex-direction: row;
flex-wrap: wrap;
.priceContainer {
margin-bottom: 0;
display: flex;
flex-direction: column;
}
}

View File

@@ -6,7 +6,7 @@
.container {
display: grid;
gap: var(--Spacing-x2);
width: min(100%, 600px);
width: min(100%, 696px);
}
.fullWidth {
@@ -18,13 +18,7 @@
}
@media screen and (min-width: 768px) {
.form {
gap: var(--Spacing-x3);
}
.container {
gap: var(--Spacing-x2);
grid-template-columns: 1fr 1fr;
width: min(100%, 600px);
}
}

View File

@@ -1,14 +1,14 @@
"use client"
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { membershipTermsAndConditions } from "@/constants/webHrefs"
import LoginButton from "@/components/LoginButton"
import Button from "@/components/TempDesignSystem/Button"
import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
import Link from "@/components/TempDesignSystem/Link"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import { useRoomContext } from "@/contexts/Details/Room"
import useLang from "@/hooks/useLang"
@@ -37,98 +37,58 @@ export default function JoinScandicFriendsCard({
return null
}
const list = [
{
title: intl.formatMessage({
defaultMessage: "Friendly room rates",
}),
},
{
title: intl.formatMessage({
defaultMessage: "Earn & spend points",
}),
},
{
title: intl.formatMessage({
defaultMessage: "Join for free",
}),
},
]
const saveOnJoiningLabel = intl.formatMessage(
{
defaultMessage: "Get the member room price: {amount}",
},
{
amount: formatPrice(
intl,
room.roomRate.member.localPrice.pricePerStay ?? 0,
room.roomRate.member.localPrice.currency ?? CurrencyEnum.Unknown
),
}
)
return (
<div className={styles.cardContainer}>
<Typography variant="Title/Subtitle/md">
<h2 className={styles.priceContainer}>
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${intl.formatMessage({
defaultMessage: "Get the member room price",
})}: `}
</span>
<span className={styles.price}>
{formatPrice(
intl,
room.roomRate.member.localPrice.pricePerStay ?? 0,
room.roomRate.member.localPrice.currency ?? CurrencyEnum.Unknown
)}
</span>
</h2>
</Typography>
<Checkbox
name={name}
className={styles.checkBox}
registerOptions={{ onChange }}
>
<div>
<Caption type="label" textTransform="uppercase" color="red">
{saveOnJoiningLabel}
</Caption>
<Caption
type="label"
textTransform="uppercase"
color="uiTextHighContrast"
>
<Typography variant="Body/Paragraph/mdRegular">
<div>
{intl.formatMessage({
defaultMessage: "Join Scandic Friends",
defaultMessage: "Join Scandic Friends now",
})}
</Caption>
</div>
</div>
</Typography>
</Checkbox>
<Footnote color="uiTextHighContrast" className={styles.login}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${intl.formatMessage({
defaultMessage: "Already a friend?",
})} `}
<Button size="small" color="Primary" asChild>
<LoginButton
className={styles.login}
color="white"
position="enter details"
trackingId="join-scandic-friends-enter-details"
variant="breadcrumb"
>
{intl.formatMessage({
defaultMessage: "Log in",
})}
</LoginButton>
</Footnote>
</Button>
<div className={styles.list}>
{list.map((item) => (
<Caption
key={item.title}
color="uiTextPlaceholder"
className={styles.listItem}
>
<MaterialIcon
icon="check"
color="Icon/Interactive/Placeholder"
size={20}
/>
{item.title}
</Caption>
))}
</div>
<div className={styles.terms}>
<Footnote color="uiTextPlaceholder">
{intl.formatMessage(
{
defaultMessage:
"By signing up you accept the Scandic Friends <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. Your membership is valid until further notice, and you can terminate your membership at any time by sending an email to Scandic's customer service",
"By joining you accept the <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. The Scandic Friends Membership is valid until further notice, but can at any time be terminated by contacting Scandic Customer Service.",
},
{
termsAndConditionsLink: (str) => (

View File

@@ -1,21 +1,30 @@
.cardContainer {
align-self: flex-start;
background-color: var(--Base-Surface-Primary-light-Normal);
border: 1px solid var(--Base-Border-Subtle);
background-color: var(--Surface-Primary-Hover-Accent);
border-radius: var(--Corner-radius-lg);
display: grid;
gap: var(--Spacing-x-one-and-half);
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
gap: var(--Space-x2);
padding: var(--Space-x2);
grid-template-areas:
"checkbox"
"list"
"login"
"terms";
width: min(100%, 600px);
"price login"
"checkbox checkbox"
"terms terms";
width: min(100%, 696px);
}
.priceContainer {
grid-area: price;
margin-bottom: var(--Space-x1);
}
.price {
color: var(--Text-Accent-Primary);
}
.login {
grid-area: login;
align-self: center;
justify-self: end;
}
.checkBox {
@@ -23,33 +32,23 @@
grid-area: checkbox;
}
.list {
display: grid;
grid-area: list;
gap: var(--Spacing-x1);
}
.listItem {
display: flex;
}
.terms {
border-top: 1px solid var(--Base-Border-Normal);
grid-area: terms;
padding-top: var(--Spacing-x1);
}
@media screen and (min-width: 768px) {
.cardContainer {
grid-template-columns: 1fr auto;
gap: var(--Spacing-x2);
grid-template-columns: 1fr auto auto;
grid-template-rows: auto auto;
gap: var(--Space-x3);
grid-template-areas:
"checkbox login"
"list list"
"terms terms";
"price checkbox login"
"terms terms terms";
}
.list {
.priceContainer {
margin-bottom: 0;
display: flex;
gap: var(--Spacing-x1);
flex-direction: column;
}
}

View File

@@ -6,7 +6,7 @@
.container {
display: grid;
gap: var(--Spacing-x2);
width: min(100%, 600px);
width: min(100%, 696px);
}
.fullWidth {
@@ -18,13 +18,7 @@
}
@media screen and (min-width: 768px) {
.form {
gap: var(--Spacing-x3);
}
.container {
gap: var(--Spacing-x2);
grid-template-columns: 1fr 1fr;
width: min(100%, 600px);
}
}

View File

@@ -13,7 +13,7 @@
display: flex;
flex-direction: column;
gap: var(--Spacing-x4);
max-width: 480px;
max-width: 696px;
}
.section {