diff --git a/.env.test b/.env.test index f651cbe63..1d303b099 100644 --- a/.env.test +++ b/.env.test @@ -44,3 +44,5 @@ GOOGLE_DYNAMIC_MAP_ID="test" HIDE_FOR_NEXT_RELEASE="true" SALESFORCE_PREFERENCE_BASE_URL="test" USE_NEW_REWARDS_ENDPOINT="true" + +TZ=UTC diff --git a/app/[lang]/(live)/(protected)/my-pages/@breadcrumbs/[...path]/page.tsx b/app/[lang]/(live)/(protected)/my-pages/@breadcrumbs/[...path]/page.tsx index 6775fd188..048cf9e5f 100644 --- a/app/[lang]/(live)/(protected)/my-pages/@breadcrumbs/[...path]/page.tsx +++ b/app/[lang]/(live)/(protected)/my-pages/@breadcrumbs/[...path]/page.tsx @@ -1,7 +1,7 @@ import { Suspense } from "react" import Breadcrumbs from "@/components/Breadcrumbs" -import BreadcrumbsSkeleton from "@/components/Breadcrumbs/BreadcrumbsSkeleton" +import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" import { setLang } from "@/i18n/serverContext" import { LangParams, PageArgs } from "@/types/params" diff --git a/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx b/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx index 528b7b211..4a94f599c 100644 --- a/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx +++ b/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx @@ -10,7 +10,7 @@ import styles from "./page.module.css" import type { LangParams, PageArgs } from "@/types/params" -export { generateMetadataAccountPage as generateMetadata } from "@/utils/generateMetadata" +export { generateMetadata } from "@/utils/generateMetadata" export default async function MyPages({ params, diff --git a/app/[lang]/(live)/(protected)/my-pages/layout.tsx b/app/[lang]/(live)/(protected)/my-pages/layout.tsx index 43268adca..80a038b9a 100644 --- a/app/[lang]/(live)/(protected)/my-pages/layout.tsx +++ b/app/[lang]/(live)/(protected)/my-pages/layout.tsx @@ -2,8 +2,8 @@ import { Suspense } from "react" import LoadingSpinner from "@/components/LoadingSpinner" import Sidebar from "@/components/MyPages/Sidebar" +import Surprises from "@/components/MyPages/Surprises" -// import Surprises from "@/components/MyPages/Surprises" import styles from "./layout.module.css" export default async function MyPagesLayout({ @@ -24,9 +24,7 @@ export default async function MyPagesLayout({ - {/* TODO: Waiting on new API stuff - - */} + ) } diff --git a/app/[lang]/(live)/(protected)/my-pages/profile/edit/page.tsx b/app/[lang]/(live)/(protected)/my-pages/profile/edit/page.tsx index dd8c6eb91..c2d24fe62 100644 --- a/app/[lang]/(live)/(protected)/my-pages/profile/edit/page.tsx +++ b/app/[lang]/(live)/(protected)/my-pages/profile/edit/page.tsx @@ -1,5 +1,5 @@ import ProfilePage from "../page" -export { generateMetadataAccountPage as generateMetadata } from "@/utils/generateMetadata" +export { generateMetadata } from "@/utils/generateMetadata" export default ProfilePage diff --git a/app/[lang]/(live)/(protected)/my-pages/profile/page.tsx b/app/[lang]/(live)/(protected)/my-pages/profile/page.tsx index ee8e3ad34..749065fc5 100644 --- a/app/[lang]/(live)/(protected)/my-pages/profile/page.tsx +++ b/app/[lang]/(live)/(protected)/my-pages/profile/page.tsx @@ -7,7 +7,7 @@ import { setLang } from "@/i18n/serverContext" import { LangParams, PageArgs } from "@/types/params" -export { generateMetadataAccountPage as generateMetadata } from "@/utils/generateMetadata" +export { generateMetadata } from "@/utils/generateMetadata" export default async function ProfilePage({ params }: PageArgs) { setLang(params.lang) diff --git a/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx b/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx index ec8f14553..f8024a816 100644 --- a/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx +++ b/app/[lang]/(live)/(public)/[contentType]/[uid]/@breadcrumbs/page.tsx @@ -1,7 +1,7 @@ import { Suspense } from "react" import Breadcrumbs from "@/components/Breadcrumbs" -import BreadcrumbsSkeleton from "@/components/Breadcrumbs/BreadcrumbsSkeleton" +import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" import { setLang } from "@/i18n/serverContext" import { LangParams, PageArgs } from "@/types/params" diff --git a/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/layout.module.css b/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/layout.module.css new file mode 100644 index 000000000..1730ffa68 --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/layout.module.css @@ -0,0 +1,3 @@ +.layout { + background-color: var(--Base-Background-Primary-Normal); +} diff --git a/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/layout.tsx b/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/layout.tsx new file mode 100644 index 000000000..b9ad3b13c --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/layout.tsx @@ -0,0 +1,16 @@ +import { notFound } from "next/navigation" + +import { env } from "@/env/server" + +import styles from "./layout.module.css" + +import { LangParams, LayoutArgs } from "@/types/params" + +export default function PaymentCallbackLayout({ + children, +}: React.PropsWithChildren>) { + if (env.HIDE_FOR_NEXT_RELEASE) { + return notFound() + } + return
{children}
+} diff --git a/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/page.tsx new file mode 100644 index 000000000..0e4e716f2 --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/page.tsx @@ -0,0 +1,70 @@ +import { redirect } from "next/navigation" + +import { + BOOKING_CONFIRMATION_NUMBER, + PaymentErrorCodeEnum, +} from "@/constants/booking" +import { Lang } from "@/constants/languages" +import { + bookingConfirmation, + payment, +} from "@/constants/routes/hotelReservation" +import { serverClient } from "@/lib/trpc/server" + +import PaymentCallback from "@/components/HotelReservation/EnterDetails/Payment/PaymentCallback" + +import { LangParams, PageArgs } from "@/types/params" + +export default async function PaymentCallbackPage({ + params, + searchParams, +}: PageArgs< + LangParams, + { status: "error" | "success" | "cancel"; confirmationNumber?: string } +>) { + console.log(`[payment-callback] callback started`) + const lang = params.lang + const status = searchParams.status + const confirmationNumber = searchParams.confirmationNumber + + if (status === "success" && confirmationNumber) { + const confirmationUrl = `${bookingConfirmation(lang)}?${BOOKING_CONFIRMATION_NUMBER}=${confirmationNumber}` + + console.log(`[payment-callback] redirecting to: ${confirmationUrl}`) + redirect(confirmationUrl) + } + + const returnUrl = payment(lang) + const searchObject = new URLSearchParams() + + if (confirmationNumber) { + try { + const bookingStatus = await serverClient().booking.status({ + confirmationNumber, + }) + if (bookingStatus.metadata) { + searchObject.set( + "errorCode", + bookingStatus.metadata.errorCode?.toString() ?? "" + ) + } + } catch (error) { + console.error( + `[payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}` + ) + if (status === "cancel") { + searchObject.set("errorCode", PaymentErrorCodeEnum.Cancelled.toString()) + } + if (status === "error") { + searchObject.set("errorCode", PaymentErrorCodeEnum.Failed.toString()) + } + } + } + + return ( + + ) +} diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx index e1a6e5315..aa5e5d523 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx @@ -3,7 +3,7 @@ import { notFound } from "next/navigation" import { Lang } from "@/constants/languages" import { env } from "@/env/server" -import { getLocations } from "@/lib/trpc/memoizedRequests" +import { getCityCoordinates, getLocations } from "@/lib/trpc/memoizedRequests" import { getHotelPins } from "@/components/HotelReservation/HotelCardDialogListing/utils" import SelectHotelMap from "@/components/HotelReservation/SelectHotel/SelectHotelMap" @@ -93,6 +93,7 @@ export default async function SelectHotelMapPage({ const hotelPins = getHotelPins(hotels) const filterList = getFiltersFromHotels(hotels) + const cityCoordinates = await getCityCoordinates({ city: city.name }) return ( @@ -102,6 +103,7 @@ export default async function SelectHotelMapPage({ mapId={googleMapId} hotels={hotels} filterList={filterList} + cityCoordinates={cityCoordinates} /> diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.module.css b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.module.css index e42544196..cb7245753 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.module.css +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.module.css @@ -14,6 +14,10 @@ padding: var(--Spacing-x3) var(--Spacing-x2) 0 var(--Spacing-x2); } +.header nav { + display: none; +} + .cityInformation { display: flex; flex-wrap: wrap; @@ -65,13 +69,19 @@ var(--Spacing-x5); } + .header nav { + display: block; + max-width: var(--max-width-navigation); + padding-left: 0; + } + .sorter { display: block; width: 339px; } .title { - margin: 0 auto; + margin: var(--Spacing-x3) auto 0; display: flex; max-width: var(--max-width-navigation); align-items: center; diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx index 21973a009..2f534e79f 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx @@ -1,8 +1,12 @@ import { differenceInCalendarDays, format, isWeekend } from "date-fns" import { notFound } from "next/navigation" +import { Suspense } from "react" import { Lang } from "@/constants/languages" -import { selectHotelMap } from "@/constants/routes/hotelReservation" +import { + selectHotel, + selectHotelMap, +} from "@/constants/routes/hotelReservation" import { getLocations } from "@/lib/trpc/memoizedRequests" import { @@ -21,6 +25,8 @@ import { import { ChevronRightIcon } from "@/components/Icons" import StaticMap from "@/components/Maps/StaticMap" import Alert from "@/components/TempDesignSystem/Alert" +import Breadcrumbs from "@/components/TempDesignSystem/Breadcrumbs" +import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" import Button from "@/components/TempDesignSystem/Button" import Link from "@/components/TempDesignSystem/Link" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" @@ -75,6 +81,27 @@ export default async function SelectHotelPage({ const departureDate = new Date(searchParams.toDate) const filterList = getFiltersFromHotels(hotels) + const breadcrumbs = [ + { + title: intl.formatMessage({ id: "Home" }), + href: `/${params.lang}`, + uid: "home-page", + }, + { + title: intl.formatMessage({ id: "Hotel reservation" }), + href: `/${params.lang}/hotelreservation`, + uid: "hotel-reservation", + }, + { + title: intl.formatMessage({ id: "Select hotel" }), + href: `${selectHotel(params.lang)}/?${selectHotelParams}`, + uid: "select-hotel", + }, + { + title: city.name, + uid: city.id, + }, + ] const isAllUnavailable = hotels.every((hotel) => hotel.price === undefined) @@ -106,6 +133,9 @@ export default async function SelectHotelPage({ return ( <>
+ }> + +
{city.name} diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/getValidDates.test.ts b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/getValidDates.test.ts new file mode 100644 index 000000000..61e162b02 --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/getValidDates.test.ts @@ -0,0 +1,55 @@ +import { beforeAll, describe, expect, it } from "@jest/globals" + +import { getValidFromDate, getValidToDate } from "./getValidDates" + +const NOW = new Date("2020-10-01T00:00:00Z") +let originalTz: string | undefined + +describe("getValidFromDate", () => { + beforeAll(() => { + jest.useFakeTimers({ now: NOW }) + }) + + afterAll(() => { + jest.useRealTimers() + }) + + describe("getValidFromDate", () => { + it("returns today when empty string is provided", () => { + const actual = getValidFromDate("") + expect(actual.toISOString()).toBe("2020-10-01T00:00:00.000Z") + }) + + it("returns today when undefined is provided", () => { + const actual = getValidFromDate(undefined) + expect(actual.toISOString()).toBe("2020-10-01T00:00:00.000Z") + }) + + it("returns given date in utc", () => { + const actual = getValidFromDate("2024-01-01") + expect(actual.toISOString()).toBe("2024-01-01T00:00:00.000Z") + }) + }) + + describe("getValidToDate", () => { + it("returns day after fromDate when empty string is provided", () => { + const actual = getValidToDate("", NOW) + expect(actual.toISOString()).toBe("2020-10-02T00:00:00.000Z") + }) + + it("returns day after fromDate when undefined is provided", () => { + const actual = getValidToDate(undefined, NOW) + expect(actual.toISOString()).toBe("2020-10-02T00:00:00.000Z") + }) + + it("returns given date in utc", () => { + const actual = getValidToDate("2024-01-01", NOW) + expect(actual.toISOString()).toBe("2024-01-01T00:00:00.000Z") + }) + + it("fallsback to day after fromDate when given date is before fromDate", () => { + const actual = getValidToDate("2020-09-30", NOW) + expect(actual.toISOString()).toBe("2020-10-02T00:00:00.000Z") + }) + }) +}) diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/getValidDates.ts b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/getValidDates.ts new file mode 100644 index 000000000..d9bcbf09e --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/getValidDates.ts @@ -0,0 +1,55 @@ +import { Dayjs } from "dayjs" + +import { dt } from "@/lib/dt" + +/** + * Get valid dates from stringFromDate and stringToDate making sure that they are not in the past and chronologically correct + * @example const { fromDate, toDate} = getValidDates("2021-01-01", "2021-01-02") + */ +export function getValidDates( + stringFromDate: string | undefined, + stringToDate: string | undefined +): { fromDate: Dayjs; toDate: Dayjs } { + const fromDate = getValidFromDate(stringFromDate) + const toDate = getValidToDate(stringToDate, fromDate) + + return { fromDate, toDate } +} + +/** + * Get valid fromDate from stringFromDate making sure that it is not in the past + */ +export function getValidFromDate(stringFromDate: string | undefined): Dayjs { + const now = dt().utc() + if (!stringFromDate) { + return now + } + const toDate = dt(stringFromDate) + + const yesterday = now.subtract(1, "day") + if (!toDate.isAfter(yesterday)) { + return now + } + + return toDate +} + +/** + * Get valid toDate from stringToDate making sure that it is after fromDate + */ +export function getValidToDate( + stringToDate: string | undefined, + fromDate: Dayjs | Date +): Dayjs { + const tomorrow = dt().utc().add(1, "day") + if (!stringToDate) { + return tomorrow + } + + const toDate = dt(stringToDate) + if (toDate.isAfter(fromDate)) { + return toDate + } + + return tomorrow +} diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx index 0aa44c7ab..5a5e7744a 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx @@ -1,25 +1,20 @@ import { differenceInCalendarDays, format, isWeekend } from "date-fns" import { notFound } from "next/navigation" +import { Suspense } from "react" import { Lang } from "@/constants/languages" -import { dt } from "@/lib/dt" -import { - getHotelData, - getLocations, - getProfileSafely, -} from "@/lib/trpc/memoizedRequests" -import { serverClient } from "@/lib/trpc/server" +import { getHotelData, getLocations } from "@/lib/trpc/memoizedRequests" import HotelInfoCard from "@/components/HotelReservation/SelectRate/HotelInfoCard" -import Rooms from "@/components/HotelReservation/SelectRate/Rooms" -import { - generateChildrenString, - getHotelReservationQueryParams, -} from "@/components/HotelReservation/SelectRate/RoomSelection/utils" +import { RoomsContainer } from "@/components/HotelReservation/SelectRate/Rooms/RoomsContainer" +import { RoomsContainerSkeleton } from "@/components/HotelReservation/SelectRate/Rooms/RoomsContainerSkeleton" +import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils" import TrackingSDK from "@/components/TrackingSDK" import { setLang } from "@/i18n/serverContext" +import { safeTry } from "@/utils/safeTry" + +import { getValidDates } from "./getValidDates" -import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter" import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate" import { TrackingChannelEnum, @@ -53,58 +48,27 @@ export default async function SelectRatePage({ return notFound() } - const validFromDate = - searchParams.fromDate && - dt(searchParams.fromDate).isAfter(dt().subtract(1, "day")) - ? searchParams.fromDate - : dt().utc().format("YYYY-MM-DD") - const validToDate = - searchParams.toDate && dt(searchParams.toDate).isAfter(validFromDate) - ? searchParams.toDate - : dt().utc().add(1, "day").format("YYYY-MM-DD") + const { fromDate, toDate } = getValidDates( + searchParams.fromDate, + searchParams.toDate + ) + const adults = selectRoomParamsObject.room[0].adults || 1 // TODO: Handle multiple rooms - const childrenCount = selectRoomParamsObject.room[0].child?.length - const children = selectRoomParamsObject.room[0].child - ? generateChildrenString(selectRoomParamsObject.room[0].child) - : undefined // TODO: Handle multiple rooms + const children = selectRoomParamsObject.room[0].child // TODO: Handle multiple rooms - const [hotelData, roomsAvailability, packages, user] = await Promise.all([ - getHotelData({ hotelId: searchParams.hotel, language: params.lang }), - serverClient().hotel.availability.rooms({ - hotelId: parseInt(searchParams.hotel, 10), - roomStayStartDate: validFromDate, - roomStayEndDate: validToDate, - adults, - children, - }), - serverClient().hotel.packages.get({ - hotelId: searchParams.hotel, - startDate: searchParams.fromDate, - endDate: searchParams.toDate, - adults, - children: childrenCount, - packageCodes: [ - RoomPackageCodeEnum.ACCESSIBILITY_ROOM, - RoomPackageCodeEnum.PET_ROOM, - RoomPackageCodeEnum.ALLERGY_ROOM, - ], - }), - getProfileSafely(), - ]) + const [hotelData, hotelDataError] = await safeTry( + getHotelData({ hotelId: searchParams.hotel, language: params.lang }) + ) + if (!hotelData && !hotelDataError) { + return notFound() + } const arrivalDate = new Date(searchParams.fromDate) const departureDate = new Date(searchParams.toDate) const hotelAttributes = hotelData?.data.attributes const roomCategories = hotelData?.included - const noRoomsAvailable = roomsAvailability?.roomConfigurations.reduce( - (acc, room) => { - return acc && room.status === "NotAvailable" - }, - true - ) - const pageTrackingData: TrackingSDKPageData = { pageId: "select-rate", domainLanguage: params.lang as Lang, @@ -119,7 +83,7 @@ export default async function SelectRatePage({ arrivalDate: format(arrivalDate, "yyyy-MM-dd"), departureDate: format(departureDate, "yyyy-MM-dd"), noOfAdults: adults, - noOfChildren: childrenCount, + noOfChildren: children?.length, //childBedPreference // "adults|adults|extra|adults" noOfRooms: 1, // // TODO: Handle multiple rooms duration: differenceInCalendarDays(departureDate, arrivalDate), @@ -132,26 +96,28 @@ export default async function SelectRatePage({ //lowestRoomPrice: } - if (!roomsAvailability) { - return "No rooms found" // TODO: Add a proper error message - } - - if (!hotelData) { - return "No hotel data found" // TODO: Add a proper error message - } - + const hotelId = +searchParams.hotel return ( <> - + + }> + + ) 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 0444913f1..0fb655de6 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/@summary/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/@summary/page.tsx @@ -64,32 +64,34 @@ export default async function SummaryPage({ redirect(selectRate(params.lang)) } - const prices = - user && availability.memberRate + const prices = { + public: { + local: { + amount: availability.publicRate.localPrice.pricePerStay, + currency: availability.publicRate.localPrice.currency, + }, + euro: availability.publicRate?.requestedPrice + ? { + amount: availability.publicRate?.requestedPrice.pricePerStay, + currency: availability.publicRate?.requestedPrice.currency, + } + : undefined, + }, + member: availability.memberRate ? { local: { - price: availability.memberRate.localPrice.pricePerStay, + amount: availability.memberRate.localPrice.pricePerStay, currency: availability.memberRate.localPrice.currency, }, euro: availability.memberRate.requestedPrice ? { - price: availability.memberRate.requestedPrice.pricePerStay, + amount: availability.memberRate.requestedPrice.pricePerStay, currency: availability.memberRate.requestedPrice.currency, } : undefined, } - : { - local: { - price: availability.publicRate.localPrice.pricePerStay, - currency: availability.publicRate.localPrice.currency, - }, - euro: availability.publicRate?.requestedPrice - ? { - price: availability.publicRate?.requestedPrice.pricePerStay, - currency: availability.publicRate?.requestedPrice.currency, - } - : undefined, - } + : undefined, + } return ( <> @@ -100,8 +102,7 @@ export default async function SummaryPage({ showMemberPrice={!!(user && availability.memberRate)} room={{ roomType: availability.selectedRoom.roomType, - localPrice: prices.local, - euroPrice: prices.euro, + prices, adults, children, rateDetails: availability.rateDetails, @@ -119,8 +120,7 @@ export default async function SummaryPage({ showMemberPrice={!!(user && availability.memberRate)} room={{ roomType: availability.selectedRoom.roomType, - localPrice: prices.local, - euroPrice: prices.euro, + prices, adults, children, rateDetails: availability.rateDetails, diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx index d175fc25f..4fbaae7ff 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/page.tsx @@ -171,6 +171,7 @@ export default async function StepPage({ label={mustBeGuaranteed ? guaranteeWithCard : selectPaymentMethod} > + diff --git a/app/api/web/payment-callback/[lang]/[status]/route.ts b/app/api/web/payment-callback/[lang]/[status]/route.ts deleted file mode 100644 index 5884d63f9..000000000 --- a/app/api/web/payment-callback/[lang]/[status]/route.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { NextRequest, NextResponse } from "next/server" - -import { - BOOKING_CONFIRMATION_NUMBER, - PaymentErrorCodeEnum, -} from "@/constants/booking" -import { Lang } from "@/constants/languages" -import { - bookingConfirmation, - payment, -} from "@/constants/routes/hotelReservation" -import { serverClient } from "@/lib/trpc/server" -import { getPublicURL } from "@/server/utils" - -export async function GET( - request: NextRequest, - { params }: { params: { lang: string; status: string } } -): Promise { - const publicURL = getPublicURL(request) - - console.log(`[payment-callback] callback started`) - const lang = params.lang as Lang - const status = params.status - - const queryParams = request.nextUrl.searchParams - const confirmationNumber = queryParams.get(BOOKING_CONFIRMATION_NUMBER) - - if (status === "success" && confirmationNumber) { - const confirmationUrl = new URL(`${publicURL}/${bookingConfirmation(lang)}`) - confirmationUrl.searchParams.set( - BOOKING_CONFIRMATION_NUMBER, - confirmationNumber - ) - - console.log(`[payment-callback] redirecting to: ${confirmationUrl}`) - return NextResponse.redirect(confirmationUrl) - } - - const returnUrl = new URL(`${publicURL}/${payment(lang)}`) - returnUrl.search = queryParams.toString() - - if (confirmationNumber) { - try { - const bookingStatus = await serverClient().booking.status({ - confirmationNumber, - }) - if (bookingStatus.metadata) { - returnUrl.searchParams.set( - "errorCode", - bookingStatus.metadata.errorCode?.toString() ?? "" - ) - } - } catch (error) { - console.error( - `[payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}` - ) - - if (status === "cancel") { - returnUrl.searchParams.set( - "errorCode", - PaymentErrorCodeEnum.Cancelled.toString() - ) - } - if (status === "error") { - returnUrl.searchParams.set( - "errorCode", - PaymentErrorCodeEnum.Failed.toString() - ) - } - } - } - - console.log(`[payment-callback] redirecting to: ${returnUrl}`) - return NextResponse.redirect(returnUrl) -} diff --git a/components/Breadcrumbs/index.tsx b/components/Breadcrumbs/index.tsx index adf892011..00d3d7985 100644 --- a/components/Breadcrumbs/index.tsx +++ b/components/Breadcrumbs/index.tsx @@ -1,60 +1,25 @@ import { serverClient } from "@/lib/trpc/server" -import { ChevronRightSmallIcon, HouseIcon } from "@/components/Icons" -import Link from "@/components/TempDesignSystem/Link" -import Footnote from "@/components/TempDesignSystem/Text/Footnote" - -import styles from "./breadcrumbs.module.css" +import BreadcrumbsComp from "@/components/TempDesignSystem/Breadcrumbs" +import { generateBreadcrumbsSchema } from "@/utils/jsonSchemas" export default async function Breadcrumbs() { const breadcrumbs = await serverClient().contentstack.breadcrumbs.get() + if (!breadcrumbs?.length) { return null } + const jsonSchema = generateBreadcrumbsSchema(breadcrumbs) - const homeBreadcrumb = breadcrumbs.shift() return ( - + <> +