Merged in feat/SW-2612-mystay-breakfast-buffet-u (pull request #2059)
Feat: SW-2612 Updated breakfast ancillary UI and Optimised code * Feat: SW-2612 Updated breakfast ancillary UI and Optimised code * feat: SW-2612 Updated UI as per figma * feat: SW-2612 Optimised code * feat: SW-2612 Optimised code Approved-by: Tobias Johansson
This commit is contained in:
@@ -2,12 +2,12 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--Spacing-x4);
|
gap: var(--Spacing-x4);
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
padding: var(--Space-x2) var(--Space-x15) 0;
|
padding: var(--Space-x2) var(--Space-x15) 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirmButtons {
|
.confirmButtons {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 var(--Space-x15);
|
padding-left: var(--Space-x15);
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default function ActionButtons({
|
|||||||
}: ActionButtonsProps) {
|
}: ActionButtonsProps) {
|
||||||
const {
|
const {
|
||||||
currentStep,
|
currentStep,
|
||||||
|
isBreakfast,
|
||||||
prevStep,
|
prevStep,
|
||||||
prevStepMobile,
|
prevStepMobile,
|
||||||
selectQuantity,
|
selectQuantity,
|
||||||
@@ -33,6 +34,7 @@ export default function ActionButtons({
|
|||||||
selectedAncillary,
|
selectedAncillary,
|
||||||
} = useAddAncillaryStore((state) => ({
|
} = useAddAncillaryStore((state) => ({
|
||||||
currentStep: state.currentStep,
|
currentStep: state.currentStep,
|
||||||
|
isBreakfast: state.isBreakfast,
|
||||||
prevStep: state.prevStep,
|
prevStep: state.prevStep,
|
||||||
prevStepMobile: state.prevStepMobile,
|
prevStepMobile: state.prevStepMobile,
|
||||||
selectQuantity: state.selectQuantity,
|
selectQuantity: state.selectQuantity,
|
||||||
@@ -96,19 +98,13 @@ export default function ActionButtons({
|
|||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
defaultMessage: "Price details",
|
defaultMessage: "Price details",
|
||||||
})}
|
})}
|
||||||
{isPriceDetailsOpen ? (
|
<MaterialIcon
|
||||||
<MaterialIcon
|
icon={
|
||||||
icon="keyboard_arrow_up"
|
isPriceDetailsOpen ? "keyboard_arrow_up" : "keyboard_arrow_down"
|
||||||
size={20}
|
}
|
||||||
color="Icon/Interactive/Accent"
|
size={20}
|
||||||
/>
|
color="Icon/Interactive/Accent"
|
||||||
) : (
|
/>
|
||||||
<MaterialIcon
|
|
||||||
icon="keyboard_arrow_down"
|
|
||||||
size={20}
|
|
||||||
color="Icon/Interactive/Accent"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<div className={styles.buttons}>
|
<div className={styles.buttons}>
|
||||||
@@ -140,7 +136,7 @@ export default function ActionButtons({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
typography="Body/Supporting text (caption)/smBold"
|
typography="Body/Supporting text (caption)/smBold"
|
||||||
variant="Secondary"
|
variant={isBreakfast ? "Primary" : "Secondary"}
|
||||||
size="Small"
|
size="Small"
|
||||||
isDisabled={isSubmitting}
|
isDisabled={isSubmitting}
|
||||||
onPress={handleNextStep}
|
onPress={handleNextStep}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Fragment } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
@@ -44,7 +45,7 @@ export default function PriceSummary({
|
|||||||
<Divider color="subtle" />
|
<Divider color="subtle" />
|
||||||
|
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<>
|
<Fragment key={item.title}>
|
||||||
{!!item.quantityWithCard && (
|
{!!item.quantityWithCard && (
|
||||||
<PriceRow
|
<PriceRow
|
||||||
title={item.title}
|
title={item.title}
|
||||||
@@ -68,7 +69,7 @@ export default function PriceSummary({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Divider color="subtle" />
|
<Divider color="subtle" />
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className={styles.column}>
|
<div className={styles.column}>
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ export default function PriceDetails({
|
|||||||
const quantityWithPoints = useWatch({ name: "quantityWithPoints" })
|
const quantityWithPoints = useWatch({ name: "quantityWithPoints" })
|
||||||
const quantityWithCard = useWatch({ name: "quantityWithCard" })
|
const quantityWithCard = useWatch({ name: "quantityWithCard" })
|
||||||
|
|
||||||
if (!selectedAncillary || currentStep !== AncillaryStepEnum.confirmation) {
|
if (
|
||||||
|
!selectedAncillary ||
|
||||||
|
(currentStep !== AncillaryStepEnum.confirmation && !isBreakfast)
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,8 +150,69 @@ export default function PriceDetails({
|
|||||||
</p>
|
</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
{isBreakfast && breakfastData ? (
|
||||||
|
<Typography variant="Body/Paragraph/mdBold">
|
||||||
|
<p className={styles.hideOnDesktop}>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{
|
||||||
|
defaultMessage:
|
||||||
|
"{totalNights, plural, one {# night} other {# nights}}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
totalNights: breakfastData.nrOfNights,
|
||||||
|
}
|
||||||
|
) +
|
||||||
|
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||||
|
" / " +
|
||||||
|
intl.formatMessage(
|
||||||
|
{
|
||||||
|
defaultMessage:
|
||||||
|
"{value, plural, one {# guest} other {# guests}}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value:
|
||||||
|
breakfastData.nrOfAdults +
|
||||||
|
breakfastData.nrOfPayingChildren +
|
||||||
|
breakfastData.nrOfFreeChildren,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.totalPriceValue}>
|
<div className={styles.totalPriceValue}>
|
||||||
|
{isBreakfast && breakfastData ? (
|
||||||
|
<>
|
||||||
|
<Typography variant="Body/Paragraph/mdBold">
|
||||||
|
<p className={styles.showOnDesktop}>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{
|
||||||
|
defaultMessage:
|
||||||
|
"{totalNights, plural, one {# night} other {# nights}}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
totalNights: breakfastData.nrOfNights,
|
||||||
|
}
|
||||||
|
) +
|
||||||
|
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||||
|
" / " +
|
||||||
|
intl.formatMessage(
|
||||||
|
{
|
||||||
|
defaultMessage:
|
||||||
|
"{value, plural, one {# guest} other {# guests}}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value:
|
||||||
|
breakfastData.nrOfAdults +
|
||||||
|
breakfastData.nrOfPayingChildren +
|
||||||
|
breakfastData.nrOfFreeChildren,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
|
<Divider variant="vertical" color="subtle" />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
{hasTotalPrice && (
|
{hasTotalPrice && (
|
||||||
<Typography variant="Body/Paragraph/mdBold">
|
<Typography variant="Body/Paragraph/mdBold">
|
||||||
<p>
|
<p>
|
||||||
@@ -185,7 +249,7 @@ export default function PriceDetails({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Divider color="subtle" />
|
<Divider color="subtle" />
|
||||||
{isPriceDetailsOpen && (
|
{isPriceDetailsOpen && currentStep === AncillaryStepEnum.confirmation && (
|
||||||
<PriceSummary
|
<PriceSummary
|
||||||
totalPrice={totalPrice}
|
totalPrice={totalPrice}
|
||||||
totalPoints={totalPoints}
|
totalPoints={totalPoints}
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
.totalPrice {
|
.totalPrice {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: var(--Spacing-x1);
|
gap: var(--Spacing-x1);
|
||||||
padding: var(--Spacing-x-one-and-half);
|
padding: var(--Spacing-x-one-and-half);
|
||||||
background-color: var(--Base-Surface-Secondary-light-Normal);
|
background-color: var(--Base-Surface-Secondary-light-Normal);
|
||||||
border-radius: var(--Corner-radius-md);
|
border-radius: var(--Corner-radius-md);
|
||||||
}
|
}
|
||||||
|
.showOnDesktop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.totalPriceInclVAT {
|
.totalPriceInclVAT {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--Space-x15);
|
gap: var(--Space-x15);
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.totalPriceValue {
|
.totalPriceValue {
|
||||||
@@ -22,3 +26,15 @@
|
|||||||
.vatText {
|
.vatText {
|
||||||
color: var(--Text-Tertiary);
|
color: var(--Text-Tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
.showOnDesktop {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.hideOnDesktop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.totalPrice {
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,10 +126,6 @@ function BreakfastInfo() {
|
|||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const breakfastData = useAddAncillaryStore((state) => state.breakfastData)
|
const breakfastData = useAddAncillaryStore((state) => state.breakfastData)
|
||||||
|
|
||||||
const { setValue } = useFormContext()
|
|
||||||
|
|
||||||
setValue("quantityWithCard", 1)
|
|
||||||
|
|
||||||
if (!breakfastData) {
|
if (!breakfastData) {
|
||||||
return intl.formatMessage({
|
return intl.formatMessage({
|
||||||
defaultMessage: "Can not show breakfast prices.",
|
defaultMessage: "Can not show breakfast prices.",
|
||||||
|
|||||||
@@ -91,7 +91,8 @@ export default function AddAncillaryFlowModal({
|
|||||||
const formMethods = useForm<AncillaryFormData>({
|
const formMethods = useForm<AncillaryFormData>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
quantityWithPoints: null,
|
quantityWithPoints: null,
|
||||||
quantityWithCard: !user || hasInsufficientPoints ? 1 : null,
|
quantityWithCard:
|
||||||
|
!user || hasInsufficientPoints || isBreakfast ? 1 : null,
|
||||||
deliveryTime: defaultDeliveryTime,
|
deliveryTime: defaultDeliveryTime,
|
||||||
optionalText: "",
|
optionalText: "",
|
||||||
termsAndConditions: false,
|
termsAndConditions: false,
|
||||||
@@ -357,17 +358,17 @@ export default function AddAncillaryFlowModal({
|
|||||||
<div className={styles.contentContainer}>
|
<div className={styles.contentContainer}>
|
||||||
<div className={styles.price}>
|
<div className={styles.price}>
|
||||||
<Typography variant="Body/Paragraph/mdBold">
|
<Typography variant="Body/Paragraph/mdBold">
|
||||||
<p>
|
{isBreakfast ? (
|
||||||
{isBreakfast ? (
|
<BreakfastPriceList />
|
||||||
<BreakfastPriceList />
|
) : (
|
||||||
) : (
|
<p>
|
||||||
formatPrice(
|
{formatPrice(
|
||||||
intl,
|
intl,
|
||||||
selectedAncillary.price.total,
|
selectedAncillary.price.total,
|
||||||
selectedAncillary.price.currency
|
selectedAncillary.price.currency
|
||||||
)
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
{selectedAncillary.points && (
|
{selectedAncillary.points && (
|
||||||
<div className={styles.pointsDivider}>
|
<div className={styles.pointsDivider}>
|
||||||
@@ -406,7 +407,8 @@ export default function AddAncillaryFlowModal({
|
|||||||
{currentStep === AncillaryStepEnum.selectAncillary ? null : (
|
{currentStep === AncillaryStepEnum.selectAncillary ? null : (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
currentStep === AncillaryStepEnum.confirmation
|
currentStep === AncillaryStepEnum.confirmation ||
|
||||||
|
isBreakfast
|
||||||
? styles.confirmStep
|
? styles.confirmStep
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--Spacing-x-half);
|
gap: var(--Spacing-x-half);
|
||||||
padding: 0 var(--Spacing-x2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Fragment } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
@@ -71,7 +72,7 @@ export function AddedAncillaries({
|
|||||||
} X${ancillary.totalUnit}`
|
} X${ancillary.totalUnit}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Fragment key={ancillary.code}>
|
||||||
<Accordion className={styles.ancillaryMobile}>
|
<Accordion className={styles.ancillaryMobile}>
|
||||||
<AccordionItem
|
<AccordionItem
|
||||||
title={ancillaryTitle}
|
title={ancillaryTitle}
|
||||||
@@ -209,7 +210,7 @@ export function AddedAncillaries({
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</Fragment>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user