feat: add mobile summary
This commit is contained in:
@@ -45,7 +45,7 @@
|
||||
.iconWrapper {
|
||||
position: relative;
|
||||
top: var(--Spacing-x1);
|
||||
z-index: 2;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.circle {
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
.iconWrapper {
|
||||
position: relative;
|
||||
top: var(--Spacing-x1);
|
||||
z-index: 2;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.circle {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
.wrapper {
|
||||
display: grid;
|
||||
grid-template-rows: 0fr 7.5em;
|
||||
|
||||
transition: 0.5s ease-in-out;
|
||||
border-top: 1px solid var(--Base-Border-Subtle);
|
||||
background: var(--Base-Surface-Primary-light-Normal);
|
||||
align-content: end;
|
||||
}
|
||||
|
||||
.bottomSheet {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
padding: var(--Spacing-x2) var(--Spacing-x3) var(--Spacing-x5)
|
||||
var(--Spacing-x3);
|
||||
justify-content: space-between;
|
||||
width: auto;
|
||||
align-items: flex-start;
|
||||
transition: 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.priceDetails {
|
||||
display: block;
|
||||
border: none;
|
||||
background: none;
|
||||
text-align: start;
|
||||
opacity: 1;
|
||||
transition:
|
||||
opacity 0.5s ease-in-out,
|
||||
padding 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.wrapper[data-open="true"] {
|
||||
grid-template-rows: 1fr 7.5em;
|
||||
}
|
||||
|
||||
.wrapper[data-open="true"] .bottomSheet {
|
||||
grid-template-columns: 0fr 1fr;
|
||||
}
|
||||
|
||||
.wrapper[data-open="true"] .priceDetails {
|
||||
opacity: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content,
|
||||
.priceDetails {
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
"use client"
|
||||
|
||||
import { PropsWithChildren, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
import { formatNumber } from "@/utils/format"
|
||||
|
||||
import styles from "./bottomSheet.module.css"
|
||||
|
||||
export function SummaryBottomSheet({ children }: PropsWithChildren) {
|
||||
const intl = useIntl()
|
||||
|
||||
const { isSummaryOpen, toggleSummaryOpen, totalPrice } = useEnterDetailsStore(
|
||||
(state) => ({
|
||||
isSummaryOpen: state.isSummaryOpen,
|
||||
toggleSummaryOpen: state.toggleSummaryOpen,
|
||||
totalPrice: state.totalPrice,
|
||||
})
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper} data-open={isSummaryOpen}>
|
||||
<div className={styles.content}>{children}</div>
|
||||
<div className={styles.bottomSheet}>
|
||||
<button
|
||||
data-open={isSummaryOpen}
|
||||
onClick={toggleSummaryOpen}
|
||||
className={styles.priceDetails}
|
||||
>
|
||||
<Caption>{intl.formatMessage({ id: "Total price" })}:</Caption>
|
||||
<Subtitle>
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
amount: formatNumber(totalPrice.local.price),
|
||||
currency: totalPrice.local.currency,
|
||||
}
|
||||
)}
|
||||
</Subtitle>
|
||||
<Caption color="baseTextHighContrast" type="underline">
|
||||
{intl.formatMessage({ id: "See details" })}
|
||||
</Caption>
|
||||
</button>
|
||||
<Button intent="primary" size="large" type="submit">
|
||||
{intl.formatMessage({ id: "Complete booking" })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { useIntl } from "react-intl"
|
||||
import { dt } from "@/lib/dt"
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
|
||||
import { ArrowRightIcon } from "@/components/Icons"
|
||||
import { ArrowRightIcon, CloseIcon } from "@/components/Icons"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
@@ -36,20 +36,25 @@ export default function Summary({
|
||||
const [chosenBreakfast, setChosenBreakfast] = useState<
|
||||
BreakfastPackage | BreakfastPackageEnum.NO_BREAKFAST
|
||||
>()
|
||||
const [totalPrice, setTotalPrice] = useState({
|
||||
local: parsePrice(room.localPrice.price),
|
||||
euro: parsePrice(room.euroPrice.price),
|
||||
})
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
const { fromDate, toDate, bedType, breakfast } = useEnterDetailsStore(
|
||||
(state) => ({
|
||||
fromDate: state.roomData.fromDate,
|
||||
toDate: state.roomData.toDate,
|
||||
bedType: state.userData.bedType,
|
||||
breakfast: state.userData.breakfast,
|
||||
})
|
||||
)
|
||||
const {
|
||||
fromDate,
|
||||
toDate,
|
||||
bedType,
|
||||
breakfast,
|
||||
setTotalPrice,
|
||||
totalPrice,
|
||||
toggleSummaryOpen,
|
||||
} = useEnterDetailsStore((state) => ({
|
||||
fromDate: state.roomData.fromDate,
|
||||
toDate: state.roomData.toDate,
|
||||
bedType: state.userData.bedType,
|
||||
breakfast: state.userData.breakfast,
|
||||
toggleSummaryOpen: state.toggleSummaryOpen,
|
||||
setTotalPrice: state.setTotalPrice,
|
||||
totalPrice: state.totalPrice,
|
||||
}))
|
||||
|
||||
const diff = dt(toDate).diff(fromDate, "days")
|
||||
|
||||
@@ -70,21 +75,48 @@ export default function Summary({
|
||||
setChosenBreakfast(breakfast)
|
||||
if (breakfast === BreakfastPackageEnum.NO_BREAKFAST) {
|
||||
setTotalPrice({
|
||||
local: parsePrice(room.localPrice.price),
|
||||
euro: parsePrice(room.euroPrice.price),
|
||||
local: {
|
||||
price: parsePrice(room.localPrice.price),
|
||||
currency: room.localPrice.currency!,
|
||||
},
|
||||
euro: {
|
||||
price: parsePrice(room.euroPrice.price),
|
||||
currency: room.euroPrice.currency!,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
setTotalPrice({
|
||||
local:
|
||||
parsePrice(room.localPrice.price) +
|
||||
parsePrice(breakfast.localPrice.totalPrice),
|
||||
euro:
|
||||
parsePrice(room.euroPrice.price) +
|
||||
parsePrice(breakfast.requestedPrice.totalPrice),
|
||||
local: {
|
||||
price:
|
||||
parsePrice(room.localPrice.price) +
|
||||
parsePrice(breakfast.localPrice.totalPrice),
|
||||
currency: room.localPrice.currency!,
|
||||
},
|
||||
euro: {
|
||||
price:
|
||||
parsePrice(room.euroPrice.price) +
|
||||
parsePrice(breakfast.requestedPrice.totalPrice),
|
||||
currency: room.euroPrice.currency!,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [bedType, breakfast, room.localPrice, room.euroPrice])
|
||||
}, [bedType, breakfast, room.localPrice, room.euroPrice, setTotalPrice])
|
||||
|
||||
useEffect(() => {
|
||||
setTotalPrice({
|
||||
local: {
|
||||
price: parsePrice(room.localPrice.price),
|
||||
currency: room.localPrice.currency!,
|
||||
},
|
||||
euro: {
|
||||
price: parsePrice(room.euroPrice.price),
|
||||
currency: room.euroPrice.currency!,
|
||||
},
|
||||
})
|
||||
}, [room.localPrice, room.euroPrice, setTotalPrice])
|
||||
|
||||
const showToggleButton = true
|
||||
|
||||
return (
|
||||
<section className={styles.summary}>
|
||||
@@ -95,6 +127,7 @@ export default function Summary({
|
||||
<ArrowRightIcon color="peach80" height={15} width={15} />
|
||||
{dt(toDate).locale(lang).format("ddd, D MMM")} ({nights})
|
||||
</Body>
|
||||
{showToggleButton ? <CloseIcon onClick={toggleSummaryOpen} /> : null}
|
||||
</header>
|
||||
<Divider color="primaryLightSubtle" />
|
||||
<div className={styles.addOns}>
|
||||
@@ -203,8 +236,8 @@ export default function Summary({
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
amount: intl.formatNumber(totalPrice.local),
|
||||
currency: room.localPrice.currency,
|
||||
amount: intl.formatNumber(totalPrice.local.price),
|
||||
currency: totalPrice.local.currency,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
@@ -213,14 +246,14 @@ export default function Summary({
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
amount: intl.formatNumber(totalPrice.euro),
|
||||
currency: room.euroPrice.currency,
|
||||
amount: intl.formatNumber(totalPrice.euro.price),
|
||||
currency: totalPrice.euro.currency,
|
||||
}
|
||||
)}
|
||||
</Caption>
|
||||
</div>
|
||||
</div>
|
||||
<Divider color="primaryLightSubtle" />
|
||||
<Divider className={styles.bottomDivider} color="primaryLightSubtle" />
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
@@ -38,3 +38,13 @@
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.bottomDivider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.bottomDivider {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user