feat(SW-1063): add member price modal
This commit is contained in:
committed by
Christel Westerberg
parent
a1a36e80d5
commit
42bb71cf2f
@@ -125,6 +125,8 @@
|
|||||||
--dialog-z-index: 9;
|
--dialog-z-index: 9;
|
||||||
--sidepeek-z-index: 100;
|
--sidepeek-z-index: 100;
|
||||||
--lightbox-z-index: 150;
|
--lightbox-z-index: 150;
|
||||||
|
--default-modal-overlay-z-index: 100;
|
||||||
|
--default-modal-z-index: 101;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
|
import { MagicWandIcon } from "@/components/Icons"
|
||||||
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
|
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||||
|
|
||||||
|
import Modal from "../../Modal"
|
||||||
|
|
||||||
|
import styles from "./modal.module.css"
|
||||||
|
|
||||||
|
import type { Dispatch, SetStateAction } from "react"
|
||||||
|
|
||||||
|
export default function MemberPriceModal({
|
||||||
|
isOpen,
|
||||||
|
setIsOpen,
|
||||||
|
}: {
|
||||||
|
isOpen: boolean
|
||||||
|
setIsOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
}) {
|
||||||
|
const memberRate = useEnterDetailsStore((state) => state.roomRate.memberRate)
|
||||||
|
const intl = useIntl()
|
||||||
|
|
||||||
|
const memberPrice = memberRate?.localPrice ?? memberRate?.requestedPrice
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onToggle={setIsOpen}>
|
||||||
|
<div className={styles.modalContent}>
|
||||||
|
<div className={styles.innerModalContent}>
|
||||||
|
<MagicWandIcon width="265px" />
|
||||||
|
<Title as="h3" level="h1" textTransform="regular">
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: "Member price activated",
|
||||||
|
})}
|
||||||
|
</Title>
|
||||||
|
|
||||||
|
{memberPrice && (
|
||||||
|
<span className={styles.newPrice}>
|
||||||
|
<Body>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: "The new price is",
|
||||||
|
})}
|
||||||
|
</Body>
|
||||||
|
<Subtitle type="two" color="red">
|
||||||
|
{intl.formatNumber(memberPrice.pricePerStay, {
|
||||||
|
currency: memberPrice.currency,
|
||||||
|
style: "currency",
|
||||||
|
})}
|
||||||
|
</Subtitle>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Button intent="primary" theme="base" onClick={() => setIsOpen(false)}>
|
||||||
|
OK
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
.modalContent {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Spacing-x3);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.innerModalContent {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Spacing-x2);
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newPrice {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--Spacing-x1);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
.modalContent {
|
||||||
|
width: 352px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import { useCallback } from "react"
|
import { useCallback, useState } from "react"
|
||||||
import { FormProvider, useForm } from "react-hook-form"
|
import { FormProvider, useForm } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ import Phone from "@/components/TempDesignSystem/Form/Phone"
|
|||||||
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
||||||
|
|
||||||
import JoinScandicFriendsCard from "./JoinScandicFriendsCard"
|
import JoinScandicFriendsCard from "./JoinScandicFriendsCard"
|
||||||
|
import MemberPriceModal from "./MemberPriceModal"
|
||||||
import { guestDetailsSchema, signedInDetailsSchema } from "./schema"
|
import { guestDetailsSchema, signedInDetailsSchema } from "./schema"
|
||||||
import Signup from "./Signup"
|
import Signup from "./Signup"
|
||||||
import SpecialRequests from "./SpecialRequests"
|
import SpecialRequests from "./SpecialRequests"
|
||||||
@@ -27,6 +28,8 @@ import type {
|
|||||||
const formID = "enter-details"
|
const formID = "enter-details"
|
||||||
export default function Details({ user, memberPrice }: DetailsProps) {
|
export default function Details({ user, memberPrice }: DetailsProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
const [isMemberPriceModalOpen, setIsMemberPriceModalOpen] = useState(false)
|
||||||
|
|
||||||
const initialData = useEnterDetailsStore((state) => state.guest)
|
const initialData = useEnterDetailsStore((state) => state.guest)
|
||||||
const updateDetails = useEnterDetailsStore(
|
const updateDetails = useEnterDetailsStore(
|
||||||
(state) => state.actions.updateDetails
|
(state) => state.actions.updateDetails
|
||||||
@@ -53,9 +56,12 @@ export default function Details({ user, memberPrice }: DetailsProps) {
|
|||||||
|
|
||||||
const onSubmit = useCallback(
|
const onSubmit = useCallback(
|
||||||
(values: DetailsSchema) => {
|
(values: DetailsSchema) => {
|
||||||
|
if ((values.join || values.membershipNo) && memberPrice) {
|
||||||
|
setIsMemberPriceModalOpen(true)
|
||||||
|
}
|
||||||
updateDetails(values)
|
updateDetails(values)
|
||||||
},
|
},
|
||||||
[updateDetails]
|
[updateDetails, setIsMemberPriceModalOpen, memberPrice]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -130,6 +136,10 @@ export default function Details({ user, memberPrice }: DetailsProps) {
|
|||||||
{intl.formatMessage({ id: "Proceed to payment method" })}
|
{intl.formatMessage({ id: "Proceed to payment method" })}
|
||||||
</Button>
|
</Button>
|
||||||
</footer>
|
</footer>
|
||||||
|
<MemberPriceModal
|
||||||
|
isOpen={isMemberPriceModalOpen}
|
||||||
|
setIsOpen={setIsMemberPriceModalOpen}
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
)
|
)
|
||||||
|
|||||||
150
components/HotelReservation/EnterDetails/Modal/index.tsx
Normal file
150
components/HotelReservation/EnterDetails/Modal/index.tsx
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { motion } from "framer-motion"
|
||||||
|
import { type PropsWithChildren, useEffect, useState } from "react"
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogTrigger,
|
||||||
|
Modal as AriaModal,
|
||||||
|
ModalOverlay,
|
||||||
|
} from "react-aria-components"
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { CloseLargeIcon } from "@/components/Icons"
|
||||||
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
|
|
||||||
|
import {
|
||||||
|
type AnimationState,
|
||||||
|
AnimationStateEnum,
|
||||||
|
type InnerModalProps,
|
||||||
|
type ModalProps,
|
||||||
|
} from "./modal"
|
||||||
|
import { fade, slideInOut } from "./motionVariants"
|
||||||
|
|
||||||
|
import styles from "./modal.module.css"
|
||||||
|
|
||||||
|
const MotionOverlay = motion(ModalOverlay)
|
||||||
|
const MotionModal = motion(AriaModal)
|
||||||
|
|
||||||
|
function InnerModal({
|
||||||
|
animation,
|
||||||
|
onAnimationComplete = () => undefined,
|
||||||
|
setAnimation,
|
||||||
|
onToggle,
|
||||||
|
isOpen,
|
||||||
|
children,
|
||||||
|
title,
|
||||||
|
}: PropsWithChildren<InnerModalProps>) {
|
||||||
|
const intl = useIntl()
|
||||||
|
function modalStateHandler(newAnimationState: AnimationState) {
|
||||||
|
setAnimation((currentAnimationState) =>
|
||||||
|
newAnimationState === AnimationStateEnum.hidden &&
|
||||||
|
currentAnimationState === AnimationStateEnum.hidden
|
||||||
|
? AnimationStateEnum.unmounted
|
||||||
|
: currentAnimationState
|
||||||
|
)
|
||||||
|
if (newAnimationState === AnimationStateEnum.visible) {
|
||||||
|
onAnimationComplete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpenChange(state: boolean) {
|
||||||
|
onToggle!(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MotionOverlay
|
||||||
|
animate={animation}
|
||||||
|
className={styles.overlay}
|
||||||
|
initial={"hidden"}
|
||||||
|
isDismissable
|
||||||
|
isExiting={animation === AnimationStateEnum.hidden}
|
||||||
|
onAnimationComplete={modalStateHandler}
|
||||||
|
variants={fade}
|
||||||
|
isOpen={isOpen}
|
||||||
|
onOpenChange={onOpenChange}
|
||||||
|
>
|
||||||
|
<MotionModal
|
||||||
|
className={styles.modal}
|
||||||
|
variants={slideInOut}
|
||||||
|
animate={animation}
|
||||||
|
initial={"hidden"}
|
||||||
|
>
|
||||||
|
<Dialog className={styles.dialog} aria-label="Dialog">
|
||||||
|
{({ close }) => (
|
||||||
|
<>
|
||||||
|
<header className={styles.header}>
|
||||||
|
{title && (
|
||||||
|
<Subtitle type="one" color="uiTextHighContrast">
|
||||||
|
{title}
|
||||||
|
</Subtitle>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button onClick={close} type="button" className={styles.close}>
|
||||||
|
<CloseLargeIcon color="uiTextMediumContrast" />
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
<section className={styles.content}>{children}</section>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Dialog>
|
||||||
|
</MotionModal>
|
||||||
|
</MotionOverlay>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Modal({
|
||||||
|
onAnimationComplete = () => undefined,
|
||||||
|
trigger,
|
||||||
|
isOpen,
|
||||||
|
onToggle,
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
}: PropsWithChildren<ModalProps>) {
|
||||||
|
const [animation, setAnimation] = useState<AnimationState>(
|
||||||
|
AnimationStateEnum.visible
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof isOpen === "boolean") {
|
||||||
|
setAnimation(
|
||||||
|
isOpen ? AnimationStateEnum.visible : AnimationStateEnum.hidden
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}, [isOpen])
|
||||||
|
|
||||||
|
if (!trigger) {
|
||||||
|
return (
|
||||||
|
<InnerModal
|
||||||
|
onAnimationComplete={onAnimationComplete}
|
||||||
|
animation={animation}
|
||||||
|
setAnimation={setAnimation}
|
||||||
|
onToggle={onToggle}
|
||||||
|
isOpen={isOpen}
|
||||||
|
title={title}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</InnerModal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DialogTrigger
|
||||||
|
onOpenChange={(isOpen) =>
|
||||||
|
setAnimation(
|
||||||
|
isOpen ? AnimationStateEnum.visible : AnimationStateEnum.hidden
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{trigger}
|
||||||
|
<InnerModal
|
||||||
|
onAnimationComplete={onAnimationComplete}
|
||||||
|
animation={animation}
|
||||||
|
setAnimation={setAnimation}
|
||||||
|
title={title}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</InnerModal>
|
||||||
|
</DialogTrigger>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
.overlay {
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
height: var(--visual-viewport-height);
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
z-index: var(--default-modal-overlay-z-index);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||||
|
border-radius: var(--Corner-radius-Medium) var(--Corner-radius-Medium) 0 0;
|
||||||
|
box-shadow: 0px 4px 24px 0px rgba(38, 32, 30, 0.08);
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: var(--default-modal-z-index);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: var(--Spacing-x3);
|
||||||
|
|
||||||
|
/* for supporting animations within content */
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
--button-dimension: 32px;
|
||||||
|
|
||||||
|
box-sizing: content-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: var(--button-dimension);
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
padding: var(--Spacing-x3) var(--Spacing-x2) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--Spacing-x2);
|
||||||
|
padding: 0 var(--Spacing-x3) var(--Spacing-x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
right: var(--Spacing-x2);
|
||||||
|
width: var(--button-dimension);
|
||||||
|
height: var(--button-dimension);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
.overlay {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
left: auto;
|
||||||
|
bottom: auto;
|
||||||
|
width: auto;
|
||||||
|
border-radius: var(--Corner-radius-Medium);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
components/HotelReservation/EnterDetails/Modal/modal.ts
Normal file
26
components/HotelReservation/EnterDetails/Modal/modal.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import type { Dispatch, SetStateAction } from "react"
|
||||||
|
|
||||||
|
export enum AnimationStateEnum {
|
||||||
|
unmounted = "unmounted",
|
||||||
|
hidden = "hidden",
|
||||||
|
visible = "visible",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AnimationState = keyof typeof AnimationStateEnum
|
||||||
|
|
||||||
|
export type ModalProps = {
|
||||||
|
onAnimationComplete?: VoidFunction
|
||||||
|
title?: string
|
||||||
|
} & (
|
||||||
|
| { trigger: JSX.Element; isOpen?: never; onToggle?: never }
|
||||||
|
| {
|
||||||
|
trigger?: never
|
||||||
|
isOpen: boolean
|
||||||
|
onToggle: Dispatch<SetStateAction<boolean>>
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export type InnerModalProps = Omit<ModalProps, "trigger"> & {
|
||||||
|
animation: AnimationState
|
||||||
|
setAnimation: Dispatch<SetStateAction<AnimationState>>
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
export const fade = {
|
||||||
|
hidden: {
|
||||||
|
opacity: 0,
|
||||||
|
transition: { duration: 0.4, ease: "easeInOut" },
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: { duration: 0.4, ease: "easeInOut" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const slideInOut = {
|
||||||
|
hidden: {
|
||||||
|
opacity: 0,
|
||||||
|
y: 32,
|
||||||
|
transition: { duration: 0.4, ease: "easeInOut" },
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: { duration: 0.4, ease: "easeInOut" },
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -5,16 +5,21 @@ import { dt } from "@/lib/dt"
|
|||||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
|
import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
|
||||||
import { ArrowRightIcon, ChevronDownSmallIcon } from "@/components/Icons"
|
import {
|
||||||
|
ArrowRightIcon,
|
||||||
|
ChevronDownSmallIcon,
|
||||||
|
ChevronRightSmallIcon,
|
||||||
|
} from "@/components/Icons"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
import Divider from "@/components/TempDesignSystem/Divider"
|
import Divider from "@/components/TempDesignSystem/Divider"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
|
||||||
import Popover from "@/components/TempDesignSystem/Popover"
|
import Popover from "@/components/TempDesignSystem/Popover"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
|
import Modal from "../../Modal"
|
||||||
|
|
||||||
import styles from "./ui.module.css"
|
import styles from "./ui.module.css"
|
||||||
|
|
||||||
import type { SummaryProps } from "@/types/components/hotelReservation/summary"
|
import type { SummaryProps } from "@/types/components/hotelReservation/summary"
|
||||||
@@ -31,6 +36,7 @@ export function storeSelector(state: DetailsState) {
|
|||||||
roomRate: state.roomRate,
|
roomRate: state.roomRate,
|
||||||
roomPrice: state.roomPrice,
|
roomPrice: state.roomPrice,
|
||||||
toggleSummaryOpen: state.actions.toggleSummaryOpen,
|
toggleSummaryOpen: state.actions.toggleSummaryOpen,
|
||||||
|
togglePriceDetailsModalOpen: state.actions.togglePriceDetailsModalOpen,
|
||||||
totalPrice: state.totalPrice,
|
totalPrice: state.totalPrice,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,6 +60,7 @@ export default function SummaryUI({
|
|||||||
roomPrice,
|
roomPrice,
|
||||||
roomRate,
|
roomRate,
|
||||||
toggleSummaryOpen,
|
toggleSummaryOpen,
|
||||||
|
togglePriceDetailsModalOpen,
|
||||||
totalPrice,
|
totalPrice,
|
||||||
} = useEnterDetailsStore(storeSelector)
|
} = useEnterDetailsStore(storeSelector)
|
||||||
|
|
||||||
@@ -82,6 +89,12 @@ export default function SummaryUI({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleTogglePriceDetailsModal() {
|
||||||
|
if (togglePriceDetailsModalOpen) {
|
||||||
|
togglePriceDetailsModalOpen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.summary}>
|
<section className={styles.summary}>
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
@@ -243,9 +256,28 @@ export default function SummaryUI({
|
|||||||
{ b: (str) => <b>{str}</b> }
|
{ b: (str) => <b>{str}</b> }
|
||||||
)}
|
)}
|
||||||
</Body>
|
</Body>
|
||||||
<Link color="burgundy" href="" variant="underscored" size="small">
|
<Modal
|
||||||
|
trigger={
|
||||||
|
<Button intent="text" onPress={handleTogglePriceDetailsModal}>
|
||||||
|
<Caption color="burgundy">
|
||||||
{intl.formatMessage({ id: "Price details" })}
|
{intl.formatMessage({ id: "Price details" })}
|
||||||
</Link>
|
</Caption>
|
||||||
|
<ChevronRightSmallIcon
|
||||||
|
color="burgundy"
|
||||||
|
height="20px"
|
||||||
|
width="20px"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={styles.modalContent}>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||||
|
eiusmod tempor incididunt ut labore et dolore magna aliqua. Arcu
|
||||||
|
risus quis varius quam quisque id diam vel. Rhoncus urna neque
|
||||||
|
viverra justo. Mattis aliquam faucibus purus in massa. Id cursus
|
||||||
|
metus aliquam eleifend mi in nulla posuere.
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Body textTransform="bold">
|
<Body textTransform="bold">
|
||||||
|
|||||||
@@ -68,6 +68,10 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modalContent {
|
||||||
|
width: 560px;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1367px) {
|
@media screen and (min-width: 1367px) {
|
||||||
.bottomDivider {
|
.bottomDivider {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -55,7 +55,10 @@ a.text {
|
|||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
/* TODO: The variants for combinations of size/text/wrapping should be looked at and iterated on */
|
||||||
|
.text:not(.wrapping) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
/* VARIANTS */
|
/* VARIANTS */
|
||||||
.default,
|
.default,
|
||||||
a.default {
|
a.default {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
|
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input :global(.react-aria-SelectValue) {
|
.input :global(.react-aria-SelectValue) {
|
||||||
|
|||||||
@@ -236,6 +236,7 @@
|
|||||||
"Marketing city": "Marketing by",
|
"Marketing city": "Marketing by",
|
||||||
"Meetings & Conferences": "Møder & Konferencer",
|
"Meetings & Conferences": "Møder & Konferencer",
|
||||||
"Member price": "Medlemspris",
|
"Member price": "Medlemspris",
|
||||||
|
"Member price activated": "Medlemspris aktiveret",
|
||||||
"Member price from": "Medlemspris fra",
|
"Member price from": "Medlemspris fra",
|
||||||
"Members": "Medlemmer",
|
"Members": "Medlemmer",
|
||||||
"Membership ID": "Medlems-id",
|
"Membership ID": "Medlems-id",
|
||||||
@@ -403,6 +404,7 @@
|
|||||||
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Fortæl os, hvilke oplysninger og opdateringer du gerne vil modtage, og hvordan, ved at klikke på linket nedenfor.",
|
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Fortæl os, hvilke oplysninger og opdateringer du gerne vil modtage, og hvordan, ved at klikke på linket nedenfor.",
|
||||||
"Terms and conditions": "Vilkår og betingelser",
|
"Terms and conditions": "Vilkår og betingelser",
|
||||||
"Thank you": "Tak",
|
"Thank you": "Tak",
|
||||||
|
"The new price is": "Nyprisen er",
|
||||||
"The price has increased": "Prisen er steget",
|
"The price has increased": "Prisen er steget",
|
||||||
"The price has increased since you selected your room.": "Prisen er steget, efter at du har valgt dit værelse.",
|
"The price has increased since you selected your room.": "Prisen er steget, efter at du har valgt dit værelse.",
|
||||||
"Theatre": "Teater",
|
"Theatre": "Teater",
|
||||||
|
|||||||
@@ -236,6 +236,7 @@
|
|||||||
"Marketing city": "Marketingstadt",
|
"Marketing city": "Marketingstadt",
|
||||||
"Meetings & Conferences": "Tagungen & Konferenzen",
|
"Meetings & Conferences": "Tagungen & Konferenzen",
|
||||||
"Member price": "Mitgliederpreis",
|
"Member price": "Mitgliederpreis",
|
||||||
|
"Member price activated": "Mitgliederpreis aktiviert",
|
||||||
"Member price from": "Mitgliederpreis ab",
|
"Member price from": "Mitgliederpreis ab",
|
||||||
"Members": "Mitglieder",
|
"Members": "Mitglieder",
|
||||||
"Membership ID": "Mitglieds-ID",
|
"Membership ID": "Mitglieds-ID",
|
||||||
@@ -403,6 +404,7 @@
|
|||||||
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Teilen Sie uns mit, welche Informationen und Updates Sie wie erhalten möchten, indem Sie auf den unten stehenden Link klicken.",
|
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Teilen Sie uns mit, welche Informationen und Updates Sie wie erhalten möchten, indem Sie auf den unten stehenden Link klicken.",
|
||||||
"Terms and conditions": "Geschäftsbedingungen",
|
"Terms and conditions": "Geschäftsbedingungen",
|
||||||
"Thank you": "Danke",
|
"Thank you": "Danke",
|
||||||
|
"The new price is": "Der neue Preis beträgt",
|
||||||
"The price has increased": "Der Preis ist gestiegen",
|
"The price has increased": "Der Preis ist gestiegen",
|
||||||
"The price has increased since you selected your room.": "Der Preis ist gestiegen, nachdem Sie Ihr Zimmer ausgewählt haben.",
|
"The price has increased since you selected your room.": "Der Preis ist gestiegen, nachdem Sie Ihr Zimmer ausgewählt haben.",
|
||||||
"Theatre": "Theater",
|
"Theatre": "Theater",
|
||||||
|
|||||||
@@ -254,6 +254,7 @@
|
|||||||
"Meetings & Conferences": "Meetings & Conferences",
|
"Meetings & Conferences": "Meetings & Conferences",
|
||||||
"Member discount": "Member discount",
|
"Member discount": "Member discount",
|
||||||
"Member price": "Member price",
|
"Member price": "Member price",
|
||||||
|
"Member price activated": "Member price activated",
|
||||||
"Member price from": "Member price from",
|
"Member price from": "Member price from",
|
||||||
"Members": "Members",
|
"Members": "Members",
|
||||||
"Membership ID": "Membership ID",
|
"Membership ID": "Membership ID",
|
||||||
@@ -440,6 +441,7 @@
|
|||||||
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Tell us what information and updates you'd like to receive, and how, by clicking the link below.",
|
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Tell us what information and updates you'd like to receive, and how, by clicking the link below.",
|
||||||
"Terms and conditions": "Terms and conditions",
|
"Terms and conditions": "Terms and conditions",
|
||||||
"Thank you": "Thank you",
|
"Thank you": "Thank you",
|
||||||
|
"The new price is": "The new price is",
|
||||||
"The price has increased": "The price has increased",
|
"The price has increased": "The price has increased",
|
||||||
"The price has increased since you selected your room.": "The price has increased since you selected your room.",
|
"The price has increased since you selected your room.": "The price has increased since you selected your room.",
|
||||||
"Theatre": "Theatre",
|
"Theatre": "Theatre",
|
||||||
|
|||||||
@@ -236,6 +236,7 @@
|
|||||||
"Marketing city": "Markkinointikaupunki",
|
"Marketing city": "Markkinointikaupunki",
|
||||||
"Meetings & Conferences": "Kokoukset & Konferenssit",
|
"Meetings & Conferences": "Kokoukset & Konferenssit",
|
||||||
"Member price": "Jäsenhinta",
|
"Member price": "Jäsenhinta",
|
||||||
|
"Member price activated": "Jäsenhinta aktivoitu",
|
||||||
"Member price from": "Jäsenhinta alkaen",
|
"Member price from": "Jäsenhinta alkaen",
|
||||||
"Members": "Jäsenet",
|
"Members": "Jäsenet",
|
||||||
"Membership ID": "Jäsentunnus",
|
"Membership ID": "Jäsentunnus",
|
||||||
@@ -404,6 +405,7 @@
|
|||||||
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Kerro meille, mitä tietoja ja päivityksiä haluat saada ja miten, napsauttamalla alla olevaa linkkiä.",
|
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Kerro meille, mitä tietoja ja päivityksiä haluat saada ja miten, napsauttamalla alla olevaa linkkiä.",
|
||||||
"Terms and conditions": "Käyttöehdot",
|
"Terms and conditions": "Käyttöehdot",
|
||||||
"Thank you": "Kiitos",
|
"Thank you": "Kiitos",
|
||||||
|
"The new price is": "Uusi hinta on",
|
||||||
"The price has increased": "Hinta on noussut",
|
"The price has increased": "Hinta on noussut",
|
||||||
"The price has increased since you selected your room.": "Hinta on noussut, koska valitsit huoneen.",
|
"The price has increased since you selected your room.": "Hinta on noussut, koska valitsit huoneen.",
|
||||||
"Theatre": "Teatteri",
|
"Theatre": "Teatteri",
|
||||||
|
|||||||
@@ -235,6 +235,7 @@
|
|||||||
"Marketing city": "Markedsføringsby",
|
"Marketing city": "Markedsføringsby",
|
||||||
"Meetings & Conferences": "Møter & Konferanser",
|
"Meetings & Conferences": "Møter & Konferanser",
|
||||||
"Member price": "Medlemspris",
|
"Member price": "Medlemspris",
|
||||||
|
"Member price activated": "Medlemspris aktivert",
|
||||||
"Member price from": "Medlemspris fra",
|
"Member price from": "Medlemspris fra",
|
||||||
"Members": "Medlemmer",
|
"Members": "Medlemmer",
|
||||||
"Membership ID": "Medlems-ID",
|
"Membership ID": "Medlems-ID",
|
||||||
@@ -402,6 +403,7 @@
|
|||||||
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Fortell oss hvilken informasjon og hvilke oppdateringer du ønsker å motta, og hvordan, ved å klikke på lenken nedenfor.",
|
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Fortell oss hvilken informasjon og hvilke oppdateringer du ønsker å motta, og hvordan, ved å klikke på lenken nedenfor.",
|
||||||
"Terms and conditions": "Vilkår og betingelser",
|
"Terms and conditions": "Vilkår og betingelser",
|
||||||
"Thank you": "Takk",
|
"Thank you": "Takk",
|
||||||
|
"The new price is": "Den nye prisen er",
|
||||||
"The price has increased": "Prisen er steget",
|
"The price has increased": "Prisen er steget",
|
||||||
"The price has increased since you selected your room.": "Prisen er steget, etter at du har valgt rommet.",
|
"The price has increased since you selected your room.": "Prisen er steget, etter at du har valgt rommet.",
|
||||||
"Theatre": "Teater",
|
"Theatre": "Teater",
|
||||||
|
|||||||
@@ -235,6 +235,7 @@
|
|||||||
"Marketing city": "Marknadsföringsstad",
|
"Marketing city": "Marknadsföringsstad",
|
||||||
"Meetings & Conferences": "Möten & Konferenser",
|
"Meetings & Conferences": "Möten & Konferenser",
|
||||||
"Member price": "Medlemspris",
|
"Member price": "Medlemspris",
|
||||||
|
"Member price activated": "Medlemspris aktiverat",
|
||||||
"Member price from": "Medlemspris från",
|
"Member price from": "Medlemspris från",
|
||||||
"Members": "Medlemmar",
|
"Members": "Medlemmar",
|
||||||
"Membership ID": "Medlems-ID",
|
"Membership ID": "Medlems-ID",
|
||||||
@@ -402,6 +403,7 @@
|
|||||||
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Berätta för oss vilken information och vilka uppdateringar du vill få och hur genom att klicka på länken nedan.",
|
"Tell us what information and updates you'd like to receive, and how, by clicking the link below.": "Berätta för oss vilken information och vilka uppdateringar du vill få och hur genom att klicka på länken nedan.",
|
||||||
"Terms and conditions": "Allmänna villkor",
|
"Terms and conditions": "Allmänna villkor",
|
||||||
"Thank you": "Tack",
|
"Thank you": "Tack",
|
||||||
|
"The new price is": "Det nya priset är",
|
||||||
"The price has increased": "Priset har ökat",
|
"The price has increased": "Priset har ökat",
|
||||||
"The price has increased since you selected your room.": "Priset har ökat sedan du valde ditt rum.",
|
"The price has increased since you selected your room.": "Priset har ökat sedan du valde ditt rum.",
|
||||||
"Theatre": "Teater",
|
"Theatre": "Teater",
|
||||||
|
|||||||
@@ -174,6 +174,13 @@ export function createDetailsStore(
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
togglePriceDetailsModalOpen() {
|
||||||
|
return set(
|
||||||
|
produce((state: DetailsState) => {
|
||||||
|
state.isPriceDetailsModalOpen = !state.isPriceDetailsModalOpen
|
||||||
|
})
|
||||||
|
)
|
||||||
|
},
|
||||||
updateBedType(bedType) {
|
updateBedType(bedType) {
|
||||||
return set(
|
return set(
|
||||||
produce((state: DetailsState) => {
|
produce((state: DetailsState) => {
|
||||||
@@ -328,6 +335,7 @@ export function createDetailsStore(
|
|||||||
: defaultGuestState,
|
: defaultGuestState,
|
||||||
isSubmittingDisabled: false,
|
isSubmittingDisabled: false,
|
||||||
isSummaryOpen: false,
|
isSummaryOpen: false,
|
||||||
|
isPriceDetailsModalOpen: false,
|
||||||
isValid: {
|
isValid: {
|
||||||
[StepEnum.selectBed]: false,
|
[StepEnum.selectBed]: false,
|
||||||
[StepEnum.breakfast]: false,
|
[StepEnum.breakfast]: false,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export interface DetailsState {
|
|||||||
setStep: (step: StepEnum) => void
|
setStep: (step: StepEnum) => void
|
||||||
setTotalPrice: (totalPrice: Price) => void
|
setTotalPrice: (totalPrice: Price) => void
|
||||||
toggleSummaryOpen: () => void
|
toggleSummaryOpen: () => void
|
||||||
|
togglePriceDetailsModalOpen: () => void
|
||||||
updateBedType: (data: BedTypeSchema) => void
|
updateBedType: (data: BedTypeSchema) => void
|
||||||
updateBreakfast: (data: BreakfastPackage | false) => void
|
updateBreakfast: (data: BreakfastPackage | false) => void
|
||||||
updateDetails: (data: DetailsSchema) => void
|
updateDetails: (data: DetailsSchema) => void
|
||||||
@@ -47,6 +48,7 @@ export interface DetailsState {
|
|||||||
guest: DetailsSchema
|
guest: DetailsSchema
|
||||||
isSubmittingDisabled: boolean
|
isSubmittingDisabled: boolean
|
||||||
isSummaryOpen: boolean
|
isSummaryOpen: boolean
|
||||||
|
isPriceDetailsModalOpen: boolean
|
||||||
isValid: Record<StepEnum, boolean>
|
isValid: Record<StepEnum, boolean>
|
||||||
packages: Packages | null
|
packages: Packages | null
|
||||||
roomRate: DetailsProviderProps["roomRate"]
|
roomRate: DetailsProviderProps["roomRate"]
|
||||||
|
|||||||
Reference in New Issue
Block a user