Merged in fix/SW-2406-update-modal-ancillaries (pull request #1911)
fix(SW-2406): update modal for ancillaries * fix(SW-2406): update modal for ancillaries * fix(SW-2406): revert translations Approved-by: Niclas Edenvin Approved-by: Erik Tiekstra
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--Spacing-x4);
|
gap: var(--Spacing-x4);
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
padding: var(--Space-x15) var(--Space-x15) 0;
|
padding: var(--Space-x2) var(--Space-x15) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirmButtons {
|
.confirmButtons {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export default function ActionButtons({
|
|||||||
const {
|
const {
|
||||||
currentStep,
|
currentStep,
|
||||||
prevStep,
|
prevStep,
|
||||||
|
prevStepMobile,
|
||||||
selectQuantity,
|
selectQuantity,
|
||||||
selectDeliveryTime,
|
selectDeliveryTime,
|
||||||
selectQuantityAndDeliveryTime,
|
selectQuantityAndDeliveryTime,
|
||||||
@@ -33,6 +34,7 @@ export default function ActionButtons({
|
|||||||
} = useAddAncillaryStore((state) => ({
|
} = useAddAncillaryStore((state) => ({
|
||||||
currentStep: state.currentStep,
|
currentStep: state.currentStep,
|
||||||
prevStep: state.prevStep,
|
prevStep: state.prevStep,
|
||||||
|
prevStepMobile: state.prevStepMobile,
|
||||||
selectQuantity: state.selectQuantity,
|
selectQuantity: state.selectQuantity,
|
||||||
selectDeliveryTime: state.selectDeliveryTime,
|
selectDeliveryTime: state.selectDeliveryTime,
|
||||||
selectQuantityAndDeliveryTime: state.selectQuantityAndDeliveryTime,
|
selectQuantityAndDeliveryTime: state.selectQuantityAndDeliveryTime,
|
||||||
@@ -116,7 +118,7 @@ export default function ActionButtons({
|
|||||||
variant="Text"
|
variant="Text"
|
||||||
size="Small"
|
size="Small"
|
||||||
color="Primary"
|
color="Primary"
|
||||||
onPress={prevStep}
|
onPress={isMobile ? prevStepMobile : prevStep}
|
||||||
>
|
>
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
defaultMessage: "Back",
|
defaultMessage: "Back",
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
.selectContainer {
|
.selectContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--Spacing-x2);
|
gap: var(--Space-x2);
|
||||||
margin-bottom: var(--Spacing-x2);
|
padding: var(--Space-x3);
|
||||||
|
margin-bottom: var(--Space-x05);
|
||||||
|
background-color: var(--Base-Background-Primary-Normal);
|
||||||
|
border-radius: var(--Corner-radius-Medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
.select {
|
.select {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--Spacing-x2);
|
gap: var(--Space-x1);
|
||||||
padding: var(--Spacing-x2) var(--Spacing-x3);
|
|
||||||
background-color: var(--Base-Background-Primary-Normal);
|
|
||||||
border-radius: var(--Corner-radius-Medium);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import { generateDeliveryOptions } from "@/components/HotelReservation/MyStay/utils/ancillaries"
|
import { generateDeliveryOptions } from "@/components/HotelReservation/MyStay/utils/ancillaries"
|
||||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||||
import Select from "@/components/TempDesignSystem/Form/Select"
|
import Select from "@/components/TempDesignSystem/Form/Select"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
|
||||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
|
||||||
|
|
||||||
import styles from "./deliveryDetailsStep.module.css"
|
import styles from "./deliveryDetailsStep.module.css"
|
||||||
|
|
||||||
@@ -16,11 +15,13 @@ export default function DeliveryMethodStep() {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.selectContainer}>
|
<div className={styles.selectContainer}>
|
||||||
<div className={styles.select}>
|
<div className={styles.select}>
|
||||||
<Subtitle type="two">
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
{intl.formatMessage({
|
<h3>
|
||||||
defaultMessage: "Delivered at:",
|
{intl.formatMessage({
|
||||||
})}
|
defaultMessage: "Delivered at:",
|
||||||
</Subtitle>
|
})}
|
||||||
|
</h3>
|
||||||
|
</Typography>
|
||||||
<Select
|
<Select
|
||||||
name="deliveryTime"
|
name="deliveryTime"
|
||||||
label={""}
|
label={""}
|
||||||
@@ -28,13 +29,15 @@ export default function DeliveryMethodStep() {
|
|||||||
registerOptions={{ required: true }}
|
registerOptions={{ required: true }}
|
||||||
isNestedInModal
|
isNestedInModal
|
||||||
/>
|
/>
|
||||||
<Body>
|
</div>
|
||||||
|
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||||
|
<p>
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"All add-ons are delivered at the same time. Changes to delivery times will affect earlier add-ons.",
|
"All add-ons are delivered at the same time. Changes to delivery times will affect earlier add-ons.",
|
||||||
})}
|
})}
|
||||||
</Body>
|
</p>
|
||||||
</div>
|
</Typography>
|
||||||
<div className={styles.select}>
|
<div className={styles.select}>
|
||||||
<Input
|
<Input
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
@@ -42,11 +45,13 @@ export default function DeliveryMethodStep() {
|
|||||||
})}
|
})}
|
||||||
name="optionalText"
|
name="optionalText"
|
||||||
/>
|
/>
|
||||||
<Caption>
|
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||||
{intl.formatMessage({
|
<h3>
|
||||||
defaultMessage: "Optional",
|
{intl.formatMessage({
|
||||||
})}
|
defaultMessage: "Optional",
|
||||||
</Caption>
|
})}
|
||||||
|
</h3>
|
||||||
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -50,20 +50,12 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
|||||||
|
|
||||||
const insufficientPoints = currentPoints < pointsCost || currentPoints === 0
|
const insufficientPoints = currentPoints < pointsCost || currentPoints === 0
|
||||||
|
|
||||||
const pointsLabel = insufficientPoints
|
|
||||||
? intl.formatMessage({
|
|
||||||
defaultMessage: "Insufficient points",
|
|
||||||
})
|
|
||||||
: intl.formatMessage({
|
|
||||||
defaultMessage: "Select quantity",
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.selectContainer}>
|
<div className={styles.selectContainer}>
|
||||||
{selectedAncillary?.points && user && (
|
{selectedAncillary?.points && user && (
|
||||||
<div className={styles.select}>
|
<div className={styles.select}>
|
||||||
<Typography variant="Title/Subtitle/md">
|
<Typography variant="Title/Subtitle/md">
|
||||||
<h2>
|
<h2 className={styles.selectTitle}>
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
defaultMessage: "Pay with points",
|
defaultMessage: "Pay with points",
|
||||||
})}
|
})}
|
||||||
@@ -84,18 +76,29 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
|||||||
<p>{currentPoints}</p>
|
<p>{currentPoints}</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<Select
|
{insufficientPoints ? (
|
||||||
name="quantityWithPoints"
|
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||||
label={pointsLabel}
|
<h2 className={styles.insufficientPoints}>
|
||||||
items={pointsQuantityOptions}
|
{intl.formatMessage({
|
||||||
disabled={insufficientPoints}
|
defaultMessage: "Insufficient points",
|
||||||
isNestedInModal
|
})}
|
||||||
/>
|
</h2>
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<Select
|
||||||
|
name="quantityWithPoints"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
defaultMessage: "Select quantity",
|
||||||
|
})}
|
||||||
|
items={pointsQuantityOptions}
|
||||||
|
isNestedInModal
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={styles.select}>
|
<div className={styles.select}>
|
||||||
<Typography variant="Title/Subtitle/md">
|
<Typography variant="Title/Subtitle/md">
|
||||||
<h2>
|
<h2 className={styles.selectTitle}>
|
||||||
{
|
{
|
||||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||||
" "
|
" "
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--Space-x025);
|
gap: var(--Space-x025);
|
||||||
margin-bottom: var(--Space-x2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.select {
|
.select {
|
||||||
@@ -15,6 +14,14 @@
|
|||||||
margin-bottom: var(--Spacing-x1);
|
margin-bottom: var(--Spacing-x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selectTitle {
|
||||||
|
margin-bottom: var(--Space-x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.insufficientPoints {
|
||||||
|
color: var(--Text-Tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
.totalPointsContainer {
|
.totalPointsContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -73,6 +80,9 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
|
.select {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
.icon {
|
.icon {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: 70dvh;
|
max-height: 70dvh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
margin-top: var(--Space-x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form {
|
.form {
|
||||||
@@ -19,22 +20,6 @@
|
|||||||
.modalScrollable {
|
.modalScrollable {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-bottom: var(--Spacing-x2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.imageContainer {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
aspect-ratio: 16 / 9;
|
|
||||||
border-radius: var(--Corner-radius-Medium);
|
|
||||||
overflow: hidden;
|
|
||||||
margin-top: var(--Spacing-x1);
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin-bottom: var(--Spacing-x3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.image {
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.price {
|
.price {
|
||||||
@@ -52,12 +37,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
position: sticky;
|
|
||||||
border-radius: var(--Corner-radius-Medium);
|
border-radius: var(--Corner-radius-Medium);
|
||||||
bottom: 0;
|
|
||||||
z-index: 10;
|
|
||||||
background: var(--Surface-Primary-OnSurface-Default);
|
background: var(--Surface-Primary-OnSurface-Default);
|
||||||
padding-bottom: var(--Space-x15);
|
padding-bottom: var(--Space-x15);
|
||||||
|
margin-top: var(--Space-x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
@@ -65,15 +48,6 @@
|
|||||||
margin: var(--Spacing-x2) 0;
|
margin: var(--Spacing-x2) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionButtons {
|
|
||||||
position: sticky;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 10;
|
|
||||||
background: var(--UI-Opacity-White-100);
|
|
||||||
border-top: 1px solid var(--Base-Border-Normal);
|
|
||||||
padding-bottom: var(--Space-x025);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pointsDivider {
|
.pointsDivider {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--Space-x2);
|
gap: var(--Space-x2);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import {
|
|||||||
getAncillarySessionData,
|
getAncillarySessionData,
|
||||||
setAncillarySessionData,
|
setAncillarySessionData,
|
||||||
} from "@/components/HotelReservation/MyStay/utils/ancillaries"
|
} from "@/components/HotelReservation/MyStay/utils/ancillaries"
|
||||||
import Image from "@/components/Image"
|
|
||||||
import LoadingSpinner from "@/components/LoadingSpinner"
|
import LoadingSpinner from "@/components/LoadingSpinner"
|
||||||
import Modal from "@/components/Modal"
|
import Modal from "@/components/Modal"
|
||||||
import Divider from "@/components/TempDesignSystem/Divider"
|
import Divider from "@/components/TempDesignSystem/Divider"
|
||||||
@@ -351,14 +350,6 @@ export default function AddAncillaryFlowModal({
|
|||||||
<div className={styles.modalScrollable}>
|
<div className={styles.modalScrollable}>
|
||||||
{selectedAncillary && (
|
{selectedAncillary && (
|
||||||
<>
|
<>
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<Image
|
|
||||||
className={styles.image}
|
|
||||||
src={selectedAncillary.imageUrl}
|
|
||||||
alt={selectedAncillary.title}
|
|
||||||
fill
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{currentStep !== AncillaryStepEnum.confirmation && (
|
{currentStep !== AncillaryStepEnum.confirmation && (
|
||||||
<div className={styles.contentContainer}>
|
<div className={styles.contentContainer}>
|
||||||
<div className={styles.price}>
|
<div className={styles.price}>
|
||||||
@@ -409,24 +400,24 @@ export default function AddAncillaryFlowModal({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Steps user={user} savedCreditCards={savedCreditCards} />
|
<Steps user={user} savedCreditCards={savedCreditCards} />
|
||||||
|
{currentStep === AncillaryStepEnum.selectAncillary ? null : (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
currentStep === AncillaryStepEnum.confirmation
|
||||||
|
? styles.confirmStep
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<PriceDetails isPriceDetailsOpen={isPriceDetailsOpen} />
|
||||||
|
<ActionButtons
|
||||||
|
isPriceDetailsOpen={isPriceDetailsOpen}
|
||||||
|
togglePriceDetails={togglePriceDetails}
|
||||||
|
isSubmitting={addAncillary.isPending || isLoading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{currentStep === AncillaryStepEnum.selectAncillary ? null : (
|
|
||||||
<div
|
|
||||||
className={
|
|
||||||
currentStep === AncillaryStepEnum.confirmation
|
|
||||||
? styles.confirmStep
|
|
||||||
: styles.actionButtons
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<PriceDetails isPriceDetailsOpen={isPriceDetailsOpen} />
|
|
||||||
<ActionButtons
|
|
||||||
isPriceDetailsOpen={isPriceDetailsOpen}
|
|
||||||
togglePriceDetails={togglePriceDetails}
|
|
||||||
isSubmitting={addAncillary.isPending || isLoading}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export interface AddAncillaryState {
|
|||||||
openModal: () => void
|
openModal: () => void
|
||||||
closeModal: () => void
|
closeModal: () => void
|
||||||
prevStep: () => void
|
prevStep: () => void
|
||||||
|
prevStepMobile: () => void
|
||||||
breakfastData: BreakfastData | null
|
breakfastData: BreakfastData | null
|
||||||
setBreakfastData: (breakfastData: BreakfastData | null) => void
|
setBreakfastData: (breakfastData: BreakfastData | null) => void
|
||||||
isBreakfast: boolean
|
isBreakfast: boolean
|
||||||
@@ -194,6 +195,23 @@ export const createAddAncillaryStore = (
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
prevStepMobile: () =>
|
||||||
|
set(
|
||||||
|
produce((state: AddAncillaryState) => {
|
||||||
|
if (state.currentStep === AncillaryStepEnum.selectQuantity) {
|
||||||
|
state.isOpen = false
|
||||||
|
clearAncillarySessionData()
|
||||||
|
state.selectedAncillary = null
|
||||||
|
state.steps = steps
|
||||||
|
} else {
|
||||||
|
if (state.currentStep === AncillaryStepEnum.confirmation) {
|
||||||
|
state.currentStep = AncillaryStepEnum.selectQuantity
|
||||||
|
} else {
|
||||||
|
state.currentStep = state.currentStep - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
selectAncillary: (ancillary) =>
|
selectAncillary: (ancillary) =>
|
||||||
set(
|
set(
|
||||||
produce((state: AddAncillaryState) => {
|
produce((state: AddAncillaryState) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user