fix(SW-1042)(SW-1114)(SW-1123): fix select room bugs
This commit is contained in:
@@ -18,9 +18,7 @@ export default function FlexibilityOption({
|
||||
name,
|
||||
paymentTerm,
|
||||
priceInformation,
|
||||
roomType,
|
||||
roomTypeCode,
|
||||
features,
|
||||
petRoomPackage,
|
||||
handleSelectRate,
|
||||
}: FlexibilityOptionProps) {
|
||||
@@ -45,10 +43,22 @@ export default function FlexibilityOption({
|
||||
|
||||
const { public: publicPrice, member: memberPrice } = product.productType
|
||||
|
||||
function onChange() {
|
||||
handleSelectRate({
|
||||
publicRateCode: publicPrice.rateCode,
|
||||
roomTypeCode: roomTypeCode,
|
||||
const onClick: React.MouseEventHandler<HTMLInputElement> = (e) => {
|
||||
handleSelectRate((prev) => {
|
||||
if (
|
||||
prev &&
|
||||
prev.publicRateCode === publicPrice.rateCode &&
|
||||
prev.roomTypeCode === roomTypeCode
|
||||
) {
|
||||
if (e.currentTarget?.checked) e.currentTarget.checked = false
|
||||
return undefined
|
||||
} else
|
||||
return {
|
||||
publicRateCode: publicPrice.rateCode,
|
||||
roomTypeCode: roomTypeCode,
|
||||
name: name,
|
||||
paymentTerm: paymentTerm,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -58,7 +68,7 @@ export default function FlexibilityOption({
|
||||
type="radio"
|
||||
name="rateCode"
|
||||
value={publicPrice?.rateCode}
|
||||
onChange={onChange}
|
||||
onClick={onClick}
|
||||
/>
|
||||
<div className={styles.card}>
|
||||
<div className={styles.header}>
|
||||
|
||||
@@ -34,6 +34,7 @@ export default function RateSummary({
|
||||
features,
|
||||
roomType,
|
||||
priceName,
|
||||
priceTerm,
|
||||
} = rateSummary
|
||||
const priceToShow = isUserLoggedIn && member ? member : publicRate
|
||||
|
||||
@@ -80,87 +81,93 @@ export default function RateSummary({
|
||||
</Footnote>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.summaryText}>
|
||||
<Subtitle color="uiTextHighContrast">{roomType}</Subtitle>
|
||||
<Body color="uiTextMediumContrast">{priceName}</Body>
|
||||
</div>
|
||||
<div className={styles.summaryPriceContainer}>
|
||||
{showMemberDiscountBanner && (
|
||||
<div className={styles.memberDiscountBannerDesktop}>
|
||||
<Footnote color="burgundy">
|
||||
{intl.formatMessage<React.ReactNode>(
|
||||
{
|
||||
id: "To get the member price <span>{amount} {currency}</span>, log in or join when completing the booking.",
|
||||
},
|
||||
{
|
||||
span: (str) => (
|
||||
<Caption color="red" type="bold" asChild>
|
||||
<span>{str}</span>
|
||||
</Caption>
|
||||
),
|
||||
amount: member.localPrice.pricePerStay,
|
||||
currency: member.localPrice.currency,
|
||||
}
|
||||
)}
|
||||
</Footnote>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.summaryPriceTextDesktop}>
|
||||
<Body>
|
||||
{intl.formatMessage<React.ReactNode>(
|
||||
{ id: "<b>Total price</b> (incl VAT)" },
|
||||
{ b: (str) => <b>{str}</b> }
|
||||
)}
|
||||
</Body>
|
||||
<Caption color="uiTextMediumContrast">{summaryPriceTex}</Caption>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.summaryText}>
|
||||
<Subtitle color="uiTextHighContrast">{roomType}</Subtitle>
|
||||
<Body color="uiTextMediumContrast">{`${priceName}, ${priceTerm}`}</Body>
|
||||
</div>
|
||||
<div className={styles.summaryPrice}>
|
||||
<div className={styles.summaryPriceTextDesktop}>
|
||||
<Subtitle
|
||||
color={isUserLoggedIn ? "red" : "uiTextHighContrast"}
|
||||
textAlign="right"
|
||||
>
|
||||
{priceToShow?.localPrice.pricePerStay}{" "}
|
||||
{priceToShow?.localPrice.currency}
|
||||
</Subtitle>
|
||||
<Body color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Approx." })}{" "}
|
||||
{priceToShow?.requestedPrice?.pricePerStay}{" "}
|
||||
{priceToShow?.requestedPrice?.currency}
|
||||
</Body>
|
||||
</div>
|
||||
<div className={styles.summaryPriceTextMobile}>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Total price" })}
|
||||
</Caption>
|
||||
<Subtitle color={isUserLoggedIn ? "red" : "uiTextHighContrast"}>
|
||||
{priceToShow?.localPrice.pricePerStay}{" "}
|
||||
{priceToShow?.localPrice.currency}
|
||||
</Subtitle>
|
||||
<Footnote
|
||||
color="uiTextMediumContrast"
|
||||
className={styles.summaryPriceTextMobile}
|
||||
>
|
||||
{summaryPriceTex}
|
||||
</Footnote>
|
||||
</div>
|
||||
{isPetRoomSelected && (
|
||||
<div className={styles.petInfo}>
|
||||
<Body
|
||||
color="uiTextHighContrast"
|
||||
textTransform="bold"
|
||||
textAlign="right"
|
||||
>
|
||||
+ {petRoomPrice} {petRoomCurrency}
|
||||
</Body>
|
||||
<Body color="uiTextMediumContrast" textAlign="right">
|
||||
{intl.formatMessage({ id: "Pet charge" })}
|
||||
</Body>
|
||||
<div className={styles.summaryPriceContainer}>
|
||||
{showMemberDiscountBanner && (
|
||||
<div className={styles.memberDiscountBannerDesktop}>
|
||||
<Footnote color="burgundy">
|
||||
{intl.formatMessage<React.ReactNode>(
|
||||
{
|
||||
id: "To get the member price <span>{amount} {currency}</span>, log in or join when completing the booking.",
|
||||
},
|
||||
{
|
||||
span: (str) => (
|
||||
<Caption color="red" type="bold" asChild>
|
||||
<span>{str}</span>
|
||||
</Caption>
|
||||
),
|
||||
amount: member.localPrice.pricePerStay,
|
||||
currency: member.localPrice.currency,
|
||||
}
|
||||
)}
|
||||
</Footnote>
|
||||
</div>
|
||||
)}
|
||||
<Button type="submit" theme="base" className={styles.continueButton}>
|
||||
{intl.formatMessage({ id: "Continue" })}
|
||||
</Button>
|
||||
<div className={styles.summaryPriceTextDesktop}>
|
||||
<Body>
|
||||
{intl.formatMessage<React.ReactNode>(
|
||||
{ id: "<b>Total price</b> (incl VAT)" },
|
||||
{ b: (str) => <b>{str}</b> }
|
||||
)}
|
||||
</Body>
|
||||
<Caption color="uiTextMediumContrast">{summaryPriceTex}</Caption>
|
||||
</div>
|
||||
<div className={styles.summaryPrice}>
|
||||
<div className={styles.summaryPriceTextDesktop}>
|
||||
<Subtitle
|
||||
color={isUserLoggedIn ? "red" : "uiTextHighContrast"}
|
||||
textAlign="right"
|
||||
>
|
||||
{priceToShow?.localPrice.pricePerStay}{" "}
|
||||
{priceToShow?.localPrice.currency}
|
||||
</Subtitle>
|
||||
<Body color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Approx." })}{" "}
|
||||
{priceToShow?.requestedPrice?.pricePerStay}{" "}
|
||||
{priceToShow?.requestedPrice?.currency}
|
||||
</Body>
|
||||
</div>
|
||||
<div className={styles.summaryPriceTextMobile}>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Total price" })}
|
||||
</Caption>
|
||||
<Subtitle color={isUserLoggedIn ? "red" : "uiTextHighContrast"}>
|
||||
{priceToShow?.localPrice.pricePerStay}{" "}
|
||||
{priceToShow?.localPrice.currency}
|
||||
</Subtitle>
|
||||
<Footnote
|
||||
color="uiTextMediumContrast"
|
||||
className={styles.summaryPriceTextMobile}
|
||||
>
|
||||
{summaryPriceTex}
|
||||
</Footnote>
|
||||
</div>
|
||||
{isPetRoomSelected && (
|
||||
<div className={styles.petInfo}>
|
||||
<Body
|
||||
color="uiTextHighContrast"
|
||||
textTransform="bold"
|
||||
textAlign="right"
|
||||
>
|
||||
+ {petRoomPrice} {petRoomCurrency}
|
||||
</Body>
|
||||
<Body color="uiTextMediumContrast" textAlign="right">
|
||||
{intl.formatMessage({ id: "Pet charge" })}
|
||||
</Body>
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
type="submit"
|
||||
theme="base"
|
||||
className={styles.continueButton}
|
||||
>
|
||||
{intl.formatMessage({ id: "Continue" })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,12 +6,19 @@
|
||||
right: 0;
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
padding: 0 0 var(--Spacing-x5);
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--Base-Border-Subtle);
|
||||
transition: bottom 300ms ease-in-out;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
max-width: var(--max-width-navigation);
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--Base-Border-Subtle);
|
||||
transition: bottom 300ms ease-in-out;
|
||||
}
|
||||
|
||||
.summary[data-visible="true"] {
|
||||
@@ -80,7 +87,9 @@
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.summary {
|
||||
padding: var(--Spacing-x3) var(--Spacing-x2) var(--Spacing-x5);
|
||||
padding: var(--Spacing-x3) var(--Spacing-x7) var(--Spacing-x5);
|
||||
}
|
||||
.content {
|
||||
flex-direction: row;
|
||||
}
|
||||
.petInfo,
|
||||
@@ -102,5 +111,6 @@
|
||||
.summaryPriceContainer {
|
||||
width: auto;
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,13 @@ export default function Rooms({
|
||||
const visibleRooms: RoomConfiguration[] =
|
||||
filterDuplicateRoomTypesByLowestPrice(roomsAvailability.roomConfigurations)
|
||||
const [selectedRate, setSelectedRate] = useState<
|
||||
{ publicRateCode: string; roomTypeCode: string } | undefined
|
||||
| {
|
||||
publicRateCode: string
|
||||
roomTypeCode: string
|
||||
name: string
|
||||
paymentTerm: string
|
||||
}
|
||||
| undefined
|
||||
>(undefined)
|
||||
const [selectedPackages, setSelectedPackages] = useState<RoomPackageCodes[]>(
|
||||
[]
|
||||
@@ -115,17 +121,30 @@ export default function Rooms({
|
||||
)
|
||||
)?.features
|
||||
|
||||
const roomType = roomCategories.find((roomCategory) =>
|
||||
roomCategory.roomTypes.some(
|
||||
(roomType) => roomType.code === room.roomTypeCode
|
||||
)
|
||||
)
|
||||
|
||||
const rateSummary: Rate = {
|
||||
features: petRoomPackage && features ? features : [],
|
||||
priceName: room.roomType,
|
||||
priceName: selectedRate?.name,
|
||||
priceTerm: selectedRate?.paymentTerm,
|
||||
public: product.productType.public,
|
||||
member: product.productType.member,
|
||||
roomType: room.roomType,
|
||||
roomType: roomType?.name || room.roomType,
|
||||
roomTypeCode: room.roomTypeCode,
|
||||
}
|
||||
|
||||
return rateSummary
|
||||
}, [filteredRooms, availablePackages, selectedPackages, selectedRate])
|
||||
}, [
|
||||
filteredRooms,
|
||||
availablePackages,
|
||||
selectedPackages,
|
||||
selectedRate,
|
||||
roomCategories,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
if (rateSummary) return
|
||||
|
||||
Reference in New Issue
Block a user