Merged in feat/SW-1055-Accordion-for-summary-bar-in-mobile-on-Select-Rate (pull request #1283)
Feat/SW-1055 Accordion for summary bar in mobile on Select Rate * feat(SW-1055) created mobile summary for select rate * feat(SW-1055) Added summary for mobile (accordion) Approved-by: Tobias Johansson
This commit is contained in:
@@ -11,6 +11,7 @@ import { RoomsContainer } from "@/components/HotelReservation/SelectRate/Rooms/R
|
||||
import { RoomsContainerSkeleton } from "@/components/HotelReservation/SelectRate/Rooms/RoomsContainerSkeleton"
|
||||
import TrackingSDK from "@/components/TrackingSDK"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
import { convertSearchParamsToObj } from "@/utils/url"
|
||||
|
||||
import { getHotelSearchDetails } from "../utils"
|
||||
import { getValidDates } from "./getValidDates"
|
||||
@@ -82,6 +83,8 @@ export default async function SelectRatePage({
|
||||
|
||||
const hotelId = +hotel.id
|
||||
|
||||
const booking = convertSearchParamsToObj<SelectRateSearchParams>(searchParams)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Suspense fallback={<HotelInfoCardSkeleton />}>
|
||||
@@ -99,6 +102,7 @@ export default async function SelectRatePage({
|
||||
toDate={toDate.toDate()}
|
||||
adultArray={adultsInRoom}
|
||||
childArray={childrenInRoom}
|
||||
booking={booking}
|
||||
/>
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
|
||||
@@ -74,7 +74,7 @@ export default function SummaryUI({
|
||||
rooms.length === 1 &&
|
||||
rooms
|
||||
.slice(0, 1)
|
||||
.some((r) => !isMember || !r.guest.join || !r.guest.membershipNo)
|
||||
.some((r) => !isMember || !r?.guest?.join || !r?.guest?.membershipNo)
|
||||
|
||||
const memberPrice = getMemberPrice(rooms[0].roomRate)
|
||||
|
||||
@@ -127,8 +127,11 @@ export default function SummaryUI({
|
||||
|
||||
const isFirstRoomMember = roomNumber === 1 && isMember
|
||||
const showMemberPrice =
|
||||
!!(isFirstRoomMember || room.guest.join || room.guest.membershipNo) &&
|
||||
memberPrice
|
||||
!!(
|
||||
isFirstRoomMember ||
|
||||
room?.guest?.join ||
|
||||
room?.guest?.membershipNo
|
||||
) && memberPrice
|
||||
|
||||
const adultsMsg = intl.formatMessage(
|
||||
{ id: "{totalAdults, plural, one {# adult} other {# adults}}" },
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
import { useEffect, useRef } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useRateSelectionStore } from "@/stores/select-rate/rate-selection"
|
||||
|
||||
import SummaryUI from "@/components/HotelReservation/EnterDetails/Summary/UI"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
import { formatPrice } from "@/utils/numberFormatting"
|
||||
|
||||
import styles from "./mobileSummary.module.css"
|
||||
|
||||
import type { MobileSummaryProps } from "@/types/components/hotelReservation/selectRate/rateSummary"
|
||||
|
||||
export default function MobileSummary({
|
||||
totalPriceToShow,
|
||||
isAllRoomsSelected,
|
||||
booking,
|
||||
isUserLoggedIn,
|
||||
vat,
|
||||
roomsAvailability,
|
||||
}: MobileSummaryProps) {
|
||||
const intl = useIntl()
|
||||
const scrollY = useRef(0)
|
||||
|
||||
const {
|
||||
guestsInRooms,
|
||||
isSummaryOpen,
|
||||
getSelectedRateSummary,
|
||||
toggleSummaryOpen,
|
||||
togglePriceDetailsModalOpen,
|
||||
} = useRateSelectionStore()
|
||||
|
||||
const selectedRateSummary = getSelectedRateSummary()
|
||||
|
||||
const rooms = selectedRateSummary.map((room, index) => ({
|
||||
adults: guestsInRooms[index].adults,
|
||||
childrenInRoom: guestsInRooms[index].children,
|
||||
roomType: room.roomType,
|
||||
roomPrice: {
|
||||
perNight: {
|
||||
local: {
|
||||
price: room.public.localPrice.pricePerNight,
|
||||
currency: room.public.localPrice.currency,
|
||||
},
|
||||
requested: undefined,
|
||||
},
|
||||
perStay: {
|
||||
local: {
|
||||
price: room.public.localPrice.pricePerStay,
|
||||
currency: room.public.localPrice.currency,
|
||||
},
|
||||
requested: undefined,
|
||||
},
|
||||
currency: room.public.localPrice.currency,
|
||||
},
|
||||
bedType: undefined,
|
||||
breakfast: undefined,
|
||||
guest: undefined,
|
||||
roomRate: {
|
||||
...room.public,
|
||||
memberRate: room.member,
|
||||
publicRate: room.public,
|
||||
},
|
||||
rateDetails: roomsAvailability.rateDefinitions.find(
|
||||
(rate) => rate.rateCode === room.public.rateCode
|
||||
)?.generalTerms,
|
||||
cancellationText:
|
||||
roomsAvailability.rateDefinitions.find(
|
||||
(rate) => rate.rateCode === room.public.rateCode
|
||||
)?.cancellationText ?? "",
|
||||
}))
|
||||
|
||||
useEffect(() => {
|
||||
if (isSummaryOpen) {
|
||||
scrollY.current = window.scrollY
|
||||
document.body.style.position = "fixed"
|
||||
document.body.style.top = `-${scrollY.current}px`
|
||||
document.body.style.width = "100%"
|
||||
} else {
|
||||
document.body.style.position = ""
|
||||
document.body.style.top = ""
|
||||
document.body.style.width = ""
|
||||
window.scrollTo({
|
||||
top: scrollY.current,
|
||||
left: 0,
|
||||
behavior: "instant",
|
||||
})
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.body.style.position = ""
|
||||
document.body.style.top = ""
|
||||
}
|
||||
}, [isSummaryOpen])
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper} data-open={isSummaryOpen}>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.summaryAccordion}>
|
||||
<SummaryUI
|
||||
booking={booking}
|
||||
rooms={rooms}
|
||||
isMember={isUserLoggedIn}
|
||||
packages={undefined}
|
||||
totalPrice={totalPriceToShow}
|
||||
vat={vat}
|
||||
breakfastIncluded={false}
|
||||
toggleSummaryOpen={toggleSummaryOpen}
|
||||
togglePriceDetailsModalOpen={togglePriceDetailsModalOpen}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.bottomSheet}>
|
||||
<button
|
||||
data-open={isSummaryOpen}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
toggleSummaryOpen()
|
||||
}}
|
||||
className={styles.priceDetailsButton}
|
||||
>
|
||||
<Caption>{intl.formatMessage({ id: "Total price" })}</Caption>
|
||||
<Subtitle>
|
||||
{formatPrice(
|
||||
intl,
|
||||
totalPriceToShow.local.price,
|
||||
totalPriceToShow.local.currency
|
||||
)}
|
||||
</Subtitle>
|
||||
<Caption color="baseTextHighContrast" type="underline">
|
||||
{intl.formatMessage({ id: "See details" })}
|
||||
</Caption>
|
||||
</button>
|
||||
<Button
|
||||
intent="primary"
|
||||
theme="base"
|
||||
size="large"
|
||||
type="submit"
|
||||
fullWidth
|
||||
disabled={!isAllRoomsSelected}
|
||||
>
|
||||
{intl.formatMessage({ id: "Continue" })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
.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 1fr;
|
||||
padding: var(--Spacing-x2) 0 var(--Spacing-x5);
|
||||
align-items: flex-start;
|
||||
transition: 0.5s ease-in-out;
|
||||
max-width: var(--max-width-page);
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.priceDetailsButton {
|
||||
display: block;
|
||||
border: none;
|
||||
background: none;
|
||||
text-align: start;
|
||||
transition: padding 0.5s ease-in-out;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wrapper[data-open="true"] {
|
||||
grid-template-rows: 1fr 7.5em;
|
||||
}
|
||||
|
||||
.wrapper[data-open="true"] .bottomSheet {
|
||||
grid-template-columns: 0fr auto;
|
||||
}
|
||||
|
||||
.wrapper[data-open="true"] .priceDetailsButton {
|
||||
animation: fadeOut 0.3s ease-out;
|
||||
opacity: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wrapper[data-open="false"] .priceDetailsButton {
|
||||
animation: fadeIn 0.8s ease-in;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.priceDetailsButton {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-height: 50dvh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.summaryAccordion {
|
||||
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;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.bottomSheet {
|
||||
padding: var(--Spacing-x2) 0 var(--Spacing-x7);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,10 @@ import SignupPromoMobile from "@/components/HotelReservation/SignupPromo/Mobile"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
import { formatPrice } from "@/utils/numberFormatting"
|
||||
|
||||
import MobileSummary from "./MobileSummary"
|
||||
import { calculateTotalPrice } from "./utils"
|
||||
|
||||
import styles from "./rateSummary.module.css"
|
||||
@@ -26,13 +26,16 @@ export default function RateSummary({
|
||||
isUserLoggedIn,
|
||||
packages,
|
||||
roomsAvailability,
|
||||
rooms,
|
||||
booking,
|
||||
vat,
|
||||
}: RateSummaryProps) {
|
||||
const intl = useIntl()
|
||||
const [isVisible, setIsVisible] = useState(false)
|
||||
|
||||
const { getSelectedRateSummary } = useRateSelectionStore()
|
||||
|
||||
const { rooms } = booking
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setIsVisible(true), 0)
|
||||
return () => clearTimeout(timer)
|
||||
@@ -88,7 +91,6 @@ export default function RateSummary({
|
||||
|
||||
return (
|
||||
<div className={styles.summary} data-visible={isVisible}>
|
||||
{showMemberDiscountBanner && <SignupPromoMobile />}
|
||||
<div className={styles.content}>
|
||||
<div className={styles.summaryText}>
|
||||
{selectedRateSummary.map((room, index) => (
|
||||
@@ -161,54 +163,48 @@ export default function RateSummary({
|
||||
>
|
||||
{formatPrice(
|
||||
intl,
|
||||
totalPriceToShow.localPrice.price,
|
||||
totalPriceToShow.localPrice.currency
|
||||
totalPriceToShow.local.price,
|
||||
totalPriceToShow.local.currency
|
||||
)}
|
||||
</Subtitle>
|
||||
{totalPriceToShow?.requestedPrice ? (
|
||||
{totalPriceToShow?.requested ? (
|
||||
<Body color="uiTextMediumContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "Approx. {value}" },
|
||||
{
|
||||
value: formatPrice(
|
||||
intl,
|
||||
totalPriceToShow.requestedPrice.price,
|
||||
totalPriceToShow.requestedPrice.currency
|
||||
totalPriceToShow.requested.price,
|
||||
totalPriceToShow.requested.currency
|
||||
),
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
) : null}
|
||||
</div>
|
||||
<div className={styles.summaryPriceTextMobile}>
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Total price" })}
|
||||
</Caption>
|
||||
<Subtitle color={isUserLoggedIn ? "red" : "uiTextHighContrast"}>
|
||||
{formatPrice(
|
||||
intl,
|
||||
totalPriceToShow.localPrice.price,
|
||||
totalPriceToShow.localPrice.currency
|
||||
)}
|
||||
</Subtitle>
|
||||
<Footnote
|
||||
color="uiTextMediumContrast"
|
||||
className={styles.summaryPriceTextMobile}
|
||||
>
|
||||
{summaryPriceText}
|
||||
</Footnote>
|
||||
</div>
|
||||
<Button
|
||||
type="submit"
|
||||
theme="base"
|
||||
className={styles.continueButton}
|
||||
disabled={!isAllRoomsSelected}
|
||||
>
|
||||
{intl.formatMessage({ id: "Continue" })}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
intent="primary"
|
||||
theme="base"
|
||||
type="submit"
|
||||
className={styles.continueButton}
|
||||
disabled={!isAllRoomsSelected}
|
||||
>
|
||||
{intl.formatMessage({ id: "Continue" })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.mobileSummary}>
|
||||
{showMemberDiscountBanner ? <SignupPromoMobile /> : null}
|
||||
<MobileSummary
|
||||
totalPriceToShow={totalPriceToShow}
|
||||
isAllRoomsSelected={isAllRoomsSelected}
|
||||
booking={booking}
|
||||
isUserLoggedIn={isUserLoggedIn}
|
||||
vat={vat}
|
||||
roomsAvailability={roomsAvailability}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
padding: 0 0 var(--Spacing-x5);
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--Base-Border-Subtle);
|
||||
transition: bottom 300ms ease-in-out;
|
||||
}
|
||||
|
||||
@@ -15,10 +13,10 @@
|
||||
width: 100%;
|
||||
max-width: var(--max-width-page);
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.summary[data-visible="true"] {
|
||||
@@ -70,11 +68,17 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.mobileSummary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 1367px) {
|
||||
.summary {
|
||||
padding: var(--Spacing-x3) 0 var(--Spacing-x5);
|
||||
border-top: 1px solid var(--Base-Border-Subtle);
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.petInfo,
|
||||
@@ -98,4 +102,7 @@
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
}
|
||||
.mobileSummary {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,18 +3,14 @@ import {
|
||||
RoomPackageCodeEnum,
|
||||
} from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import type { Rate } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
|
||||
interface TotalPrice {
|
||||
localPrice: { currency: string; price: number }
|
||||
requestedPrice?: { currency: string; price: number }
|
||||
}
|
||||
import type { Price } from "@/types/stores/enter-details"
|
||||
|
||||
export const calculateTotalPrice = (
|
||||
selectedRateSummary: Rate[],
|
||||
isUserLoggedIn: boolean,
|
||||
petRoomPackage: RoomPackage | undefined
|
||||
) => {
|
||||
return selectedRateSummary.reduce<TotalPrice>(
|
||||
return selectedRateSummary.reduce<Price>(
|
||||
(total, room) => {
|
||||
const priceToUse =
|
||||
isUserLoggedIn && room.member ? room.member : room.public
|
||||
@@ -29,18 +25,18 @@ export const calculateTotalPrice = (
|
||||
: 0
|
||||
|
||||
return {
|
||||
localPrice: {
|
||||
local: {
|
||||
currency: priceToUse.localPrice.currency,
|
||||
price:
|
||||
total.localPrice.price +
|
||||
total.local.price +
|
||||
priceToUse.localPrice.pricePerStay +
|
||||
petRoomPrice,
|
||||
},
|
||||
requestedPrice: priceToUse.requestedPrice
|
||||
requested: priceToUse.requestedPrice
|
||||
? {
|
||||
currency: priceToUse.requestedPrice.currency,
|
||||
price:
|
||||
(total.requestedPrice?.price ?? 0) +
|
||||
(total.requested?.price ?? 0) +
|
||||
priceToUse.requestedPrice.pricePerStay +
|
||||
petRoomPrice,
|
||||
}
|
||||
@@ -48,11 +44,11 @@ export const calculateTotalPrice = (
|
||||
}
|
||||
},
|
||||
{
|
||||
localPrice: {
|
||||
local: {
|
||||
currency: selectedRateSummary[0].public.localPrice.currency,
|
||||
price: 0,
|
||||
},
|
||||
requestedPrice: undefined,
|
||||
requested: undefined,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -102,6 +102,12 @@ export async function RoomsContainer({
|
||||
)
|
||||
}
|
||||
|
||||
if (!hotelData) {
|
||||
// TODO: Log hotel data error
|
||||
console.error("[RoomsContainer] unable to fetch hotel data")
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Rooms
|
||||
availablePackages={packages ?? []}
|
||||
@@ -109,6 +115,7 @@ export async function RoomsContainer({
|
||||
isUserLoggedIn={isUserLoggedIn}
|
||||
roomsAvailability={roomsAvailability}
|
||||
roomCategories={hotelData?.roomCategories ?? []}
|
||||
vat={hotelData.hotel.vat}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ export default function Rooms({
|
||||
isUserLoggedIn,
|
||||
roomsAvailability,
|
||||
roomCategories = [],
|
||||
vat,
|
||||
}: SelectRateProps) {
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
@@ -41,8 +42,13 @@ export default function Rooms({
|
||||
const arrivalDate = searchParams.get("fromDate")
|
||||
const departureDate = searchParams.get("toDate")
|
||||
|
||||
const { selectedRates, rateSummary, calculateRateSummary, initializeRates } =
|
||||
useRateSelectionStore()
|
||||
const {
|
||||
selectedRates,
|
||||
rateSummary,
|
||||
calculateRateSummary,
|
||||
initializeRates,
|
||||
setGuestsInRooms,
|
||||
} = useRateSelectionStore()
|
||||
|
||||
const {
|
||||
selectedPackagesByRoom,
|
||||
@@ -60,6 +66,12 @@ export default function Rooms({
|
||||
[searchParams]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
bookingWidgetSearchData.rooms.forEach((room, index) => {
|
||||
setGuestsInRooms(index, room.adults, room.childrenInRoom)
|
||||
})
|
||||
}, [bookingWidgetSearchData.rooms, setGuestsInRooms])
|
||||
|
||||
const isMultipleRooms = bookingWidgetSearchData.rooms.length > 1
|
||||
|
||||
useEffect(() => {
|
||||
@@ -265,7 +277,8 @@ export default function Rooms({
|
||||
isUserLoggedIn={isUserLoggedIn}
|
||||
packages={availablePackages}
|
||||
roomsAvailability={roomsAvailability}
|
||||
rooms={bookingWidgetSearchData.rooms}
|
||||
booking={bookingWidgetSearchData}
|
||||
vat={vat}
|
||||
/>
|
||||
</form>
|
||||
)}
|
||||
|
||||
@@ -249,8 +249,8 @@
|
||||
"In extra bed": "i ekstra seng",
|
||||
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
|
||||
"Included": "Inkluderet",
|
||||
"Invalid booking code": "Ugyldig reservationskode",
|
||||
"Indoor pool": "Indendørs pool",
|
||||
"Invalid booking code": "Ugyldig reservationskode",
|
||||
"Is there anything else you would like us to know before your arrival?": "Er der andet, du gerne vil have os til at vide, før din ankomst?",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det er ikke muligt at administrere dine kommunikationspræferencer lige nu, prøv venligst igen senere eller kontakt support, hvis problemet fortsætter.",
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Det ser ud til, at ingen hoteller matcher dine filtre. Prøv at justere din søgning for at finde det perfekte ophold.",
|
||||
@@ -428,20 +428,20 @@
|
||||
"Read more": "Læs mere",
|
||||
"Read more & book a table": "Læs mere og bestil bord",
|
||||
"Read more about the hotel": "Læs mere om hotellet",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Read more about wellness & exercise": "Læs mere om wellness & motion",
|
||||
"Rebooking": "Rebooking",
|
||||
"Redeem benefit": "Redeem benefit",
|
||||
"Redeemed & valid through:": "Redeemed & valid through:",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Reference #{bookingNr}": "Reference #{bookingNr}",
|
||||
"Relax": "Slap af",
|
||||
"Remember code": "Husk kode",
|
||||
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
|
||||
"Request bedtype": "Anmod om sengetype",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Reservation number {value}": "Reservation number {value}",
|
||||
"Reservation policy": "Reservation policy",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Restaurant & Bar": "Restaurant & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Gentag den nye adgangskode",
|
||||
@@ -476,6 +476,7 @@
|
||||
"See rooms": "Se værelser",
|
||||
"See you soon!": "See you soon!",
|
||||
"Select a country": "Vælg et land",
|
||||
"Select a rate": "Vælg et tilbud",
|
||||
"Select bed": "Vælg seng",
|
||||
"Select breakfast options": "Vælg morgenmadsmuligheder",
|
||||
"Select country of residence": "Vælg bopælsland",
|
||||
@@ -554,9 +555,9 @@
|
||||
"VAT amount": "VAT amount",
|
||||
"VAT {vat}%": "Moms {vat}%",
|
||||
"Valid through {expirationDate}": "Gyldig til og med {expirationDate}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"Verification code": "Verification code",
|
||||
"View all hotels in {country}": "Se alle hoteller i {country}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"View as list": "Vis som liste",
|
||||
"View as map": "Vis som kort",
|
||||
"View room details": "View room details",
|
||||
|
||||
@@ -250,8 +250,8 @@
|
||||
"In extra bed": "im zusätzlichen Bett",
|
||||
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
|
||||
"Included": "Iinklusive",
|
||||
"Invalid booking code": "Ungültiger Buchungscode",
|
||||
"Indoor pool": "Innenpool",
|
||||
"Invalid booking code": "Ungültiger Buchungscode",
|
||||
"Is there anything else you would like us to know before your arrival?": "Gibt es noch etwas, das Sie uns vor Ihrer Ankunft mitteilen möchten?",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Es ist derzeit nicht möglich, Ihre Kommunikationseinstellungen zu verwalten. Bitte versuchen Sie es später erneut oder wenden Sie sich an den Support, wenn das Problem weiterhin besteht.",
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Es scheint, dass keine Hotels Ihren Filtern entsprechen. Versuchen Sie, Ihre Suche anzupassen, um den perfekten Aufenthalt zu finden.",
|
||||
@@ -429,20 +429,20 @@
|
||||
"Read more": "Mehr lesen",
|
||||
"Read more & book a table": "Lesen Sie mehr und reservieren Sie einen Tisch",
|
||||
"Read more about the hotel": "Lesen Sie mehr über das Hotel",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Read more about wellness & exercise": "Lesen Sie mehr über Wellness & Bewegung",
|
||||
"Rebooking": "Rebooking",
|
||||
"Redeem benefit": "Redeem benefit",
|
||||
"Redeemed & valid through:": "Redeemed & valid through:",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Reference #{bookingNr}": "Referenz #{bookingNr}",
|
||||
"Relax": "Entspannen",
|
||||
"Remember code": "Code merken",
|
||||
"Remove card from member profile": "Karte aus dem Mitgliedsprofil entfernen",
|
||||
"Request bedtype": "Bettentyp anfragen",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Reservation number {value}": "Reservation number {value}",
|
||||
"Reservation policy": "Reservation policy",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Restaurant & Bar": "Restaurant & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Neues Passwort erneut eingeben",
|
||||
@@ -477,6 +477,7 @@
|
||||
"See rooms": "Zimmer ansehen",
|
||||
"See you soon!": "See you soon!",
|
||||
"Select a country": "Wähle ein Land",
|
||||
"Select a rate": "Wähle ein Angebot",
|
||||
"Select bed": "Betttyp auswählen",
|
||||
"Select breakfast options": "Wählen Sie Frühstücksoptionen",
|
||||
"Select country of residence": "Wählen Sie das Land Ihres Wohnsitzes aus",
|
||||
@@ -554,9 +555,9 @@
|
||||
"VAT amount": "VAT amount",
|
||||
"VAT {vat}%": "MwSt. {vat}%",
|
||||
"Valid through {expirationDate}": "Gültig bis {expirationDate}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"Verification code": "Verification code",
|
||||
"View all hotels in {country}": "Alle Hotels in {country} anzeigen",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"View as list": "Als Liste anzeigen",
|
||||
"View as map": "Als Karte anzeigen",
|
||||
"View room details": "View room details",
|
||||
|
||||
@@ -252,8 +252,8 @@
|
||||
"In extra bed": "In extra bed",
|
||||
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
|
||||
"Included": "Included",
|
||||
"Invalid booking code": "Invalid booking code",
|
||||
"Indoor pool": "Indoor pool",
|
||||
"Invalid booking code": "Invalid booking code",
|
||||
"Is there anything else you would like us to know before your arrival?": "Is there anything else you would like us to know before your arrival?",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.",
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
@@ -481,6 +481,7 @@
|
||||
"See rooms": "See rooms",
|
||||
"See you soon!": "See you soon!",
|
||||
"Select a country": "Select a country",
|
||||
"Select a rate": "Select a rate",
|
||||
"Select bed": "Select bed",
|
||||
"Select breakfast options": "Select breakfast options",
|
||||
"Select country of residence": "Select country of residence",
|
||||
|
||||
@@ -249,8 +249,8 @@
|
||||
"In extra bed": "Oma vuodepaikka",
|
||||
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
|
||||
"Included": "Sisälly hintaan",
|
||||
"Invalid booking code": "Virheellinen varauskoodi",
|
||||
"Indoor pool": "Sisäuima-allas",
|
||||
"Invalid booking code": "Virheellinen varauskoodi",
|
||||
"Is there anything else you would like us to know before your arrival?": "Onko jotain muuta, mitä haluaisit meidän tietävän ennen saapumistasi?",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Viestintäasetuksiasi ei voi hallita juuri nyt. Yritä myöhemmin uudelleen tai ota yhteyttä tukeen, jos ongelma jatkuu.",
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Näyttää siltä, että mikään hotelli ei vastaa suodattimiasi. Yritä muokata hakuasi löytääksesi täydellisen oleskelun.",
|
||||
@@ -428,20 +428,20 @@
|
||||
"Read more": "Lue lisää",
|
||||
"Read more & book a table": "Lue lisää ja varaa pöytä",
|
||||
"Read more about the hotel": "Lue lisää hotellista",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Read more about wellness & exercise": "Lue lisää hyvinvoinnista ja liikunnasta",
|
||||
"Rebooking": "Rebooking",
|
||||
"Redeem benefit": "Redeem benefit",
|
||||
"Redeemed & valid through:": "Redeemed & valid through:",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Reference #{bookingNr}": "Referenssi #{bookingNr}",
|
||||
"Relax": "Rentoutua",
|
||||
"Remember code": "Muista koodi",
|
||||
"Remove card from member profile": "Poista kortti jäsenprofiilista",
|
||||
"Request bedtype": "Pyydä sänkytyyppiä",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Reservation number {value}": "Reservation number {value}",
|
||||
"Reservation policy": "Reservation policy",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Restaurant & Bar": "Ravintola & Baari",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Kirjoita uusi salasana uudelleen",
|
||||
@@ -477,6 +477,7 @@
|
||||
"See rooms": "Katso huoneet",
|
||||
"See you soon!": "See you soon!",
|
||||
"Select a country": "Valitse maa",
|
||||
"Select a rate": "Valitse hinta",
|
||||
"Select bed": "Valitse vuodetyyppi",
|
||||
"Select breakfast options": "Valitse aamiaisvaihtoehdot",
|
||||
"Select country of residence": "Valitse asuinmaa",
|
||||
@@ -529,8 +530,8 @@
|
||||
"Things nearby {hotelName}": "Lähellä olevia asioita {hotelName}",
|
||||
"This room is equipped with": "Tämä huone on varustettu",
|
||||
"This room is not available": "Tämä huone ei ole käytettävissä",
|
||||
"Thursday": "Thursday",
|
||||
"This verifcation is needed for additional security.": "This verifcation is needed for additional security.",
|
||||
"Thursday": "Thursday",
|
||||
"Times": "Ajat",
|
||||
"To get the member price <span>{price}</span>, log in or join when completing the booking.": "Jäsenhintaan saavat sisäänkirjautuneet tai liittyneet jäsenet.",
|
||||
"To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "Varmistaaksesi varauksen, pyydämme sinua antamaan meille maksukortin tiedot. Varmista, että ei veloiteta maksusi tällä hetkellä.",
|
||||
@@ -554,9 +555,9 @@
|
||||
"VAT amount": "VAT amount",
|
||||
"VAT {vat}%": "ALV {vat}%",
|
||||
"Valid through {expirationDate}": "Voimassa {expirationDate} asti",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"Verification code": "Verification code",
|
||||
"View all hotels in {country}": "Näytä kaikki hotellit maassa {country}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"View as list": "Näytä listana",
|
||||
"View as map": "Näytä kartalla",
|
||||
"View room details": "View room details",
|
||||
@@ -603,9 +604,9 @@
|
||||
"You have no previous stays.": "Sinulla ei ole aiempia majoituksia.",
|
||||
"You have no upcoming stays.": "Sinulla ei ole tulevia majoituksia.",
|
||||
"You have now cancelled your payment.": "Sinut nyt peruutit maksun.",
|
||||
"You must accept the terms and conditions": "You must accept the terms and conditions",
|
||||
"You'll find all your gifts in 'My benefits'": "You'll find all your gifts in 'My benefits'",
|
||||
"Your Challenges Conquer & Earn!": "Your Challenges Conquer & Earn!",
|
||||
"You must accept the terms and conditions": "You must accept the terms and conditions",
|
||||
"Your accounts are connected": "Your accounts are connected",
|
||||
"Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.": "Varauksesi on vahvistettu, mutta jäsenyytesi ei voitu vahvistaa. Jos olet bookeutunut jäsenyysalennoilla, sinun on joko esitettävä olemassa olevan jäsenyysnumero tarkistukseen, tulla jäseneksi tai maksamaan hinnan eron hotellissa. Jäsenyyden tilittäminen on suositeltavampaa tehdä verkkoon ennen majoittumista.",
|
||||
"Your card was successfully removed!": "Korttisi poistettiin onnistuneesti!",
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
"Address: {address}": "Adresse: {address}",
|
||||
"Adults": "Voksne",
|
||||
"Age": "Alder",
|
||||
"{memberPrice} {currency}": "{memberPrice} {currency}",
|
||||
"Airport": "Flyplass",
|
||||
"All our breakfast buffets offer gluten free, vegan, and allergy-friendly options.": "Alle våre frokostbufféer tilbyr glutenfrie, veganske og allergivennlige alternativer.",
|
||||
"Allergy-friendly room": "Allergirom",
|
||||
@@ -249,8 +248,8 @@
|
||||
"In extra bed": "i ekstraseng",
|
||||
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
|
||||
"Included": "Inkludert",
|
||||
"Invalid booking code": "Ugyldig bookingkode",
|
||||
"Indoor pool": "Innendørs basseng",
|
||||
"Invalid booking code": "Ugyldig bookingkode",
|
||||
"Is there anything else you would like us to know before your arrival?": "Er det noe annet du vil at vi skal vite før ankomsten din?",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det er ikke mulig å administrere kommunikasjonspreferansene dine akkurat nå, prøv igjen senere eller kontakt support hvis problemet vedvarer.",
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Det ser ut til at ingen hoteller samsvarer med filtrene dine. Prøv å justere søket for å finne det perfekte oppholdet.",
|
||||
@@ -428,20 +427,20 @@
|
||||
"Read more": "Les mer",
|
||||
"Read more & book a table": "Les mer og bestill bord",
|
||||
"Read more about the hotel": "Les mer om hotellet",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Read more about wellness & exercise": "Les mer om velvære og trening",
|
||||
"Rebooking": "Rebooking",
|
||||
"Redeem benefit": "Redeem benefit",
|
||||
"Redeemed & valid through:": "Redeemed & valid through:",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Reference #{bookingNr}": "Referanse #{bookingNr}",
|
||||
"Relax": "Slappe av",
|
||||
"Remember code": "Husk kode",
|
||||
"Remove card from member profile": "Fjern kortet fra medlemsprofilen",
|
||||
"Request bedtype": "Be om sengetype",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Reservation number {value}": "Reservation number {value}",
|
||||
"Reservation policy": "Reservation policy",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Restaurant & Bar": "Restaurant & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Skriv inn nytt passord på nytt",
|
||||
@@ -476,6 +475,7 @@
|
||||
"See rooms": "Se rom",
|
||||
"See you soon!": "See you soon!",
|
||||
"Select a country": "Velg et land",
|
||||
"Select a rate": "Velg et tilbud",
|
||||
"Select bed": "Vælg seng",
|
||||
"Select breakfast options": "Velg frokostalternativer",
|
||||
"Select country of residence": "Velg bostedsland",
|
||||
@@ -553,9 +553,9 @@
|
||||
"VAT amount": "VAT amount",
|
||||
"VAT {vat}%": "mva {vat}%",
|
||||
"Valid through {expirationDate}": "Gyldig til og med {expirationDate}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"Verification code": "Verification code",
|
||||
"View all hotels in {country}": "Se alle hotellene i {country}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"View as list": "Vis som liste",
|
||||
"View as map": "Vis som kart",
|
||||
"View room details": "View room details",
|
||||
@@ -658,6 +658,7 @@
|
||||
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||
"{distanceInKm} km": "{distanceInKm} km",
|
||||
"{lowest} to {highest} persons": "{lowest} til {highest} personer",
|
||||
"{memberPrice} {currency}": "{memberPrice} {currency}",
|
||||
"{min} to {max} characters": "{min} til {max} tegn",
|
||||
"{numberOfRooms, plural, one {# room type} other {# room types}} available": "{numberOfRooms, plural, one {# room type} other {# room types}} tilgjengelig",
|
||||
"{number} km to city center": "{number} km til sentrum",
|
||||
|
||||
@@ -248,8 +248,8 @@
|
||||
"In extra bed": "Egen sängplats",
|
||||
"In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.": "In order to verify your account linking we will ask you to sign in to your SAS EuroBonus account.",
|
||||
"Included": "Inkluderad",
|
||||
"Invalid booking code": "Ogiltig bokningskod",
|
||||
"Indoor pool": "Inomhuspool",
|
||||
"Invalid booking code": "Ogiltig bokningskod",
|
||||
"Is there anything else you would like us to know before your arrival?": "Är det något mer du vill att vi ska veta innan din ankomst?",
|
||||
"It is not posible to manage your communication preferences right now, please try again later or contact support if the problem persists.": "Det gick inte att hantera dina kommunikationsinställningar just nu, försök igen senare eller kontakta supporten om problemet kvarstår.",
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.": "Det verkar som att inga hotell matchar dina filter. Prova att justera din sökning för att hitta den perfekta vistelsen.",
|
||||
@@ -427,20 +427,20 @@
|
||||
"Read more": "Läs mer",
|
||||
"Read more & book a table": "Läs mer och boka bord",
|
||||
"Read more about the hotel": "Läs mer om hotellet",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Read more about wellness & exercise": "Läs mer om friskvård & träning",
|
||||
"Rebooking": "Rebooking",
|
||||
"Redeem benefit": "Redeem benefit",
|
||||
"Redeemed & valid through:": "Redeemed & valid through:",
|
||||
"Redirecting you to SAS": "Redirecting you to SAS",
|
||||
"Redirecting you to my pages.": "Redirecting you to my pages.",
|
||||
"Reference #{bookingNr}": "Referens #{bookingNr}",
|
||||
"Relax": "Koppla av",
|
||||
"Remember code": "Kom ihåg kod",
|
||||
"Remove card from member profile": "Ta bort kortet från medlemsprofilen",
|
||||
"Request bedtype": "Request bedtype",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Reservation number {value}": "Reservation number {value}",
|
||||
"Reservation policy": "Reservation policy",
|
||||
"Reservation No. {reservationNumber}": "Reservation No. {reservationNumber}",
|
||||
"Restaurant & Bar": "Restaurang & Bar",
|
||||
"Restaurants & Bars": "Restaurants & Bars",
|
||||
"Retype new password": "Upprepa nytt lösenord",
|
||||
@@ -475,6 +475,7 @@
|
||||
"See rooms": "Se rum",
|
||||
"See you soon!": "See you soon!",
|
||||
"Select a country": "Välj ett land",
|
||||
"Select a rate": "Välj ett pris",
|
||||
"Select bed": "Välj säng",
|
||||
"Select breakfast options": "Välj frukostalternativ",
|
||||
"Select country of residence": "Välj bosättningsland",
|
||||
@@ -552,9 +553,9 @@
|
||||
"VAT amount": "VAT amount",
|
||||
"VAT {vat}%": "Moms {vat}%",
|
||||
"Valid through {expirationDate}": "Gäller till och med {expirationDate}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"Verification code": "Verification code",
|
||||
"View all hotels in {country}": "Visa alla hotell i {country}",
|
||||
"View and buy add-ons": "View and buy add-ons",
|
||||
"View as list": "Visa som lista",
|
||||
"View as map": "Visa som karta",
|
||||
"View room details": "View room details",
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
RoomPackages,
|
||||
} from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import type {
|
||||
Child,
|
||||
Rate,
|
||||
RateCode,
|
||||
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
@@ -22,6 +23,9 @@ export interface RateSummaryParams {
|
||||
interface RateSelectionState {
|
||||
selectedRates: (RateCode | undefined)[]
|
||||
rateSummary: (Rate | null)[]
|
||||
isPriceDetailsModalOpen: boolean
|
||||
isSummaryOpen: boolean
|
||||
guestsInRooms: { adults: number; children?: Child[] }[]
|
||||
modifyRate: (index: number) => void
|
||||
selectRate: (index: number, rate: RateCode | undefined) => void
|
||||
initializeRates: (count: number) => void
|
||||
@@ -31,11 +35,17 @@ interface RateSelectionState {
|
||||
roomCategories,
|
||||
}: RateSummaryParams) => void
|
||||
getSelectedRateSummary: () => Rate[]
|
||||
togglePriceDetailsModalOpen: () => void
|
||||
toggleSummaryOpen: () => void
|
||||
setGuestsInRooms: (index: number, adults: number, children?: Child[]) => void
|
||||
}
|
||||
|
||||
export const useRateSelectionStore = create<RateSelectionState>((set, get) => ({
|
||||
selectedRates: [],
|
||||
rateSummary: [],
|
||||
isPriceDetailsModalOpen: false,
|
||||
isSummaryOpen: false,
|
||||
guestsInRooms: [{ adults: 1 }],
|
||||
modifyRate: (index) =>
|
||||
set((state) => {
|
||||
const newRates = [...state.selectedRates]
|
||||
@@ -69,4 +79,24 @@ export const useRateSelectionStore = create<RateSelectionState>((set, get) => ({
|
||||
const { rateSummary } = get()
|
||||
return rateSummary.filter((summary): summary is Rate => summary !== null)
|
||||
},
|
||||
togglePriceDetailsModalOpen: () => {
|
||||
set((state) => ({
|
||||
isPriceDetailsModalOpen: !state.isPriceDetailsModalOpen,
|
||||
}))
|
||||
},
|
||||
|
||||
toggleSummaryOpen: () => {
|
||||
set((state) => ({
|
||||
isSummaryOpen: !state.isSummaryOpen,
|
||||
}))
|
||||
},
|
||||
setGuestsInRooms: (index, adults, children) => {
|
||||
set((state) => ({
|
||||
guestsInRooms: [
|
||||
...state.guestsInRooms.slice(0, index),
|
||||
{ adults, children },
|
||||
...state.guestsInRooms.slice(index + 1),
|
||||
],
|
||||
}))
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
import type { Price } from "@/types/stores/enter-details"
|
||||
import type { RoomsAvailability } from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
import type { RoomPackages } from "./roomFilter"
|
||||
import type { Room } from "./selectRate"
|
||||
import type { SelectRateSearchParams } from "./selectRate"
|
||||
|
||||
export interface RateSummaryProps {
|
||||
isUserLoggedIn: boolean
|
||||
packages: RoomPackages | undefined
|
||||
roomsAvailability: RoomsAvailability
|
||||
rooms: Room[]
|
||||
booking: SelectRateSearchParams
|
||||
vat: number
|
||||
}
|
||||
|
||||
export interface MobileSummaryProps {
|
||||
totalPriceToShow: Price
|
||||
isAllRoomsSelected: boolean
|
||||
booking: SelectRateSearchParams
|
||||
isUserLoggedIn: boolean
|
||||
vat: number
|
||||
roomsAvailability: RoomsAvailability
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ export interface SelectRateProps {
|
||||
isUserLoggedIn: boolean
|
||||
roomsAvailability: RoomsAvailability
|
||||
roomCategories: Room[]
|
||||
vat: number
|
||||
}
|
||||
|
||||
export interface RoomSelectionPanelProps {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { Lang } from "@/constants/languages"
|
||||
import type { Child } from "./selectRate"
|
||||
import type { Child, SelectRateSearchParams } from "./selectRate"
|
||||
|
||||
export interface RoomsContainerProps {
|
||||
adultArray: number[]
|
||||
booking: SelectRateSearchParams
|
||||
childArray?: Child[]
|
||||
fromDate: Date
|
||||
hotelId: number
|
||||
|
||||
@@ -33,7 +33,7 @@ export interface SummaryUIProps {
|
||||
childrenInRoom: Child[] | undefined
|
||||
bedType: BedTypeSchema | undefined
|
||||
breakfast: BreakfastPackage | false | undefined
|
||||
guest: DetailsSchema
|
||||
guest: DetailsSchema | undefined
|
||||
roomRate: DetailsProviderProps["roomRate"]
|
||||
roomPrice: RoomPrice
|
||||
roomType: string
|
||||
|
||||
Reference in New Issue
Block a user