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;
|
||||
gap: var(--Spacing-x4);
|
||||
justify-content: flex-end;
|
||||
padding: var(--Space-x15) var(--Space-x15) 0;
|
||||
padding: var(--Space-x2) var(--Space-x15) 0;
|
||||
}
|
||||
|
||||
.confirmButtons {
|
||||
|
||||
@@ -26,6 +26,7 @@ export default function ActionButtons({
|
||||
const {
|
||||
currentStep,
|
||||
prevStep,
|
||||
prevStepMobile,
|
||||
selectQuantity,
|
||||
selectDeliveryTime,
|
||||
selectQuantityAndDeliveryTime,
|
||||
@@ -33,6 +34,7 @@ export default function ActionButtons({
|
||||
} = useAddAncillaryStore((state) => ({
|
||||
currentStep: state.currentStep,
|
||||
prevStep: state.prevStep,
|
||||
prevStepMobile: state.prevStepMobile,
|
||||
selectQuantity: state.selectQuantity,
|
||||
selectDeliveryTime: state.selectDeliveryTime,
|
||||
selectQuantityAndDeliveryTime: state.selectQuantityAndDeliveryTime,
|
||||
@@ -116,7 +118,7 @@ export default function ActionButtons({
|
||||
variant="Text"
|
||||
size="Small"
|
||||
color="Primary"
|
||||
onPress={prevStep}
|
||||
onPress={isMobile ? prevStepMobile : prevStep}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Back",
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
.selectContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
margin-bottom: var(--Spacing-x2);
|
||||
gap: var(--Space-x2);
|
||||
padding: var(--Space-x3);
|
||||
margin-bottom: var(--Space-x05);
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
}
|
||||
|
||||
.select {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
padding: var(--Spacing-x2) var(--Spacing-x3);
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { generateDeliveryOptions } from "@/components/HotelReservation/MyStay/utils/ancillaries"
|
||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||
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"
|
||||
|
||||
@@ -16,11 +15,13 @@ export default function DeliveryMethodStep() {
|
||||
return (
|
||||
<div className={styles.selectContainer}>
|
||||
<div className={styles.select}>
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Delivered at:",
|
||||
})}
|
||||
</Subtitle>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Delivered at:",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Select
|
||||
name="deliveryTime"
|
||||
label={""}
|
||||
@@ -28,13 +29,15 @@ export default function DeliveryMethodStep() {
|
||||
registerOptions={{ required: true }}
|
||||
isNestedInModal
|
||||
/>
|
||||
<Body>
|
||||
</div>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage:
|
||||
"All add-ons are delivered at the same time. Changes to delivery times will affect earlier add-ons.",
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
</p>
|
||||
</Typography>
|
||||
<div className={styles.select}>
|
||||
<Input
|
||||
label={intl.formatMessage({
|
||||
@@ -42,11 +45,13 @@ export default function DeliveryMethodStep() {
|
||||
})}
|
||||
name="optionalText"
|
||||
/>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Optional",
|
||||
})}
|
||||
</Caption>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Optional",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -50,20 +50,12 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
||||
|
||||
const insufficientPoints = currentPoints < pointsCost || currentPoints === 0
|
||||
|
||||
const pointsLabel = insufficientPoints
|
||||
? intl.formatMessage({
|
||||
defaultMessage: "Insufficient points",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage: "Select quantity",
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={styles.selectContainer}>
|
||||
{selectedAncillary?.points && user && (
|
||||
<div className={styles.select}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>
|
||||
<h2 className={styles.selectTitle}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Pay with points",
|
||||
})}
|
||||
@@ -84,18 +76,29 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
||||
<p>{currentPoints}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<Select
|
||||
name="quantityWithPoints"
|
||||
label={pointsLabel}
|
||||
items={pointsQuantityOptions}
|
||||
disabled={insufficientPoints}
|
||||
isNestedInModal
|
||||
/>
|
||||
{insufficientPoints ? (
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<h2 className={styles.insufficientPoints}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Insufficient points",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
) : (
|
||||
<Select
|
||||
name="quantityWithPoints"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Select quantity",
|
||||
})}
|
||||
items={pointsQuantityOptions}
|
||||
isNestedInModal
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.select}>
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>
|
||||
<h2 className={styles.selectTitle}>
|
||||
{
|
||||
/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */
|
||||
" "
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Space-x025);
|
||||
margin-bottom: var(--Space-x2);
|
||||
}
|
||||
|
||||
.select {
|
||||
@@ -15,6 +14,14 @@
|
||||
margin-bottom: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.selectTitle {
|
||||
margin-bottom: var(--Space-x1);
|
||||
}
|
||||
|
||||
.insufficientPoints {
|
||||
color: var(--Text-Tertiary);
|
||||
}
|
||||
|
||||
.totalPointsContainer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -73,6 +80,9 @@
|
||||
display: none;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
.select {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.icon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
flex-direction: column;
|
||||
max-height: 70dvh;
|
||||
width: 100%;
|
||||
margin-top: var(--Space-x3);
|
||||
}
|
||||
|
||||
.form {
|
||||
@@ -19,22 +20,6 @@
|
||||
.modalScrollable {
|
||||
display: flex;
|
||||
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 {
|
||||
@@ -52,12 +37,10 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
position: sticky;
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
background: var(--Surface-Primary-OnSurface-Default);
|
||||
padding-bottom: var(--Space-x15);
|
||||
margin-top: var(--Space-x2);
|
||||
}
|
||||
|
||||
.description {
|
||||
@@ -65,15 +48,6 @@
|
||||
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 {
|
||||
display: flex;
|
||||
gap: var(--Space-x2);
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
getAncillarySessionData,
|
||||
setAncillarySessionData,
|
||||
} from "@/components/HotelReservation/MyStay/utils/ancillaries"
|
||||
import Image from "@/components/Image"
|
||||
import LoadingSpinner from "@/components/LoadingSpinner"
|
||||
import Modal from "@/components/Modal"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
@@ -351,14 +350,6 @@ export default function AddAncillaryFlowModal({
|
||||
<div className={styles.modalScrollable}>
|
||||
{selectedAncillary && (
|
||||
<>
|
||||
<div className={styles.imageContainer}>
|
||||
<Image
|
||||
className={styles.image}
|
||||
src={selectedAncillary.imageUrl}
|
||||
alt={selectedAncillary.title}
|
||||
fill
|
||||
/>
|
||||
</div>
|
||||
{currentStep !== AncillaryStepEnum.confirmation && (
|
||||
<div className={styles.contentContainer}>
|
||||
<div className={styles.price}>
|
||||
@@ -409,24 +400,24 @@ export default function AddAncillaryFlowModal({
|
||||
</>
|
||||
)}
|
||||
<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>
|
||||
</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>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@@ -52,6 +52,7 @@ export interface AddAncillaryState {
|
||||
openModal: () => void
|
||||
closeModal: () => void
|
||||
prevStep: () => void
|
||||
prevStepMobile: () => void
|
||||
breakfastData: BreakfastData | null
|
||||
setBreakfastData: (breakfastData: BreakfastData | null) => void
|
||||
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) =>
|
||||
set(
|
||||
produce((state: AddAncillaryState) => {
|
||||
|
||||
Reference in New Issue
Block a user