diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.module.css b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.module.css
new file mode 100644
index 000000000..f680a23a1
--- /dev/null
+++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.module.css
@@ -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;
+ }
+}
diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.tsx
index b39c2622b..adfc99808 100644
--- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.tsx
+++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.tsx
@@ -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 (
-
+ <>
+
+
+ >
)
}
diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/enterDetailsLayout.css b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/enterDetailsLayout.css
index 13c3ded9f..31054ccd4 100644
--- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/enterDetailsLayout.css
+++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/enterDetailsLayout.css
@@ -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;
}
}
diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/layout.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/layout.tsx
index 3a4af62ba..2b5a6241f 100644
--- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/layout.tsx
+++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/layout.tsx
@@ -30,11 +30,7 @@ export default async function StepLayout({
{hotelHeader}
diff --git a/components/HotelReservation/EnterDetails/SectionAccordion/sectionAccordion.module.css b/components/HotelReservation/EnterDetails/SectionAccordion/sectionAccordion.module.css
index 93398378d..7b9ea37dc 100644
--- a/components/HotelReservation/EnterDetails/SectionAccordion/sectionAccordion.module.css
+++ b/components/HotelReservation/EnterDetails/SectionAccordion/sectionAccordion.module.css
@@ -45,7 +45,7 @@
.iconWrapper {
position: relative;
top: var(--Spacing-x1);
- z-index: 2;
+ z-index: 1;
}
.circle {
diff --git a/components/HotelReservation/EnterDetails/SelectedRoom/selectedRoom.module.css b/components/HotelReservation/EnterDetails/SelectedRoom/selectedRoom.module.css
index 120ddc4e5..f88a56606 100644
--- a/components/HotelReservation/EnterDetails/SelectedRoom/selectedRoom.module.css
+++ b/components/HotelReservation/EnterDetails/SelectedRoom/selectedRoom.module.css
@@ -38,7 +38,7 @@
.iconWrapper {
position: relative;
top: var(--Spacing-x1);
- z-index: 2;
+ z-index: 1;
}
.circle {
diff --git a/components/HotelReservation/EnterDetails/Summary/BottomSheet/bottomSheet.module.css b/components/HotelReservation/EnterDetails/Summary/BottomSheet/bottomSheet.module.css
new file mode 100644
index 000000000..c7e82d8af
--- /dev/null
+++ b/components/HotelReservation/EnterDetails/Summary/BottomSheet/bottomSheet.module.css
@@ -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;
+}
diff --git a/components/HotelReservation/EnterDetails/Summary/BottomSheet/index.tsx b/components/HotelReservation/EnterDetails/Summary/BottomSheet/index.tsx
new file mode 100644
index 000000000..fa617b256
--- /dev/null
+++ b/components/HotelReservation/EnterDetails/Summary/BottomSheet/index.tsx
@@ -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 (
+
+
{children}
+
+
+
+
+
+ )
+}
diff --git a/components/HotelReservation/EnterDetails/Summary/index.tsx b/components/HotelReservation/EnterDetails/Summary/index.tsx
index b8d744baa..188ba94e3 100644
--- a/components/HotelReservation/EnterDetails/Summary/index.tsx
+++ b/components/HotelReservation/EnterDetails/Summary/index.tsx
@@ -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 (
@@ -95,6 +127,7 @@ export default function Summary({
{dt(toDate).locale(lang).format("ddd, D MMM")} ({nights})