diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx index f1fb59405..91db8e53b 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx @@ -22,7 +22,6 @@ import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoo import DesktopSummary from "@/components/HotelReservation/EnterDetails/Summary/Desktop" import MobileSummary from "@/components/HotelReservation/EnterDetails/Summary/Mobile" import { generateChildrenString } from "@/components/HotelReservation/utils" -import TrackingSDK from "@/components/TrackingSDK" import { getIntl } from "@/i18n" import { setLang } from "@/i18n/serverContext" import EnterDetailsProvider from "@/providers/EnterDetailsProvider" @@ -34,11 +33,7 @@ import styles from "./page.module.css" import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" import { type SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate" -import { - TrackingChannelEnum, - type TrackingSDKHotelInfo, - type TrackingSDKPageData, -} from "@/types/components/tracking" +import { type TrackingSDKHotelInfo } from "@/types/components/tracking" import { StepEnum } from "@/types/enums/step" import type { LangParams, PageArgs } from "@/types/params" @@ -106,13 +101,13 @@ export default async function StepPage({ const packages = packageCodes ? await getPackages({ - adults, - children: childrenInRoom?.length, - endDate: toDate, - hotelId, - packageCodes, - startDate: fromDate, - }) + adults, + children: childrenInRoom?.length, + endDate: toDate, + hotelId, + packageCodes, + startDate: fromDate, + }) : null const roomAvailability = await getSelectedRoomAvailability( @@ -153,13 +148,13 @@ export default async function StepPage({ const memberPrice = roomAvailability.memberRate ? { - price: roomAvailability.memberRate.localPrice.pricePerStay, - currency: roomAvailability.memberRate.localPrice.currency, - } + price: roomAvailability.memberRate.localPrice.pricePerStay, + currency: roomAvailability.memberRate.localPrice.currency, + } : undefined - const arrivalDate = new Date(searchParams.fromDate) - const departureDate = new Date(searchParams.toDate) + const arrivalDate = new Date(searchParams.fromdate) + const departureDate = new Date(searchParams.todate) const hotelAttributes = hotelData?.hotel const initialHotelsTrackingData: TrackingSDKHotelInfo = { diff --git a/components/HotelReservation/EnterDetails/Summary/PriceDetailsTable/index.tsx b/components/HotelReservation/EnterDetails/Summary/PriceDetailsTable/index.tsx deleted file mode 100644 index 196309748..000000000 --- a/components/HotelReservation/EnterDetails/Summary/PriceDetailsTable/index.tsx +++ /dev/null @@ -1,195 +0,0 @@ -"use client" - -import { useIntl } from "react-intl" - -import { dt } from "@/lib/dt" -import { useEnterDetailsStore } from "@/stores/enter-details" - -import Body from "@/components/TempDesignSystem/Text/Body" -import Caption from "@/components/TempDesignSystem/Text/Caption" -import useLang from "@/hooks/useLang" -import { formatPrice } from "@/utils/numberFormatting" - -import styles from "./priceDetailsTable.module.css" - -import { type PriceDetailsTableProps } from "@/types/components/hotelReservation/enterDetails/priceDetailsTable" -import type { DetailsState } from "@/types/stores/enter-details" - -function Row({ - label, - value, - bold, -}: { - label: string - value: string - bold?: boolean -}) { - return ( - - - {label} - - - {value} - - - ) -} - -function TableSection({ children }: React.PropsWithChildren) { - return {children} -} - -function TableSectionHeader({ - title, - subtitle, -}: { - title: string - subtitle?: string -}) { - return ( - - - {title} - {subtitle ? {subtitle} : null} - - - ) -} - -export function storeSelector(state: DetailsState) { - return { - bedType: state.bedType, - booking: state.booking, - breakfast: state.breakfast, - packages: state.packages, - roomRate: state.roomRate, - roomPrice: state.roomPrice, - totalPrice: state.totalPrice, - vat: state.vat, - } -} - -export default function PriceDetailsTable({ - roomType, -}: PriceDetailsTableProps) { - const intl = useIntl() - const lang = useLang() - - const { bedType, booking, breakfast, roomPrice, totalPrice, vat } = - useEnterDetailsStore(storeSelector) - - // TODO: Update for Multiroom later - const { adults, childrenInRoom } = booking.rooms[0] - - const diff = dt(booking.toDate).diff(booking.fromDate, "days") - const nights = intl.formatMessage( - { id: "{totalNights, plural, one {# night} other {# nights}}" }, - { totalNights: diff } - ) - const vatPercentage = vat / 100 - const vatAmount = totalPrice.local.price * vatPercentage - - const priceExclVat = totalPrice.local.price - vatAmount - - const duration = ` ${dt(booking.fromDate).locale(lang).format("ddd, D MMM")} - - - ${dt(booking.toDate).locale(lang).format("ddd, D MMM")} (${nights})` - return ( - - - - - {bedType ? ( - - ) : null} - - - - {breakfast ? ( - - - {childrenInRoom?.length ? ( - - ) : null} - - - ) : null} - - - - - - - - - -
- - {intl.formatMessage({ id: "Price including VAT" })} - - - - {formatPrice( - intl, - totalPrice.local.price, - totalPrice.local.currency - )} - -
- ) -} diff --git a/components/HotelReservation/EnterDetails/Summary/UI/index.tsx b/components/HotelReservation/EnterDetails/Summary/UI/index.tsx index c67c59513..9958bb48b 100644 --- a/components/HotelReservation/EnterDetails/Summary/UI/index.tsx +++ b/components/HotelReservation/EnterDetails/Summary/UI/index.tsx @@ -5,12 +5,12 @@ import { useIntl } from "react-intl" import { dt } from "@/lib/dt" +import PriceDetailsModal from "@/components/HotelReservation/PriceDetailsModal" import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop" import { ArrowRightIcon, CheckIcon, ChevronDownSmallIcon, - ChevronRightSmallIcon, } from "@/components/Icons" import Modal from "@/components/Modal" import Button from "@/components/TempDesignSystem/Button" @@ -21,8 +21,6 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import useLang from "@/hooks/useLang" import { formatPrice } from "@/utils/numberFormatting" -import PriceDetailsTable from "../PriceDetailsTable" - import styles from "./ui.module.css" import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" @@ -36,6 +34,7 @@ export default function SummaryUI({ totalPrice, isMember, breakfastIncluded, + vat, toggleSummaryOpen, togglePriceDetailsModalOpen, }: SummaryUIProps) { @@ -358,24 +357,21 @@ export default function SummaryUI({ { b: (str) => {str} } )} - - - {intl.formatMessage({ id: "Price details" })} - - - - } - > - {/* // TODO: all rooms needs to be passed to PriceDetails */} - - + ({ + adults: r.adults, + childrenInRoom: r.childrenInRoom, + roomPrice: r.roomPrice, + roomType: r.roomType, + bedType: r.bedType, + breakfast: r.breakfast, + }))} + totalPrice={totalPrice} + vat={vat} + toggleModal={handleTogglePriceDetailsModal} + />
diff --git a/components/HotelReservation/PriceDetailsModal/PriceDetailsTable/index.tsx b/components/HotelReservation/PriceDetailsModal/PriceDetailsTable/index.tsx new file mode 100644 index 000000000..5a99030bb --- /dev/null +++ b/components/HotelReservation/PriceDetailsModal/PriceDetailsTable/index.tsx @@ -0,0 +1,217 @@ +"use client" + +import React from "react" +import { useIntl } from "react-intl" + +import { dt } from "@/lib/dt" + +import Body from "@/components/TempDesignSystem/Text/Body" +import Caption from "@/components/TempDesignSystem/Text/Caption" +import useLang from "@/hooks/useLang" +import { formatPrice } from "@/utils/numberFormatting" + +import styles from "./priceDetailsTable.module.css" + +import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType" +import type { BreakfastPackage } from "@/types/components/hotelReservation/enterDetails/breakfast" +import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate" +import type { Price, RoomPrice } from "@/types/stores/enter-details" + +function Row({ + label, + value, + bold, +}: { + label: string + value: string + bold?: boolean +}) { + return ( + + + {label} + + + {value} + + + ) +} + +function TableSection({ children }: React.PropsWithChildren) { + return {children} +} + +function TableSectionHeader({ + title, + subtitle, +}: { + title: string + subtitle?: string +}) { + return ( + + + {title} + {subtitle ? {subtitle} : null} + + + ) +} + +interface PriceDetailsTableProps { + fromDate: string + toDate: string + rooms: { + adults: number + childrenInRoom: Child[] | undefined + roomType: string + roomPrice: RoomPrice + bedType: BedTypeSchema | undefined + breakfast: BreakfastPackage | false | undefined + }[] + totalPrice: Price + vat: number +} + +export default function PriceDetailsTable({ + fromDate, + toDate, + rooms, + totalPrice, + vat, +}: PriceDetailsTableProps) { + const intl = useIntl() + const lang = useLang() + + const diff = dt(toDate).diff(fromDate, "days") + const nights = intl.formatMessage( + { id: "{totalNights, plural, one {# night} other {# nights}}" }, + { totalNights: diff } + ) + const vatPercentage = vat / 100 + const vatAmount = totalPrice.local.price * vatPercentage + + const priceExclVat = totalPrice.local.price - vatAmount + + const duration = ` ${dt(fromDate).locale(lang).format("ddd, D MMM")} + - + ${dt(toDate).locale(lang).format("ddd, D MMM")} (${nights})` + return ( + + {rooms.map((room, idx) => ( + + + {rooms.length > 1 && ( + + {intl.formatMessage({ id: "Room" })} {idx + 1} + + )} + + + {room.bedType ? ( + + ) : null} + + + + {room.breakfast ? ( + + + {room.childrenInRoom?.length ? ( + + ) : null} + + + ) : null} + + ))} + + + + + + + + + +
+ + {intl.formatMessage({ id: "Price including VAT" })} + + + + {formatPrice( + intl, + totalPrice.local.price, + totalPrice.local.currency + )} + +
+ ) +} diff --git a/components/HotelReservation/EnterDetails/Summary/PriceDetailsTable/priceDetailsTable.module.css b/components/HotelReservation/PriceDetailsModal/PriceDetailsTable/priceDetailsTable.module.css similarity index 100% rename from components/HotelReservation/EnterDetails/Summary/PriceDetailsTable/priceDetailsTable.module.css rename to components/HotelReservation/PriceDetailsModal/PriceDetailsTable/priceDetailsTable.module.css diff --git a/components/HotelReservation/PriceDetailsModal/index.tsx b/components/HotelReservation/PriceDetailsModal/index.tsx new file mode 100644 index 000000000..002e25c94 --- /dev/null +++ b/components/HotelReservation/PriceDetailsModal/index.tsx @@ -0,0 +1,62 @@ +import { useIntl } from "react-intl" + +import ChevronRightSmallIcon from "@/components/Icons/ChevronRightSmall" +import Modal from "@/components/Modal" +import Button from "@/components/TempDesignSystem/Button" +import Caption from "@/components/TempDesignSystem/Text/Caption" + +import PriceDetailsTable from "./PriceDetailsTable" + +import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType" +import type { BreakfastPackage } from "@/types/components/hotelReservation/enterDetails/breakfast" +import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate" +import type { Price, RoomPrice } from "@/types/stores/enter-details" + +interface PriceDetailsModalProps { + fromDate: string + toDate: string + rooms: { + adults: number + childrenInRoom: Child[] | undefined + roomType: string + roomPrice: RoomPrice + bedType: BedTypeSchema | undefined + breakfast: BreakfastPackage | false | undefined + }[] + totalPrice: Price + vat: number + toggleModal: () => void +} + +export default function PriceDetailsModal({ + fromDate, + toDate, + rooms, + totalPrice, + vat, + toggleModal, +}: PriceDetailsModalProps) { + const intl = useIntl() + + return ( + + + {intl.formatMessage({ id: "Price details" })} + + + + } + > + + + ) +} diff --git a/i18n/dictionaries/de.json b/i18n/dictionaries/de.json index 4548c50f7..ed0f928e2 100644 --- a/i18n/dictionaries/de.json +++ b/i18n/dictionaries/de.json @@ -376,6 +376,7 @@ "Restaurant & Bar": "Restaurant & Bar", "Restaurants & Bars": "Restaurants & Bars", "Retype new password": "Neues Passwort erneut eingeben", + "Room": "Zimmer", "Room & Terms": "Zimmer & Bedingungen", "Room charge": "Zimmerpreis", "Room facilities": "Zimmerausstattung", diff --git a/i18n/dictionaries/en.json b/i18n/dictionaries/en.json index 86f73802f..f40723212 100644 --- a/i18n/dictionaries/en.json +++ b/i18n/dictionaries/en.json @@ -417,6 +417,7 @@ "Restaurant & Bar": "Restaurant & Bar", "Restaurants & Bars": "Restaurants & Bars", "Retype new password": "Retype new password", + "Room": "Room", "Room & Terms": "Room & Terms", "Room charge": "Room charge", "Room facilities": "Room facilities", diff --git a/i18n/dictionaries/fi.json b/i18n/dictionaries/fi.json index fa3696e4b..74dd19e36 100644 --- a/i18n/dictionaries/fi.json +++ b/i18n/dictionaries/fi.json @@ -378,6 +378,7 @@ "Restaurant & Bar": "Ravintola & Baari", "Restaurants & Bars": "Restaurants & Bars", "Retype new password": "Kirjoita uusi salasana uudelleen", + "Room": "Huone", "Room & Terms": "Huone & Ehdot", "Room charge": "Huonemaksu", "Room facilities": "Huoneen varustelu", diff --git a/i18n/dictionaries/no.json b/i18n/dictionaries/no.json index 2895508da..4ac8c63c4 100644 --- a/i18n/dictionaries/no.json +++ b/i18n/dictionaries/no.json @@ -377,6 +377,7 @@ "Restaurant & Bar": "Restaurant & Bar", "Restaurants & Bars": "Restaurants & Bars", "Retype new password": "Skriv inn nytt passord på nytt", + "Room": "Rom", "Room & Terms": "Rom & Vilkår", "Room charge": "Pris for rom", "Room facilities": "Romfasiliteter", diff --git a/i18n/dictionaries/sv.json b/i18n/dictionaries/sv.json index 36218d964..4c214b8c6 100644 --- a/i18n/dictionaries/sv.json +++ b/i18n/dictionaries/sv.json @@ -377,6 +377,7 @@ "Restaurant & Bar": "Restaurang & Bar", "Restaurants & Bars": "Restaurants & Bars", "Retype new password": "Upprepa nytt lösenord", + "Room": "Rum", "Room & Terms": "Rum & Villkor", "Room charge": "Rumspris", "Room facilities": "Rumfaciliteter", diff --git a/types/components/hotelReservation/enterDetails/priceDetailsTable.ts b/types/components/hotelReservation/enterDetails/priceDetailsTable.ts deleted file mode 100644 index f2204491d..000000000 --- a/types/components/hotelReservation/enterDetails/priceDetailsTable.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface PriceDetailsTableProps { - roomType: string -}