feat: add mobile summary
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
.mobileSummary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.desktopSummary {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.summary {
|
||||
background-color: var(--Main-Grey-White);
|
||||
|
||||
border-color: var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-bottom: none;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.hider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.mobileSummary {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.desktopSummary {
|
||||
display: grid;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
margin-top: calc(0px - var(--Spacing-x9));
|
||||
}
|
||||
|
||||
.summary {
|
||||
position: sticky;
|
||||
top: calc(
|
||||
var(--booking-widget-desktop-height) + var(--Spacing-x2) +
|
||||
var(--Spacing-x-half)
|
||||
);
|
||||
z-index: 10;
|
||||
border-radius: var(--Corner-radius-Large) var(--Corner-radius-Large) 0 0;
|
||||
margin-top: calc(0px - var(--Spacing-x9));
|
||||
}
|
||||
|
||||
.shadow {
|
||||
display: block;
|
||||
background-color: var(--Main-Grey-White);
|
||||
border-color: var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
border-style: solid;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.hider {
|
||||
display: block;
|
||||
background-color: var(--Scandic-Brand-Warm-White);
|
||||
position: sticky;
|
||||
top: calc(var(--booking-widget-desktop-height) - 6px);
|
||||
margin-top: var(--Spacing-x4);
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,14 @@ import {
|
||||
} from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import Summary from "@/components/HotelReservation/EnterDetails/Summary"
|
||||
import { SummaryBottomSheet } from "@/components/HotelReservation/EnterDetails/Summary/BottomSheet"
|
||||
import {
|
||||
generateChildrenString,
|
||||
getQueryParamsForEnterDetails,
|
||||
} from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import { LangParams, PageArgs, SearchParams } from "@/types/params"
|
||||
|
||||
@@ -62,16 +65,41 @@ export default async function SummaryPage({
|
||||
}
|
||||
|
||||
return (
|
||||
<Summary
|
||||
showMemberPrice={!!(user && availability.memberRate)}
|
||||
room={{
|
||||
roomType: availability.selectedRoom.roomType,
|
||||
localPrice: prices.local,
|
||||
euroPrice: prices.euro,
|
||||
adults,
|
||||
children,
|
||||
cancellationText: availability.cancellationText,
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
<div className={styles.mobileSummary}>
|
||||
<SummaryBottomSheet>
|
||||
<div className={styles.summary}>
|
||||
<Summary
|
||||
showMemberPrice={!!(user && availability.memberRate)}
|
||||
room={{
|
||||
roomType: availability.selectedRoom.roomType,
|
||||
localPrice: prices.local,
|
||||
euroPrice: prices.euro,
|
||||
adults,
|
||||
children,
|
||||
cancellationText: availability.cancellationText,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SummaryBottomSheet>
|
||||
</div>
|
||||
<div className={styles.desktopSummary}>
|
||||
<div className={styles.hider} />
|
||||
<div className={styles.summary}>
|
||||
<Summary
|
||||
showMemberPrice={!!(user && availability.memberRate)}
|
||||
room={{
|
||||
roomType: availability.selectedRoom.roomType,
|
||||
localPrice: prices.local,
|
||||
euroPrice: prices.euro,
|
||||
adults,
|
||||
children,
|
||||
cancellationText: availability.cancellationText,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.shadow} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
.enter-details-layout__content {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x3) var(--Spacing-x9);
|
||||
grid-template-columns: 1fr 340px;
|
||||
grid-template-rows: auto 1fr;
|
||||
margin: var(--Spacing-x5) auto 0;
|
||||
/* simulates padding on viewport smaller than --max-width-navigation */
|
||||
width: min(
|
||||
@@ -22,80 +20,23 @@
|
||||
}
|
||||
|
||||
.enter-details-layout__summaryContainer {
|
||||
grid-column: 2 / 3;
|
||||
grid-row: 1/-1;
|
||||
}
|
||||
|
||||
.enter-details-layout__summary {
|
||||
background-color: var(--Main-Grey-White);
|
||||
|
||||
border-color: var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: var(--Corner-radius-Large);
|
||||
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.enter-details-layout__hider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.enter-details-layout__shadow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.enter-details-layout__summaryContainer {
|
||||
display: grid;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
margin-top: calc(0px - var(--Spacing-x9));
|
||||
}
|
||||
|
||||
.enter-details-layout__summary {
|
||||
position: sticky;
|
||||
top: calc(
|
||||
var(--booking-widget-desktop-height) +
|
||||
var(--booking-widget-desktop-height) + var(--Spacing-x-one-and-half)
|
||||
);
|
||||
margin-top: calc(0px - var(--Spacing-x9));
|
||||
border-bottom: none;
|
||||
border-radius: var(--Corner-radius-Large) var(--Corner-radius-Large) 0 0;
|
||||
}
|
||||
|
||||
.enter-details-layout__hider {
|
||||
display: block;
|
||||
background-color: var(--Scandic-Brand-Warm-White);
|
||||
position: sticky;
|
||||
margin-top: var(--Spacing-x4);
|
||||
top: calc(
|
||||
var(--booking-widget-desktop-height) +
|
||||
var(--booking-widget-desktop-height) - 6px
|
||||
);
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.enter-details-layout__shadow {
|
||||
display: block;
|
||||
background-color: var(--Main-Grey-White);
|
||||
border-color: var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
border-style: solid;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.enter-details-layout__summary {
|
||||
top: calc(
|
||||
var(--booking-widget-desktop-height) + var(--Spacing-x2) +
|
||||
var(--Spacing-x-half)
|
||||
);
|
||||
.enter-details-layout__content {
|
||||
grid-template-columns: 1fr 340px;
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
|
||||
.enter-details-layout__hider {
|
||||
top: calc(var(--booking-widget-desktop-height) - 6px);
|
||||
.enter-details-layout__summaryContainer {
|
||||
position: static;
|
||||
display: grid;
|
||||
grid-column: 2/3;
|
||||
grid-row: 1/-1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,7 @@ export default async function StepLayout({
|
||||
{hotelHeader}
|
||||
<div className={"enter-details-layout__content"}>
|
||||
{children}
|
||||
<aside className="enter-details-layout__summaryContainer">
|
||||
<div className="enter-details-layout__hider" />
|
||||
<div className="enter-details-layout__summary">{summary}</div>
|
||||
<div className="enter-details-layout__shadow" />
|
||||
</aside>
|
||||
<aside className={"enter-details-layout__summaryContainer"}>{summary}</aside>
|
||||
</div>
|
||||
</main>
|
||||
</EnterDetailsProvider>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,15 @@ p.caption {
|
||||
text-decoration: var(--typography-Caption-Labels-textDecoration);
|
||||
}
|
||||
|
||||
.underline {
|
||||
font-family: var(--typography-Caption-Underline-fontFamily);
|
||||
font-size: var(--typography-Caption-Underline-fontSize);
|
||||
font-weight: var(--typography-Caption-Underline-fontWeight);
|
||||
letter-spacing: var(--typography-Caption-Underline-letterSpacing);
|
||||
line-height: var(--typography-Caption-Underline-lineHeight);
|
||||
text-decoration: underline; /* var(--typography-Caption-Underline-textDecoration) /* Commented till figma values are fixed to underline instead of "underline" */
|
||||
}
|
||||
|
||||
.regular {
|
||||
font-family: var(--typography-Caption-Regular-fontFamily);
|
||||
font-size: var(--typography-Caption-Regular-fontSize);
|
||||
@@ -58,6 +67,10 @@ p.caption {
|
||||
color: var(--Base-Text-Medium-contrast);
|
||||
}
|
||||
|
||||
.baseTextHighContrast {
|
||||
color: var(--Base-Text-High-contrast);
|
||||
}
|
||||
|
||||
.red {
|
||||
color: var(--Scandic-Brand-Scandic-Red);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ const config = {
|
||||
regular: styles.regular,
|
||||
bold: styles.bold,
|
||||
label: styles.labels,
|
||||
underline: styles.underline,
|
||||
},
|
||||
color: {
|
||||
baseTextAccent: styles.baseTextAccent,
|
||||
@@ -22,6 +23,7 @@ const config = {
|
||||
uiTextMediumContrast: styles.uiTextMediumContrast,
|
||||
uiTextPlaceholder: styles.uiTextPlaceholder,
|
||||
disabled: styles.disabled,
|
||||
baseTextHighContrast: styles.baseTextHighContrast,
|
||||
},
|
||||
textTransform: {
|
||||
uppercase: styles.uppercase,
|
||||
@@ -48,6 +50,7 @@ const fontOnlyConfig = {
|
||||
regular: styles.regular,
|
||||
bold: styles.bold,
|
||||
label: styles.labels,
|
||||
underline: styles.underline,
|
||||
},
|
||||
textTransform: {
|
||||
uppercase: styles.uppercase,
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"Bus terminal": "Busstation",
|
||||
"Business": "Forretning",
|
||||
"Cancel": "Afbestille",
|
||||
"Change room": "Skift værelse",
|
||||
"Check in": "Check ind",
|
||||
"Check out": "Check ud",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Tjek de kreditkort, der er gemt på din profil. Betal med et gemt kort, når du er logget ind for en mere jævn weboplevelse.",
|
||||
@@ -71,6 +72,7 @@
|
||||
"Code / Voucher": "Bookingkoder / voucher",
|
||||
"Coming up": "Er lige om hjørnet",
|
||||
"Compare all levels": "Sammenlign alle niveauer",
|
||||
"Complete booking": "Fuldfør bookingen",
|
||||
"Complete booking & go to payment": "Udfyld booking & gå til betaling",
|
||||
"Complete the booking": "Fuldfør bookingen",
|
||||
"Contact information": "Kontaktoplysninger",
|
||||
@@ -285,6 +287,7 @@
|
||||
"Search": "Søge",
|
||||
"See all FAQ": "Se alle FAQ",
|
||||
"See all photos": "Se alle billeder",
|
||||
"See details": "Se detaljer",
|
||||
"See hotel details": "Se hoteloplysninger",
|
||||
"See less FAQ": "Se mindre FAQ",
|
||||
"See on map": "Se på kort",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"Bus terminal": "Busbahnhof",
|
||||
"Business": "Geschäft",
|
||||
"Cancel": "Stornieren",
|
||||
"Change room": "Zimmer ändern",
|
||||
"Check in": "Einchecken",
|
||||
"Check out": "Auschecken",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Sehen Sie sich die in Ihrem Profil gespeicherten Kreditkarten an. Bezahlen Sie mit einer gespeicherten Karte, wenn Sie angemeldet sind, für ein reibungsloseres Web-Erlebnis.",
|
||||
@@ -71,6 +72,7 @@
|
||||
"Code / Voucher": "Buchungscodes / Gutscheine",
|
||||
"Coming up": "Demnächst",
|
||||
"Compare all levels": "Vergleichen Sie alle Levels",
|
||||
"Complete booking": "Buchung abschließen",
|
||||
"Complete booking & go to payment": "Buchung abschließen & zur Bezahlung gehen",
|
||||
"Complete the booking": "Buchung abschließen",
|
||||
"Contact information": "Kontaktinformationen",
|
||||
@@ -284,6 +286,7 @@
|
||||
"Search": "Suchen",
|
||||
"See all FAQ": "Siehe alle FAQ",
|
||||
"See all photos": "Alle Fotos ansehen",
|
||||
"See details": "Siehe Einzelheiten",
|
||||
"See hotel details": "Hotelinformationen ansehen",
|
||||
"See less FAQ": "Weniger anzeigen FAQ",
|
||||
"See on map": "Karte ansehen",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"Code / Voucher": "Code / Voucher",
|
||||
"Coming up": "Coming up",
|
||||
"Compare all levels": "Compare all levels",
|
||||
"Complete booking": "Complete booking",
|
||||
"Complete booking & go to payment": "Complete booking & go to payment",
|
||||
"Complete the booking": "Complete the booking",
|
||||
"Contact information": "Contact information",
|
||||
@@ -314,6 +315,7 @@
|
||||
"Search": "Search",
|
||||
"See all FAQ": "See all FAQ",
|
||||
"See all photos": "See all photos",
|
||||
"See details": "See details",
|
||||
"See hotel details": "See hotel details",
|
||||
"See less FAQ": "See less FAQ",
|
||||
"See on map": "See on map",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"Bus terminal": "Bussiasema",
|
||||
"Business": "Business",
|
||||
"Cancel": "Peruuttaa",
|
||||
"Change room": "Vaihda huonetta",
|
||||
"Check in": "Sisäänkirjautuminen",
|
||||
"Check out": "Uloskirjautuminen",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Tarkista profiiliisi tallennetut luottokortit. Maksa tallennetulla kortilla kirjautuneena, jotta verkkokokemus on sujuvampi.",
|
||||
@@ -71,6 +72,7 @@
|
||||
"Code / Voucher": "Varauskoodit / kupongit",
|
||||
"Coming up": "Tulossa",
|
||||
"Compare all levels": "Vertaa kaikkia tasoja",
|
||||
"Complete booking": "Täydennä varaus",
|
||||
"Complete booking & go to payment": "Täydennä varaus & siirry maksamaan",
|
||||
"Complete the booking": "Täydennä varaus",
|
||||
"Contact information": "Yhteystiedot",
|
||||
@@ -286,6 +288,7 @@
|
||||
"Search": "Haku",
|
||||
"See all FAQ": "Katso kaikki UKK",
|
||||
"See all photos": "Katso kaikki kuvat",
|
||||
"See details": "Katso tiedot",
|
||||
"See hotel details": "Katso hotellin tiedot",
|
||||
"See less FAQ": "Katso vähemmän UKK",
|
||||
"See on map": "Näytä kartalla",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"Bus terminal": "Bussterminal",
|
||||
"Business": "Forretnings",
|
||||
"Cancel": "Avbryt",
|
||||
"Change room": "Endre rom",
|
||||
"Check in": "Sjekk inn",
|
||||
"Check out": "Sjekk ut",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Sjekk ut kredittkortene som er lagret på profilen din. Betal med et lagret kort når du er pålogget for en jevnere nettopplevelse.",
|
||||
@@ -71,6 +72,7 @@
|
||||
"Code / Voucher": "Bestillingskoder / kuponger",
|
||||
"Coming up": "Kommer opp",
|
||||
"Compare all levels": "Sammenlign alle nivåer",
|
||||
"Complete booking": "Fullfør reservasjonen",
|
||||
"Complete booking & go to payment": "Fullfør bestilling & gå til betaling",
|
||||
"Complete the booking": "Fullfør reservasjonen",
|
||||
"Contact information": "Kontaktinformasjon",
|
||||
@@ -283,6 +285,7 @@
|
||||
"Search": "Søk",
|
||||
"See all FAQ": "Se alle FAQ",
|
||||
"See all photos": "Se alle bilder",
|
||||
"See details": "Se detaljer",
|
||||
"See hotel details": "Se hotellinformasjon",
|
||||
"See less FAQ": "Se mindre FAQ",
|
||||
"See on map": "Se på kart",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"Bus terminal": "Bussterminal",
|
||||
"Business": "Business",
|
||||
"Cancel": "Avbryt",
|
||||
"Change room": "Ändra rum",
|
||||
"Check in": "Checka in",
|
||||
"Check out": "Checka ut",
|
||||
"Check out the credit cards saved to your profile. Pay with a saved card when signed in for a smoother web experience.": "Kolla in kreditkorten som sparats i din profil. Betala med ett sparat kort när du är inloggad för en smidigare webbupplevelse.",
|
||||
@@ -71,6 +72,7 @@
|
||||
"Code / Voucher": "Bokningskoder / kuponger",
|
||||
"Coming up": "Kommer härnäst",
|
||||
"Compare all levels": "Jämför alla nivåer",
|
||||
"Complete booking": "Slutför bokning",
|
||||
"Complete booking & go to payment": "Fullför bokning & gå till betalning",
|
||||
"Complete the booking": "Slutför bokningen",
|
||||
"Contact information": "Kontaktinformation",
|
||||
@@ -283,6 +285,7 @@
|
||||
"Search": "Sök",
|
||||
"See all FAQ": "Se alla FAQ",
|
||||
"See all photos": "Se alla foton",
|
||||
"See details": "Se detaljer",
|
||||
"See hotel details": "Se hotellinformation",
|
||||
"See less FAQ": "See färre FAQ",
|
||||
"See on map": "Se på karta",
|
||||
|
||||
@@ -23,6 +23,11 @@ import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||
|
||||
const SESSION_STORAGE_KEY = "enterDetails"
|
||||
|
||||
type TotalPrice = {
|
||||
local: { price: number; currency: string }
|
||||
euro: { price: number; currency: string }
|
||||
}
|
||||
|
||||
interface EnterDetailsState {
|
||||
userData: {
|
||||
bedType: BedTypeSchema | undefined
|
||||
@@ -32,6 +37,8 @@ interface EnterDetailsState {
|
||||
steps: StepEnum[]
|
||||
selectRateUrl: string
|
||||
currentStep: StepEnum
|
||||
totalPrice: TotalPrice
|
||||
isSummaryOpen: boolean
|
||||
isValid: Record<StepEnum, boolean>
|
||||
completeStep: (updatedData: Partial<EnterDetailsState["userData"]>) => void
|
||||
navigate: (
|
||||
@@ -42,6 +49,8 @@ interface EnterDetailsState {
|
||||
>
|
||||
) => void
|
||||
setCurrentStep: (step: StepEnum) => void
|
||||
toggleSummaryOpen: () => void
|
||||
setTotalPrice: (totalPrice: TotalPrice) => void
|
||||
}
|
||||
|
||||
export function initEditDetailsState(
|
||||
@@ -129,6 +138,11 @@ export function initEditDetailsState(
|
||||
roomData,
|
||||
selectRateUrl,
|
||||
steps: Object.values(StepEnum),
|
||||
totalPrice: {
|
||||
local: { price: 0, currency: "" },
|
||||
euro: { price: 0, currency: "" },
|
||||
},
|
||||
isSummaryOpen: false,
|
||||
setCurrentStep: (step) => set({ currentStep: step }),
|
||||
navigate: (step, updatedData) =>
|
||||
set(
|
||||
@@ -166,6 +180,8 @@ export function initEditDetailsState(
|
||||
get().navigate(nextStep, updatedData)
|
||||
})
|
||||
),
|
||||
toggleSummaryOpen: () => set({ isSummaryOpen: !get().isSummaryOpen }),
|
||||
setTotalPrice: (totalPrice) => set({ totalPrice: totalPrice }),
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user