Merged in feat/SW-1504-UI-update-breakfast-component (pull request #1284)

feat(SW-1504): Used AncillaryCard and added to breakfast choice

* feat(SW-1504): Craeted AncillaryCard and added to breakfast choice

* feat(SW-1504): Using of AncillaryCard

* feat(SW-1504) Removed unused imports

* feat(SW-1504): Added price text

* feat(SW-1504): added /night per adult

* feat(SW-1504) Removed type prop


Approved-by: Arvid Norlin
This commit is contained in:
Pontus Dreij
2025-02-14 15:43:14 +00:00
parent 21d06e2d84
commit ed9dbded5d
12 changed files with 93 additions and 48 deletions

View File

@@ -0,0 +1,3 @@
.ancillaryChoiceCard:hover {
cursor: pointer;
}

View File

@@ -0,0 +1,39 @@
import { useFormContext } from "react-hook-form"
import { AncillaryCard } from "@/components/TempDesignSystem/AncillaryCard"
import styles from "./ancillaryChoiceCard.module.css"
import type { BreakfastChoiceCardProps } from "@/types/components/ancillaryCard"
export default function BreakfastChoiceCard({
name,
id,
value,
ancillary,
}: BreakfastChoiceCardProps) {
const { register, setValue } = useFormContext()
function onLabelClick(event: React.MouseEvent) {
// Preventing click event on label elements firing twice: https://github.com/facebook/react/issues/14295
event.preventDefault()
setValue(name, value)
}
return (
<label
onClick={onLabelClick}
tabIndex={0}
className={styles.ancillaryChoiceCard}
>
<AncillaryCard ancillary={ancillary} />
<input
{...register(name)}
aria-hidden
id={id || name}
hidden
type="radio"
value={value}
/>
</label>
)
}

View File

@@ -8,10 +8,8 @@ import { useIntl } from "react-intl"
import { useEnterDetailsStore } from "@/stores/enter-details"
import { selectRoom } from "@/stores/enter-details/helpers"
import { Highlight } from "@/components/TempDesignSystem/Form/ChoiceCard/_Card"
import RadioCard from "@/components/TempDesignSystem/Form/ChoiceCard/Radio"
import BreakfastChoiceCard from "@/components/HotelReservation/EnterDetails/Breakfast/BreakfastChoiceCard"
import Body from "@/components/TempDesignSystem/Text/Body"
import { formatPrice } from "@/utils/numberFormatting"
import { breakfastFormSchema } from "./schema"
@@ -93,52 +91,41 @@ export default function Breakfast({
) : null}
<form className={styles.form} onSubmit={methods.handleSubmit(onSubmit)}>
{packages.map((pkg) => (
<RadioCard
<BreakfastChoiceCard
key={pkg.code}
id={pkg.code}
name="breakfast"
subtitle={
pkg.code === BreakfastPackageEnum.FREE_MEMBER_BREAKFAST
? intl.formatMessage<React.ReactNode>(
{
id: "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult",
},
{
amount: formatPrice(
intl,
parseInt(pkg.localPrice.price),
pkg.localPrice.currency
),
currency: pkg.localPrice.currency,
free: (str) => <Highlight>{str}</Highlight>,
strikethrough: (str) => <s>{str}</s>,
}
)
: intl.formatMessage(
{ id: "{amount}/night per adult" },
{
amount: formatPrice(
intl,
parseInt(pkg.localPrice.price),
pkg.localPrice.currency
),
}
)
}
text={intl.formatMessage({
id: "All our breakfast buffets offer gluten free, vegan, and allergy-friendly options.",
})}
title={intl.formatMessage({ id: "Breakfast buffet" })}
ancillary={{
title: intl.formatMessage({ id: "Breakfast buffet" }),
price: {
total: parseInt(pkg.localPrice.price),
currency: pkg.localPrice.currency,
included:
pkg.code === BreakfastPackageEnum.FREE_MEMBER_BREAKFAST,
text: intl.formatMessage({ id: "/night per adult" }),
},
description: intl.formatMessage({
id: "All our breakfast buffets offer gluten free, vegan, and allergy-friendly options.",
}),
imageUrl: "/_static/img/enter-details/breakfast.png", // TODO: Add dynamic image
}}
value={pkg.code}
id={pkg.code}
/>
))}
<RadioCard
<BreakfastChoiceCard
name="breakfast"
subtitle={formatPrice(intl, 0, packages[0].localPrice.currency)}
text={intl.formatMessage({
id: "You can always change your mind later and add breakfast at the hotel.",
})}
title={intl.formatMessage({ id: "No breakfast" })}
ancillary={{
title: intl.formatMessage({ id: "No breakfast" }),
price: {
total: 0,
currency: packages[0].localPrice.currency,
},
description: intl.formatMessage({
id: "You can always change your mind later and add breakfast at the hotel.",
}),
imageUrl: "/_static/img/enter-details/breakfast.png", // TODO: Add dynamic image
imageOpacity: 0.1,
}}
value="false"
/>
</form>

View File

@@ -32,11 +32,13 @@ export function AncillaryCard({ ancillary }: AncillaryCardProps) {
<div className={styles.price}>
<Body color="uiTextHighContrast">
{formatPrice(
intl,
ancillary.price.total,
ancillary.price.currency
)}
{ancillary.price.included
? intl.formatMessage({ id: "Included" })
: `${formatPrice(
intl,
ancillary.price.total,
ancillary.price.currency
)} ${ancillary.price.text}`}
</Body>
{ancillary.points && (

View File

@@ -1,4 +1,5 @@
{
"/night per adult": "/nat per voksen",
"<b>Included</b> (based on availability)": "<b>Inkluderet</b> (baseret på tilgængelighed)",
"<b>Total price</b> (incl VAT)": "<b>Samlet pris</b> (inkl. moms)",
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/nat per voksen",

View File

@@ -1,4 +1,5 @@
{
"/night per adult": "/Nacht pro Erwachsenem",
"<b>Included</b> (based on availability)": "<b>Inbegriffen</b> (je nach Verfügbarkeit)",
"<b>Total price</b> (incl VAT)": "<b>Gesamtpreis</b> (inkl. MwSt.)",
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/Nacht pro Erwachsenem",

View File

@@ -1,5 +1,6 @@
{
"+46 8 517 517 00": "+46 8 517 517 00",
"/night per adult": "/night per adult",
"<b>Included</b> (based on availability)": "<b>Included</b> (based on availability)",
"<b>Total price</b> (incl VAT)": "<b>Total price</b> (incl VAT)",
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult",

View File

@@ -1,4 +1,5 @@
{
"/night per adult": "/yötä aikuista kohti",
"<b>Included</b> (based on availability)": "<b>Sisältyy</b> (saatavuuden mukaan)",
"<b>Total price</b> (incl VAT)": "<b>Kokonaishinta</b> (sis. ALV)",
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/yötä aikuista kohti",

View File

@@ -1,4 +1,5 @@
{
"/night per adult": "/natt per voksen",
"<b>Included</b> (based on availability)": "<b>Inkludert</b> (basert på tilgjengelighet)",
"<b>Total price</b> (incl VAT)": "<b>Totalpris</b> (inkl. mva)",
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/natt per voksen",

View File

@@ -1,4 +1,5 @@
{
"/night per adult": "/natt per vuxen",
"<b>Included</b> (based on availability)": "<b>Ingår</b> (baserat på tillgänglighet)",
"<b>Total price</b> (incl VAT)": "<b>Totalpris</b> (inkl moms)",
"<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/night per adult": "<strikethrough>{amount}</strikethrough> <free>0 {currency}</free>/natt per vuxen",

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 MiB

View File

@@ -6,8 +6,16 @@ export interface AncillaryCardProps {
price: {
total: number
currency: string
text?: string
included?: boolean
}
points?: number
description?: string
}
}
export interface BreakfastChoiceCardProps extends AncillaryCardProps {
name: string
id?: string
value: string
}