From 7710d3f8f90c11bccd7d58e4cac0e8ef35ccad1a Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Fri, 25 Oct 2024 11:09:03 +0200 Subject: [PATCH] fix: make summary sticky --- .../(standard)/[step]/@hotelHeader/page.tsx | 5 +- .../(standard)/[step]/@sidePeek/page.tsx | 5 +- .../(standard)/[step]/@summary/page.tsx | 59 ++++++++------ .../(standard)/[step]/layout.module.css | 79 ++++++++++++++++++- .../(standard)/[step]/layout.tsx | 6 +- .../(standard)/[step]/page.tsx | 18 +++-- .../(standard)/layout.module.css | 1 - .../EnterDetails/BedType/index.tsx | 7 +- .../EnterDetails/Summary/index.tsx | 21 +++-- .../SelectRate/RoomSelection/utils.ts | 4 +- .../Form/ChoiceCard/_Card/card.ts | 2 +- lib/trpc/memoizedRequests/index.ts | 15 ++-- next.config.js | 4 +- stores/enter-details.ts | 43 +--------- .../enterDetails/bookingData.ts | 5 +- .../hotelReservation/selectRate/selectRate.ts | 3 +- 16 files changed, 170 insertions(+), 107 deletions(-) diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@hotelHeader/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@hotelHeader/page.tsx index 58a216006..75101475a 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@hotelHeader/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@hotelHeader/page.tsx @@ -14,7 +14,10 @@ export default async function HotelHeader({ if (!searchParams.hotel) { redirect(home) } - const hotel = await getHotelData(searchParams.hotel, params.lang) + const hotel = await getHotelData({ + hotelId: searchParams.hotel, + language: params.lang, + }) if (!hotel?.data) { redirect(home) } diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@sidePeek/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@sidePeek/page.tsx index 13b770699..deca843c3 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@sidePeek/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@sidePeek/page.tsx @@ -13,7 +13,10 @@ export default async function HotelSidePeek({ if (!searchParams.hotel) { redirect(`/${params.lang}`) } - const hotel = await getHotelData(searchParams.hotel, params.lang) + const hotel = await getHotelData({ + hotelId: searchParams.hotel, + language: params.lang, + }) if (!hotel?.data) { redirect(`/${params.lang}`) } 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 4a15e3994..4258d94d8 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/@summary/page.tsx @@ -20,23 +20,31 @@ export default async function SummaryPage({ const { hotel, adults, children, roomTypeCode, rateCode, fromDate, toDate } = getQueryParamsForEnterDetails(selectRoomParams) - const user = await getProfileSafely() - const hotelData = await getHotelData(hotel, params.lang, undefined, [HotelIncludeEnum.RoomCategories]) - const availability = await getRoomAvailability({ - hotelId: parseInt(hotel), - adults, - children, - roomStayStartDate: fromDate, - roomStayEndDate: toDate, - }) + const [user, hotelData, availability] = await Promise.all([ + getProfileSafely(), + getHotelData({ + hotelId: hotel, + language: params.lang, + include: [HotelIncludeEnum.RoomCategories], + }), + getRoomAvailability({ + hotelId: parseInt(hotel), + adults, + children, + roomStayStartDate: fromDate, + roomStayEndDate: toDate, + }), + ]) if (!hotelData?.data || !hotelData?.included || !availability) { console.error("No hotel or availability data", hotelData, availability) - // TODO: handle this case return null } + const cancellationText = + availability?.rateDefinitions.find((rate) => rate.rateCode === rateCode) + ?.cancellationText ?? "" const chosenRoom = availability.roomConfigurations.find( (availRoom) => availRoom.roomTypeCode === roomTypeCode ) @@ -47,28 +55,31 @@ export default async function SummaryPage({ return null } - const cancellationText = - availability?.rateDefinitions.find((rate) => rate.rateCode === rateCode) - ?.cancellationText ?? "" + const memberRate = chosenRoom.products.find( + (rate) => rate.productType.member?.rateCode === rateCode + )?.productType.member - const memberPrice = - chosenRoom.products.find( - (rate) => rate.productType.member?.rateCode === rateCode - )?.productType.member?.localPrice.pricePerStay ?? "0" + const publicRate = chosenRoom.products.find( + (rate) => rate.productType.public?.rateCode === rateCode + )?.productType.public - const publicPrice = - chosenRoom.products.find( - (rate) => rate.productType.public?.rateCode === rateCode - )?.productType.public?.localPrice.pricePerStay ?? "0" - - const price = user ? memberPrice : publicPrice + const prices = user + ? { + local: memberRate?.localPrice.pricePerStay, + euro: memberRate?.requestedPrice?.pricePerStay, + } + : { + local: publicRate?.localPrice.pricePerStay, + euro: publicRate?.requestedPrice?.pricePerStay, + } return ( {children} - + {sidePeek} diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/page.tsx index 44de099bf..adfcbc34a 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/[step]/page.tsx @@ -20,7 +20,7 @@ import { getIntl } from "@/i18n" import { StepEnum } from "@/types/components/hotelReservation/enterDetails/step" import { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate" -import type { LangParams, PageArgs, } from "@/types/params" +import type { LangParams, PageArgs } from "@/types/params" export function preload() { void getProfileSafely() @@ -34,12 +34,10 @@ function isValidStep(step: string): step is StepEnum { export default async function StepPage({ params, searchParams, -}: PageArgs< - LangParams & { step: StepEnum }, - SelectRateSearchParams ->) { +}: PageArgs) { + const { lang } = params if (!searchParams.hotel) { - redirect(`/${params.lang}`) + redirect(`/${lang}`) } void getBreakfastPackages(searchParams.hotel) @@ -64,7 +62,11 @@ export default async function StepPage({ rateCode }) - const hotelData = await getHotelData(hotelId, params.lang, undefined, [HotelIncludeEnum.RoomCategories]) + const hotelData = await getHotelData({ + hotelId, + language: lang, + include: [HotelIncludeEnum.RoomCategories], + }) const user = await getProfileSafely() const savedCreditCards = await getCreditCardsSafely() @@ -153,6 +155,6 @@ export default async function StepPage({ mustBeGuaranteed={mustBeGuaranteed} /> - + ) } diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/layout.module.css b/app/[lang]/(live)/(public)/hotelreservation/(standard)/layout.module.css index 0969a7151..1730ffa68 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/layout.module.css +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/layout.module.css @@ -1,4 +1,3 @@ .layout { - min-height: 100dvh; background-color: var(--Base-Background-Primary-Normal); } diff --git a/components/HotelReservation/EnterDetails/BedType/index.tsx b/components/HotelReservation/EnterDetails/BedType/index.tsx index 27c95d963..646ec1311 100644 --- a/components/HotelReservation/EnterDetails/BedType/index.tsx +++ b/components/HotelReservation/EnterDetails/BedType/index.tsx @@ -43,10 +43,6 @@ export default function BedType({ reValidateMode: "onChange", }) - const text = intl.formatMessage( - { id: "Included (based on availability)" }, - { b: (str) => {str} } - ) const completeStep = useEnterDetailsStore((state) => state.completeStep) const onSubmit = useCallback( @@ -71,7 +67,7 @@ export default function BedType({ {roomTypes.map((roomType) => { const width = roomType.size.max === roomType.size.min - ? roomType.size.max + ? `${roomType.size.min} cm` : `${roomType.size.min} cm - ${roomType.size.max} cm` return ( diff --git a/components/HotelReservation/EnterDetails/Summary/index.tsx b/components/HotelReservation/EnterDetails/Summary/index.tsx index c1bad51f4..094c9e860 100644 --- a/components/HotelReservation/EnterDetails/Summary/index.tsx +++ b/components/HotelReservation/EnterDetails/Summary/index.tsx @@ -17,6 +17,7 @@ import useLang from "@/hooks/useLang" import styles from "./summary.module.css" import { RoomsData } from "@/types/components/hotelReservation/enterDetails/bookingData" +import { BreakfastPackageEnum } from "@/types/enums/breakfast" export default function Summary({ isMember, @@ -25,8 +26,8 @@ export default function Summary({ isMember: boolean room: RoomsData }) { - const [chosenBed, setChosenBed] = useState() - const [chosenBreakfast, setCosenBreakfast] = useState() + const [chosenBed, setChosenBed] = useState() + const [chosenBreakfast, setCosenBreakfast] = useState() const intl = useIntl() const lang = useLang() const { fromDate, toDate, bedType, breakfast } = useEnterDetailsStore( @@ -54,7 +55,11 @@ export default function Summary({ useEffect(() => { setChosenBed(bedType) - setCosenBreakfast(breakfast) + if (breakfast === BreakfastPackageEnum.NO_BREAKFAST) { + setCosenBreakfast("No breakfast") + } else if (breakfast) { + setCosenBreakfast("Breakfast buffet") + } }, [bedType, breakfast]) return ( @@ -75,7 +80,7 @@ export default function Summary({ {intl.formatMessage( { id: "{amount} {currency}" }, - { amount: room.price, currency: "SEK" } + { amount: room.localPrice, currency: "SEK" } )} @@ -121,7 +126,9 @@ export default function Summary({ {chosenBreakfast ? (
- {chosenBreakfast} + + {intl.formatMessage({ id: chosenBreakfast })} + {intl.formatMessage( { id: "{amount} {currency}" }, @@ -149,14 +156,14 @@ export default function Summary({ {intl.formatMessage( { id: "{amount} {currency}" }, - { amount: room.price, currency: "SEK" } // TODO: calculate total price + { amount: room.localPrice, currency: "SEK" } // TODO: calculate total price )} {intl.formatMessage({ id: "Approx." })}{" "} {intl.formatMessage( { id: "{amount} {currency}" }, - { amount: "455", currency: "EUR" } + { amount: room.euroPrice, currency: "EUR" } )}
diff --git a/components/HotelReservation/SelectRate/RoomSelection/utils.ts b/components/HotelReservation/SelectRate/RoomSelection/utils.ts index 24309d355..1fe62f39c 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/utils.ts +++ b/components/HotelReservation/SelectRate/RoomSelection/utils.ts @@ -16,8 +16,8 @@ export function getQueryParamsForEnterDetails(searchParams: URLSearchParams) { return { ...selectRoomParamsObject, adults: room[0].adults, // TODO: Handle multiple rooms - children: room[0].child?.length.toString(), // TODO: Handle multiple rooms - roomTypeCode: room[0].roomtypecode, + children: room[0].child?.length.toString(), // TODO: Handle multiple rooms and children + roomTypeCode: room[0].roomtype, rateCode: room[0].ratecode, } } diff --git a/components/TempDesignSystem/Form/ChoiceCard/_Card/card.ts b/components/TempDesignSystem/Form/ChoiceCard/_Card/card.ts index 145116409..8fe8476d3 100644 --- a/components/TempDesignSystem/Form/ChoiceCard/_Card/card.ts +++ b/components/TempDesignSystem/Form/ChoiceCard/_Card/card.ts @@ -23,7 +23,7 @@ interface ListCardProps extends BaseCardProps { interface TextCardProps extends BaseCardProps { list?: never - text: React.ReactNode + text?: React.ReactNode } export type CardProps = ListCardProps | TextCardProps diff --git a/lib/trpc/memoizedRequests/index.ts b/lib/trpc/memoizedRequests/index.ts index 00c404bfb..547ff7874 100644 --- a/lib/trpc/memoizedRequests/index.ts +++ b/lib/trpc/memoizedRequests/index.ts @@ -54,12 +54,17 @@ export const getUserTracking = cache(async function getMemoizedUserTracking() { return serverClient().user.tracking() }) -export const getHotelData = cache(async function getMemoizedHotelData( - hotelId: string, - language: string, - isCardOnlyPayment?: boolean, +export const getHotelData = cache(async function getMemoizedHotelData({ + hotelId, + language, + isCardOnlyPayment, + include, +}: { + hotelId: string + language: string + isCardOnlyPayment?: boolean include?: HotelIncludeEnum[] -) { +}) { return serverClient().hotel.hotelData.get({ hotelId, language, diff --git a/next.config.js b/next.config.js index f91af6594..fae418d6c 100644 --- a/next.config.js +++ b/next.config.js @@ -87,12 +87,12 @@ const nextConfig = { // value: undefined, // }, // { - // key: "fromdate", + // key: "fromDate", // type: "query", // value: undefined, // }, // { - // key: "todate", + // key: "toDate", // type: "query", // value: undefined, // }, diff --git a/stores/enter-details.ts b/stores/enter-details.ts index ccea01655..1c2c6b8d8 100644 --- a/stores/enter-details.ts +++ b/stores/enter-details.ts @@ -6,7 +6,7 @@ import { create, useStore } from "zustand" import { bedTypeSchema } from "@/components/HotelReservation/EnterDetails/BedType/schema" import { breakfastStoreSchema } from "@/components/HotelReservation/EnterDetails/Breakfast/schema" import { detailsSchema } from "@/components/HotelReservation/EnterDetails/Details/schema" -import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils" +import { getQueryParamsForEnterDetails } from "@/components/HotelReservation/SelectRate/RoomSelection/utils" import type { BookingData } from "@/types/components/hotelReservation/enterDetails/bookingData" import { BreakfastPackage } from "@/types/components/hotelReservation/enterDetails/breakfast" @@ -37,22 +37,6 @@ interface EnterDetailsState { closeSidePeek: () => void } -function getUpdatedValue( - searchParams: URLSearchParams, - key: string, - defaultValue: T -): T { - const value = searchParams.get(key) - if (value === null) return defaultValue - if (typeof defaultValue === "number") - return parseInt(value, 10) as unknown as T - if (typeof defaultValue === "boolean") - return (value === "true") as unknown as T - if (defaultValue instanceof Date) return new Date(value) as unknown as T - - return value as unknown as T -} - export function initEditDetailsState( currentStep: StepEnum, searchParams: ReadonlyURLSearchParams @@ -62,32 +46,9 @@ export function initEditDetailsState( ? sessionStorage.getItem(SESSION_STORAGE_KEY) : null - const today = new Date() - const tomorrow = new Date() - tomorrow.setDate(today.getDate() + 1) - let roomData: BookingData if (searchParams?.size) { - roomData = getHotelReservationQueryParams(searchParams) - - roomData.room = roomData.room.map((room, index) => ({ - ...room, - adults: getUpdatedValue( - searchParams, - `room[${index}].adults`, - room.adults - ), - roomtypecode: getUpdatedValue( - searchParams, - `room[${index}].roomtypecode`, - room.roomtypecode - ), - ratecode: getUpdatedValue( - searchParams, - `room[${index}].ratecode`, - room.ratecode - ), - })) + roomData = getQueryParamsForEnterDetails(searchParams) } const defaultUserData: EnterDetailsState["userData"] = { diff --git a/types/components/hotelReservation/enterDetails/bookingData.ts b/types/components/hotelReservation/enterDetails/bookingData.ts index 9a780fa66..058d67990 100644 --- a/types/components/hotelReservation/enterDetails/bookingData.ts +++ b/types/components/hotelReservation/enterDetails/bookingData.ts @@ -5,7 +5,7 @@ interface Child { interface Room { adults: number - roomtypecode?: string + roomtype?: string ratecode?: string child?: Child[] } @@ -18,7 +18,8 @@ export interface BookingData { export type RoomsData = { roomType: string - price: string + localPrice: string + euroPrice: string adults: number children?: Child[] cancellationText: string diff --git a/types/components/hotelReservation/selectRate/selectRate.ts b/types/components/hotelReservation/selectRate/selectRate.ts index 42ba91bde..fd1771955 100644 --- a/types/components/hotelReservation/selectRate/selectRate.ts +++ b/types/components/hotelReservation/selectRate/selectRate.ts @@ -7,8 +7,9 @@ export interface Child { interface Room { adults: number - roomtypecode?: string + roomtype?: string ratecode?: string + counterratecode?: string child?: Child[] }