feat: refactor NewDates, clean up legacy code

This reverts commit 0c7836fa59.
This commit is contained in:
Simon Emanuelsson
2025-05-03 19:33:04 +02:00
parent c6a0b4ee30
commit db289b80b1
96 changed files with 1603 additions and 1500 deletions

View File

@@ -0,0 +1,49 @@
import { useIntl } from "react-intl"
import { useMyStayStore } from "@/stores/my-stay"
import Row from "./Row"
export default function BedPreference() {
const intl = useIntl()
const bedType = useMyStayStore((state) => state.bookedRoom.room?.bedType)
if (!bedType) {
return null
}
const mainBedWidthValueMsg = intl.formatMessage(
{
defaultMessage: "{value} cm",
},
{
value: bedType.mainBed.widthRange.min,
}
)
const mainBedWidthRangeMsg = intl.formatMessage(
{
defaultMessage: "{min}{max} cm",
},
{
min: bedType.mainBed.widthRange.min,
max: bedType.mainBed.widthRange.max,
}
)
const sameWidth =
bedType.mainBed.widthRange.min === bedType.mainBed.widthRange.max
const widthMsg = sameWidth ? mainBedWidthValueMsg : mainBedWidthRangeMsg
const text = `${bedType.mainBed.description} (${widthMsg})`
return (
<Row
icon="bed"
text={text}
title={intl.formatMessage({
defaultMessage: "Bed preference",
})}
/>
)
}

View File

@@ -0,0 +1,35 @@
"use client"
import { useIntl } from "react-intl"
import { useMyStayStore } from "@/stores/my-stay"
import { formatPrice } from "@/utils/numberFormatting"
import Row from "./Row"
export default function Breakfast() {
const intl = useIntl()
const { breakfast, rateDefinition } = useMyStayStore((state) => ({
breakfast: state.bookedRoom.breakfast,
rateDefinition: state.bookedRoom.rateDefinition,
}))
let breakfastPrice = intl.formatMessage({
defaultMessage: "No breakfast",
})
if (rateDefinition.breakfastIncluded) {
breakfastPrice = intl.formatMessage({
defaultMessage: "Included",
})
} else if (breakfast) {
breakfastPrice = formatPrice(
intl,
breakfast.localPrice.totalPrice,
breakfast.localPrice.currency
)
}
const title = intl.formatMessage({ defaultMessage: "Breakfast" })
return <Row icon="coffee" text={breakfastPrice} title={title} />
}

View File

@@ -0,0 +1,45 @@
import { useIntl } from "react-intl"
import { useMyStayStore } from "@/stores/my-stay"
import Row from "./Row"
export default function Guests() {
const intl = useIntl()
const { adults, childrenAges } = useMyStayStore((state) => ({
adults: state.bookedRoom.adults,
childrenAges: state.bookedRoom.childrenAges,
}))
const adultsMsg = intl.formatMessage(
{
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
},
{
adults,
}
)
const childrenMsg = intl.formatMessage(
{
defaultMessage: "{children, plural, one {# child} other {# children}}",
},
{
children: childrenAges.length,
}
)
const adultsOnlyMsg = adultsMsg
const adultsAndChildrenMsg = [adultsMsg, childrenMsg].join(", ")
return (
<Row
icon="person"
text={childrenAges.length > 0 ? adultsAndChildrenMsg : adultsOnlyMsg}
title={intl.formatMessage({
defaultMessage: "Guests",
})}
/>
)
}

View File

@@ -0,0 +1,47 @@
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
import { useMyStayStore } from "@/stores/my-stay"
import { hasModifiableRate } from "@/components/HotelReservation/MyStay/utils"
import useLang from "@/hooks/useLang"
import Row from "./Row"
export default function ModifyBy() {
const intl = useIntl()
const lang = useLang()
const { checkInDate, isModifyable } = useMyStayStore((state) => ({
checkInDate: state.bookedRoom.checkInDate,
isModifyable: hasModifiableRate(
state.bookedRoom.rateDefinition.cancellationRule
),
}))
if (!isModifyable) {
return null
}
const fromDate = dt(checkInDate).locale(lang)
const text = intl.formatMessage(
{
defaultMessage: "Until {time}, {date}",
},
{
time: "18:00",
date: fromDate.format("dddd D MMM"),
}
)
return (
<Row
icon="refresh"
text={text}
title={intl.formatMessage({
defaultMessage: "Modify By",
})}
/>
)
}

View File

@@ -0,0 +1,36 @@
import { useIntl } from "react-intl"
import { useMyStayStore } from "@/stores/my-stay"
import Row from "./Row"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
export default function Packages() {
const intl = useIntl()
const packages = useMyStayStore(
(state) =>
state.bookedRoom.packages
?.filter((item) =>
Object.values(RoomPackageCodeEnum).includes(
item.code as RoomPackageCodeEnum
)
)
.map((item) => item.description) || []
)
if (!packages.length) {
return null
}
return (
<Row
icon="meeting_room"
text={packages.join(", ")}
title={intl.formatMessage({
defaultMessage: "Room classification",
})}
/>
)
}

View File

@@ -0,0 +1,32 @@
"use client"
import {
MaterialIcon,
type MaterialIconProps,
} from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import styles from "./row.module.css"
interface RowProps {
icon: MaterialIconProps["icon"]
text: string
title: string
}
export default function Row({ icon, text, title }: RowProps) {
return (
<div className={styles.row}>
<span className={styles.title}>
<MaterialIcon icon={icon} color="Icon/Default" size={20} />
<Typography variant="Body/Paragraph/mdBold">
<p>{title}</p>
</Typography>
</span>
<div className={styles.content}>
<Typography variant="Body/Paragraph/mdRegular">
<p color="uiTextHighContrast">{text}</p>
</Typography>
</div>
</div>
)
}

View File

@@ -0,0 +1,38 @@
.row {
display: flex;
flex-direction: column;
padding: var(--Spacing-x-one-and-half) 0;
}
.row:last-child {
border-bottom: none;
}
.title {
display: flex;
flex-direction: row;
gap: var(--Spacing-x1);
}
.title svg {
height: 24px;
width: 24px;
}
.content {
padding-left: var(--Spacing-x4);
}
@media (min-width: 768px) {
.row {
align-items: center;
border-bottom: 1px solid var(--Base-Border-Subtle);
flex-direction: row;
justify-content: space-between;
}
.title svg {
height: 20px;
width: 20px;
}
}

View File

@@ -0,0 +1,27 @@
import { useIntl } from "react-intl"
import { useMyStayStore } from "@/stores/my-stay"
import Row from "./Row"
export default function Terms() {
const intl = useIntl()
const cancellationText = useMyStayStore(
(state) => state.bookedRoom.rateDefinition.cancellationText
)
if (!cancellationText) {
return null
}
return (
<Row
icon="contract"
text={cancellationText}
title={intl.formatMessage({
defaultMessage: "Terms",
})}
/>
)
}

View File

@@ -0,0 +1,10 @@
.details {
max-width: 100%;
padding: 0 var(--Spacing-x2);
}
@media (min-width: 768px) {
.details {
padding: 0;
}
}

View File

@@ -0,0 +1,21 @@
import BedPreference from "./BedPreference"
import Breakfast from "./Breakfast"
import Guests from "./Guests"
import ModifyBy from "./ModifyBy"
import Packages from "./Packages"
import Terms from "./Terms"
import styles from "./details.module.css"
export default function Details() {
return (
<div className={styles.details}>
<Guests />
<Terms />
<ModifyBy />
<Breakfast />
<Packages />
<BedPreference />
</div>
)
}