Merged in fix/STAY-133 (pull request #3313)
Fix/STAY-133 * fix: Add static summary buttons row on add ancillary flow * fix: refactor handling of modals * fix: refactor file structure for add ancillary flow * Merged in chore/replace-deprecated-body (pull request #3300) Replace deprecated <Body> with <Typography> * chore: replace deprecated body component * refactor: replace Body component with Typography across various components * merge Approved-by: Bianca Widstam Approved-by: Matilda Landström Approved-by: Bianca Widstam Approved-by: Matilda Landström
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modalScrollable {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.form::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import Modal from "@scandic-hotels/design-system/Modal"
|
||||
|
||||
import { useAddAncillaryStore } from "@/stores/my-stay/add-ancillary-flow"
|
||||
|
||||
import styles from "./wrapper.module.css"
|
||||
|
||||
export default function AncillaryFlowModalWrapper({
|
||||
children,
|
||||
}: React.PropsWithChildren) {
|
||||
const { isOpen, closeModal, selectedAncillaryTitle } = useAddAncillaryStore(
|
||||
(state) => ({
|
||||
isOpen: state.isOpen,
|
||||
closeModal: state.closeModal,
|
||||
selectedAncillaryTitle: state.selectedAncillary?.title,
|
||||
})
|
||||
)
|
||||
return (
|
||||
<Modal isOpen={isOpen} onToggle={closeModal} title={selectedAncillaryTitle}>
|
||||
<div className={styles.modalWrapper}>{children}</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
.modalWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 70dvh;
|
||||
width: 100%;
|
||||
margin-top: var(--Space-x3);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.modalWrapper {
|
||||
width: 492px;
|
||||
}
|
||||
}
|
||||
@@ -136,77 +136,81 @@ export default function Summary({
|
||||
: null
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(styles.summary, {
|
||||
[styles.backgroundBox]: isConfirmation || isSingleItem,
|
||||
})}
|
||||
>
|
||||
{(isSingleItem || isConfirmation) && (
|
||||
<PriceDetails
|
||||
totalPrice={totalPrice}
|
||||
totalPoints={totalPoints}
|
||||
selectedAncillary={selectedAncillary}
|
||||
/>
|
||||
)}
|
||||
{isConfirmation && isPriceDetailsOpen && (
|
||||
<PriceSummary
|
||||
totalPrice={totalPrice}
|
||||
totalPoints={totalPoints}
|
||||
items={items}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.summary}>
|
||||
<div
|
||||
className={cx({
|
||||
[styles.confirmButtons]: isConfirmation,
|
||||
[styles.backgroundBox]: isConfirmation || isSingleItem,
|
||||
})}
|
||||
>
|
||||
{isConfirmation && (
|
||||
<Button
|
||||
type="button"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="Small"
|
||||
variant="Text"
|
||||
onPress={togglePriceDetails}
|
||||
className={styles.priceButton}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "commonpriceDetails",
|
||||
defaultMessage: "Price details",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon={
|
||||
isPriceDetailsOpen ? "keyboard_arrow_up" : "keyboard_arrow_down"
|
||||
}
|
||||
size={20}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
</Button>
|
||||
{(isSingleItem || isConfirmation) && (
|
||||
<PriceDetails
|
||||
totalPrice={totalPrice}
|
||||
totalPoints={totalPoints}
|
||||
selectedAncillary={selectedAncillary}
|
||||
/>
|
||||
)}
|
||||
{isConfirmation && isPriceDetailsOpen && (
|
||||
<PriceSummary
|
||||
totalPrice={totalPrice}
|
||||
totalPoints={totalPoints}
|
||||
items={items}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={cx({
|
||||
[styles.confirmButtons]: isConfirmation,
|
||||
})}
|
||||
>
|
||||
{isConfirmation && (
|
||||
<Button
|
||||
type="button"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="Small"
|
||||
variant="Text"
|
||||
onPress={togglePriceDetails}
|
||||
className={styles.priceButton}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "commonpriceDetails",
|
||||
defaultMessage: "Price details",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon={
|
||||
isPriceDetailsOpen
|
||||
? "keyboard_arrow_up"
|
||||
: "keyboard_arrow_down"
|
||||
}
|
||||
size={20}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<div className={styles.buttons}>
|
||||
<Button
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
type="button"
|
||||
variant="Text"
|
||||
size="Small"
|
||||
color="Primary"
|
||||
onPress={() => prevStep(isMobile)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "common.back",
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</Button>
|
||||
<div className={styles.buttons}>
|
||||
<Button
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
type="button"
|
||||
variant="Text"
|
||||
size="Small"
|
||||
color="Primary"
|
||||
onPress={() => prevStep(isMobile)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "common.back",
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="Small"
|
||||
isDisabled={isSubmitting}
|
||||
isPending={isSubmitting}
|
||||
{...buttonProps}
|
||||
>
|
||||
{buttonLabel}
|
||||
</Button>
|
||||
<Button
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="Small"
|
||||
isDisabled={isSubmitting}
|
||||
isPending={isSubmitting}
|
||||
{...buttonProps}
|
||||
>
|
||||
{buttonLabel}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,8 +1,10 @@
|
||||
.summmary {
|
||||
.summary {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-top: var(--Space-x2);
|
||||
padding: var(--Space-x2) var(--Space-x2) var(--Space-x3);
|
||||
width: 100%;
|
||||
border-top: 1px solid var(--Border-Default);
|
||||
}
|
||||
|
||||
.backgroundBox {
|
||||
@@ -0,0 +1,25 @@
|
||||
.modal {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.modalContent {
|
||||
gap: unset;
|
||||
}
|
||||
|
||||
.modalScrollable {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
padding: var(--Space-x2);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.modal {
|
||||
width: 492px;
|
||||
}
|
||||
|
||||
.modalScrollable {
|
||||
padding: var(--Space-x3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import Modal from "@scandic-hotels/design-system/Modal"
|
||||
|
||||
import {
|
||||
AncillaryStepEnum,
|
||||
useAddAncillaryStore,
|
||||
} from "@/stores/my-stay/add-ancillary-flow"
|
||||
|
||||
import Description from "../Description"
|
||||
import Steps from "../Steps"
|
||||
import Summary from "./Summary"
|
||||
|
||||
import styles from "./addAncillaryModal.module.css"
|
||||
|
||||
import type { StepsProps } from "@/types/components/myPages/myStay/ancillaries"
|
||||
|
||||
export default function AddAncillaryModal({
|
||||
error,
|
||||
savedCreditCards,
|
||||
user,
|
||||
}: StepsProps) {
|
||||
const { isOpen, closeModal, selectedAncillaryTitle, currentStep } =
|
||||
useAddAncillaryStore((state) => ({
|
||||
isOpen: state.isOpen,
|
||||
closeModal: state.closeModal,
|
||||
selectedAncillaryTitle: state.selectedAncillary?.title,
|
||||
currentStep: state.currentStep,
|
||||
}))
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onToggle={closeModal}
|
||||
title={selectedAncillaryTitle}
|
||||
withActions
|
||||
contentClassName={styles.modalContent}
|
||||
className={styles.modal}
|
||||
>
|
||||
<div className={styles.modalScrollable}>
|
||||
<Description />
|
||||
<Steps user={user} savedCreditCards={savedCreditCards} error={error} />
|
||||
</div>
|
||||
|
||||
<Summary
|
||||
isConfirmation={currentStep === AncillaryStepEnum.confirmation}
|
||||
/>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
@@ -16,8 +16,6 @@ import { useAddAncillaryStore } from "@/stores/my-stay/add-ancillary-flow"
|
||||
import TermsAndConditions from "@/components/HotelReservation/MyStay/TermsAndConditions"
|
||||
import { trackUpdatePaymentMethod } from "@/utils/tracking"
|
||||
|
||||
import Summary from "../Summary"
|
||||
|
||||
import styles from "./confirmationStep.module.css"
|
||||
|
||||
import type { ConfirmationStepProps } from "@/types/components/myPages/myStay/ancillaries"
|
||||
@@ -228,7 +226,6 @@ export default function ConfirmationStep({
|
||||
</Typography>
|
||||
)}
|
||||
<TermsAndConditions />
|
||||
<Summary isConfirmation />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import { generateDeliveryOptions } from "@/components/HotelReservation/MyStay/ut
|
||||
import Input from "@/components/TempDesignSystem/Form/Input"
|
||||
import Select from "@/components/TempDesignSystem/Form/Select"
|
||||
|
||||
import Summary from "../Summary"
|
||||
|
||||
import styles from "./deliveryDetailsStep.module.css"
|
||||
|
||||
export default function DeliveryMethodStep() {
|
||||
@@ -28,7 +26,7 @@ export default function DeliveryMethodStep() {
|
||||
</Typography>
|
||||
<Select
|
||||
name="deliveryTime"
|
||||
label=""
|
||||
label={""}
|
||||
items={deliveryTimeOptions}
|
||||
registerOptions={{ required: true }}
|
||||
isNestedInModal
|
||||
@@ -61,7 +59,6 @@ export default function DeliveryMethodStep() {
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<Summary />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -18,10 +18,7 @@ export default function Mobile({ user, savedCreditCards, error }: StepsProps) {
|
||||
if (currentStep === AncillaryStepEnum.selectQuantity) {
|
||||
return (
|
||||
<>
|
||||
<SelectQuantityStep
|
||||
user={user}
|
||||
hideSummary={selectedAncillary?.requiresDeliveryTime}
|
||||
/>
|
||||
<SelectQuantityStep user={user} />
|
||||
{selectedAncillary?.requiresDeliveryTime && <DeliveryMethodStep />}
|
||||
</>
|
||||
)
|
||||
@@ -11,7 +11,6 @@ import { useAddAncillaryStore } from "@/stores/my-stay/add-ancillary-flow"
|
||||
import Select from "@/components/TempDesignSystem/Form/Select"
|
||||
import { getErrorMessage } from "@/utils/getErrorMessage"
|
||||
|
||||
import Summary from "../Summary"
|
||||
import { BreakfastInfo } from "./BreakfastInfo"
|
||||
|
||||
import styles from "./selectQuantityStep.module.css"
|
||||
@@ -26,10 +25,7 @@ const cardQuantityOptions = Array.from({ length: 7 }, (_, i) => ({
|
||||
value: i,
|
||||
}))
|
||||
|
||||
export default function SelectQuantityStep({
|
||||
user,
|
||||
hideSummary = false,
|
||||
}: SelectQuantityStepProps) {
|
||||
export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
||||
const { isBreakfast, selectedAncillary } = useAddAncillaryStore((state) => ({
|
||||
isBreakfast: state.isBreakfast,
|
||||
selectedAncillary: state.selectedAncillary,
|
||||
@@ -50,12 +46,7 @@ export default function SelectQuantityStep({
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
{content}
|
||||
{!hideSummary && <Summary />}
|
||||
</div>
|
||||
)
|
||||
return <div className={styles.container}>{content}</div>
|
||||
}
|
||||
|
||||
function InnerSelectQuantityStep({
|
||||
@@ -0,0 +1,6 @@
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -29,10 +29,9 @@ import {
|
||||
trackGlaAncillaryAttempt,
|
||||
} from "@/utils/tracking/myStay"
|
||||
|
||||
import { isAncillaryError } from "../../../utils"
|
||||
import { type AncillaryFormData, ancillaryFormSchema } from "../schema"
|
||||
import Description from "./Description"
|
||||
import Steps from "./Steps"
|
||||
import { isAncillaryError } from "../../utils"
|
||||
import AddAncillaryFlow from "./Modal"
|
||||
import { type AncillaryFormData, ancillaryFormSchema } from "./schema"
|
||||
import {
|
||||
buildBreakfastPackages,
|
||||
calculateBreakfastData,
|
||||
@@ -315,14 +314,11 @@ export default function AddAncillaryFlowModal({
|
||||
className={styles.form}
|
||||
id="add-ancillary-form-id"
|
||||
>
|
||||
<div className={styles.modalScrollable}>
|
||||
<Description />
|
||||
<Steps
|
||||
user={user}
|
||||
savedCreditCards={savedCreditCards}
|
||||
error={errorMessage}
|
||||
/>
|
||||
</div>
|
||||
<AddAncillaryFlow
|
||||
error={errorMessage}
|
||||
savedCreditCards={savedCreditCards}
|
||||
user={user}
|
||||
/>
|
||||
</form>
|
||||
</FormProvider>
|
||||
)
|
||||
@@ -12,7 +12,7 @@ import type { IntlShape } from "react-intl"
|
||||
|
||||
import type { AncillaryErrorMessage } from "@/types/components/myPages/myStay/ancillaries"
|
||||
import type { BreakfastData } from "@/stores/my-stay/add-ancillary-flow"
|
||||
import type { AncillaryFormData } from "../schema"
|
||||
import type { AncillaryFormData } from "./schema"
|
||||
|
||||
/**
|
||||
* This function calculates some breakfast data in the store.
|
||||
Reference in New Issue
Block a user