Merge remote-tracking branch 'origin' into feature/tracking
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { NextRequest, NextResponse } from "next/server"
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { AuthError } from "next-auth"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
|
||||
@@ -4,7 +4,7 @@ import Breadcrumbs from "@/components/Breadcrumbs"
|
||||
import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default function AllBreadcrumbs({ params }: PageArgs<LangParams>) {
|
||||
setLang(params.lang)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@media screen and (min-width: 1367px) {
|
||||
.content {
|
||||
gap: var(--Spacing-x5);
|
||||
grid-template-columns: max(360px) 1fr;
|
||||
grid-template-columns: max(340px) 1fr;
|
||||
padding-left: var(--Spacing-x5);
|
||||
padding-right: var(--Spacing-x5);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function CommunicationSlot({
|
||||
params,
|
||||
|
||||
@@ -9,7 +9,7 @@ import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function CreditCardSlot({ params }: PageArgs<LangParams>) {
|
||||
setLang(params.lang)
|
||||
|
||||
@@ -9,7 +9,7 @@ import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function MembershipCardSlot({
|
||||
params,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { getProfile } from "@/lib/trpc/memoizedRequests"
|
||||
import Form from "@/components/Forms/Edit/Profile"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function EditProfileSlot({
|
||||
params,
|
||||
|
||||
@@ -20,7 +20,7 @@ import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function Profile({ params }: PageArgs<LangParams>) {
|
||||
setLang(params.lang)
|
||||
|
||||
@@ -5,7 +5,7 @@ import { serverClient } from "@/lib/trpc/server"
|
||||
import TrackingSDK from "@/components/TrackingSDK"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export { generateMetadata } from "@/utils/generateMetadata"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import Breadcrumbs from "@/components/Breadcrumbs"
|
||||
import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default function PageBreadcrumbs({ params }: PageArgs<LangParams>) {
|
||||
setLang(params.lang)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { setPreviewData } from "@/lib/previewContext"
|
||||
|
||||
import InitLivePreview from "@/components/LivePreview"
|
||||
|
||||
import { PageArgs, UIDParams } from "@/types/params"
|
||||
import type { PageArgs, UIDParams } from "@/types/params"
|
||||
|
||||
export default function PreviewPage({
|
||||
searchParams,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import styles from "./layout.module.css"
|
||||
|
||||
import {
|
||||
import type {
|
||||
ContentTypeParams,
|
||||
LangParams,
|
||||
LayoutArgs,
|
||||
|
||||
@@ -11,7 +11,7 @@ import CollectionPage from "@/components/ContentType/StaticPages/CollectionPage"
|
||||
import ContentPage from "@/components/ContentType/StaticPages/ContentPage"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import {
|
||||
import type {
|
||||
ContentTypeParams,
|
||||
LangParams,
|
||||
PageArgs,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import styles from "./layout.module.css"
|
||||
|
||||
import { LangParams, LayoutArgs } from "@/types/params"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
|
||||
export default function PaymentCallbackLayout({
|
||||
children,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import PaymentCallback from "@/components/HotelReservation/EnterDetails/Payment/PaymentCallback"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function PaymentCallbackPage({
|
||||
params,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import styles from "./layout.module.css"
|
||||
|
||||
import { LangParams, LayoutArgs } from "@/types/params"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
|
||||
export default function HotelReservationLayout({
|
||||
children,
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import LoadingSpinner from "@/components/LoadingSpinner"
|
||||
|
||||
export default function LoadingModal() {
|
||||
return <LoadingSpinner />
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
|
||||
import { notFound } from "next/navigation"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
import { env } from "@/env/server"
|
||||
import { getCityCoordinates, getLocations } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import { getHotelPins } from "@/components/HotelReservation/HotelCardDialogListing/utils"
|
||||
import SelectHotelMap from "@/components/HotelReservation/SelectHotel/SelectHotelMap"
|
||||
import {
|
||||
generateChildrenString,
|
||||
getHotelReservationQueryParams,
|
||||
} from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { MapModal } from "@/components/MapModal"
|
||||
import TrackingSDK from "@/components/TrackingSDK"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { fetchAvailableHotels, getFiltersFromHotels } from "../../utils"
|
||||
|
||||
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
|
||||
import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
|
||||
import {
|
||||
TrackingChannelEnum,
|
||||
TrackingSDKHotelInfo,
|
||||
TrackingSDKPageData,
|
||||
} from "@/types/components/tracking"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function SelectHotelMapPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageArgs<LangParams, SelectHotelSearchParams>) {
|
||||
setLang(params.lang)
|
||||
const locations = await getLocations()
|
||||
|
||||
if (!locations || "error" in locations) {
|
||||
return null
|
||||
}
|
||||
const city = locations.data.find(
|
||||
(location) =>
|
||||
location.name.toLowerCase() === searchParams.city.toLowerCase()
|
||||
)
|
||||
if (!city) return notFound()
|
||||
|
||||
const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID
|
||||
const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY
|
||||
|
||||
const selectHotelParams = new URLSearchParams(searchParams)
|
||||
const selectHotelParamsObject =
|
||||
getHotelReservationQueryParams(selectHotelParams)
|
||||
const adults = selectHotelParamsObject.room[0].adults // TODO: Handle multiple rooms
|
||||
const child = selectHotelParamsObject.room[0].child // TODO: Handle multiple rooms
|
||||
const children = child ? generateChildrenString(child) : undefined // TODO: Handle multiple rooms
|
||||
|
||||
const hotels = await fetchAvailableHotels({
|
||||
cityId: city.id,
|
||||
roomStayStartDate: searchParams.fromDate,
|
||||
roomStayEndDate: searchParams.toDate,
|
||||
adults,
|
||||
children,
|
||||
})
|
||||
|
||||
const validHotels = hotels.filter(
|
||||
(hotel): hotel is HotelData => hotel !== null
|
||||
)
|
||||
|
||||
const arrivalDate = new Date(searchParams.fromDate)
|
||||
const departureDate = new Date(searchParams.toDate)
|
||||
|
||||
const pageTrackingData: TrackingSDKPageData = {
|
||||
pageId: "select-hotel",
|
||||
domainLanguage: params.lang as Lang,
|
||||
channel: TrackingChannelEnum["hotelreservation"],
|
||||
pageName: "hotelreservation|select-hotel|mapview",
|
||||
siteSections: "hotelreservation|select-hotel|mapview",
|
||||
pageType: "bookinghotelsmapviewpage",
|
||||
siteVersion: "new-web",
|
||||
}
|
||||
|
||||
const hotelsTrackingData: TrackingSDKHotelInfo = {
|
||||
availableResults: hotels.length,
|
||||
searchTerm: searchParams.city,
|
||||
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
|
||||
departureDate: format(departureDate, "yyyy-MM-dd"),
|
||||
noOfAdults: adults,
|
||||
noOfChildren: child?.length,
|
||||
ageOfChildren: child?.map((c) => c.age).join(","),
|
||||
childBedPreference: child?.map((c) => ChildBedMapEnum[c.bed]).join("|"),
|
||||
noOfRooms: 1, // // TODO: Handle multiple rooms
|
||||
duration: differenceInCalendarDays(departureDate, arrivalDate),
|
||||
leadTime: differenceInCalendarDays(arrivalDate, new Date()),
|
||||
searchType: "destination",
|
||||
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
|
||||
country: validHotels?.[0].hotelData.address.country,
|
||||
region: validHotels?.[0].hotelData.address.city,
|
||||
}
|
||||
|
||||
const hotelPins = getHotelPins(validHotels)
|
||||
const filterList = getFiltersFromHotels(validHotels)
|
||||
const cityCoordinates = await getCityCoordinates({
|
||||
city: city.name,
|
||||
hotel: { address: hotels?.[0]?.hotelData?.address.streetAddress },
|
||||
})
|
||||
|
||||
return (
|
||||
<MapModal>
|
||||
<SelectHotelMap
|
||||
apiKey={googleMapsApiKey}
|
||||
hotelPins={hotelPins}
|
||||
mapId={googleMapId}
|
||||
hotels={validHotels}
|
||||
filterList={filterList}
|
||||
cityCoordinates={cityCoordinates}
|
||||
/>
|
||||
<Suspense fallback={null}>
|
||||
<TrackingSDK
|
||||
pageData={pageTrackingData}
|
||||
hotelInfo={hotelsTrackingData}
|
||||
/>
|
||||
</Suspense>
|
||||
</MapModal>
|
||||
)
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export default function Default() {
|
||||
return null
|
||||
}
|
||||
@@ -3,3 +3,9 @@
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.layout {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
import styles from "./layout.module.css"
|
||||
|
||||
import { LangParams, LayoutArgs } from "@/types/params"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
|
||||
export default function HotelReservationLayout({
|
||||
children,
|
||||
modal,
|
||||
}: React.PropsWithChildren<
|
||||
LayoutArgs<LangParams> & { modal: React.ReactNode }
|
||||
>) {
|
||||
return (
|
||||
<div className={styles.layout}>
|
||||
{children}
|
||||
{modal}
|
||||
</div>
|
||||
)
|
||||
}: React.PropsWithChildren<LayoutArgs<LangParams>>) {
|
||||
return <div className={styles.layout}>{children}</div>
|
||||
}
|
||||
|
||||
@@ -1 +1,63 @@
|
||||
export { default } from "../@modal/(.)map/page"
|
||||
import { notFound } from "next/navigation"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { getLocations } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import { SelectHotelMapContainer } from "@/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer"
|
||||
import { SelectHotelMapContainerSkeleton } from "@/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainerSkeleton"
|
||||
import {
|
||||
generateChildrenString,
|
||||
getHotelReservationQueryParams,
|
||||
} from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { MapContainer } from "@/components/MapContainer"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function SelectHotelMapPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageArgs<LangParams, SelectHotelSearchParams>) {
|
||||
setLang(params.lang)
|
||||
const locations = await getLocations()
|
||||
|
||||
if (!locations || "error" in locations) {
|
||||
return null
|
||||
}
|
||||
const city = locations.data.find(
|
||||
(location) =>
|
||||
location.name.toLowerCase() === searchParams.city.toLowerCase()
|
||||
)
|
||||
if (!city) return notFound()
|
||||
|
||||
const selectHotelParams = new URLSearchParams(searchParams)
|
||||
const selectHotelParamsObject =
|
||||
getHotelReservationQueryParams(selectHotelParams)
|
||||
const adultsInRoom = selectHotelParamsObject.room[0].adults // TODO: Handle multiple rooms
|
||||
const childrenInRoom = selectHotelParamsObject.room[0].child
|
||||
? generateChildrenString(selectHotelParamsObject.room[0].child)
|
||||
: undefined // TODO: Handle multiple rooms
|
||||
const child = selectHotelParamsObject.room[0].child // TODO: Handle multiple rooms
|
||||
|
||||
return (
|
||||
<div className={styles.main}>
|
||||
<MapContainer>
|
||||
<Suspense
|
||||
key={city.name}
|
||||
fallback={<SelectHotelMapContainerSkeleton />}
|
||||
>
|
||||
<SelectHotelMapContainer
|
||||
city={city}
|
||||
searchParams={searchParams}
|
||||
adultsInRoom={adultsInRoom}
|
||||
childrenInRoom={childrenInRoom}
|
||||
child={child}
|
||||
/>
|
||||
</Suspense>
|
||||
</MapContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
.main {
|
||||
display: flex;
|
||||
padding: 0 var(--Spacing-x2) var(--Spacing-x3) var(--Spacing-x2);
|
||||
background-color: var(--Scandic-Brand-Warm-White);
|
||||
min-height: 100dvh;
|
||||
flex-direction: column;
|
||||
max-width: var(--max-width);
|
||||
margin: 0 auto;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x2);
|
||||
padding: var(--Spacing-x3) var(--Spacing-x2) 0 var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.header nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cityInformation {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.sorter {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sideBar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
display: flex;
|
||||
gap: var(--Spacing-x2);
|
||||
margin-bottom: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.button {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.hotelList {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.filter {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.main {
|
||||
padding: var(--Spacing-x5);
|
||||
}
|
||||
.header {
|
||||
display: block;
|
||||
background-color: var(--Base-Surface-Subtle-Normal);
|
||||
padding: var(--Spacing-x4) var(--Spacing-x5) var(--Spacing-x3)
|
||||
var(--Spacing-x5);
|
||||
}
|
||||
|
||||
.header nav {
|
||||
display: block;
|
||||
max-width: var(--max-width-navigation);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sorter {
|
||||
display: block;
|
||||
width: 339px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: var(--Spacing-x3) auto 0;
|
||||
display: flex;
|
||||
max-width: var(--max-width-navigation);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.sideBar {
|
||||
max-width: 340px;
|
||||
}
|
||||
.filter {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.link {
|
||||
display: flex;
|
||||
padding-bottom: var(--Spacing-x6);
|
||||
}
|
||||
.mapContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--Base-Surface-Primary-light-Normal);
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
border: 1px solid var(--Base-Border-Subtle);
|
||||
}
|
||||
.main {
|
||||
flex-direction: row;
|
||||
gap: var(--Spacing-x5);
|
||||
}
|
||||
.buttonContainer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,18 @@
|
||||
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
|
||||
import { notFound } from "next/navigation"
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
import {
|
||||
selectHotel,
|
||||
selectHotelMap,
|
||||
} from "@/constants/routes/hotelReservation"
|
||||
import { getLocations } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import {
|
||||
fetchAvailableHotels,
|
||||
getFiltersFromHotels,
|
||||
} from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils"
|
||||
import HotelCardListing from "@/components/HotelReservation/HotelCardListing"
|
||||
import HotelCount from "@/components/HotelReservation/SelectHotel/HotelCount"
|
||||
import HotelFilter from "@/components/HotelReservation/SelectHotel/HotelFilter"
|
||||
import HotelSorter from "@/components/HotelReservation/SelectHotel/HotelSorter"
|
||||
import MobileMapButtonContainer from "@/components/HotelReservation/SelectHotel/MobileMapButtonContainer"
|
||||
import SelectHotel from "@/components/HotelReservation/SelectHotel"
|
||||
import { SelectHotelSkeleton } from "@/components/HotelReservation/SelectHotel/SelectHotelSkeleton"
|
||||
import {
|
||||
generateChildrenString,
|
||||
getHotelReservationQueryParams,
|
||||
} from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
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"
|
||||
import TrackingSDK from "@/components/TrackingSDK"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
|
||||
import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
|
||||
import {
|
||||
TrackingChannelEnum,
|
||||
TrackingSDKHotelInfo,
|
||||
TrackingSDKPageData,
|
||||
} from "@/types/components/tracking"
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default async function SelectHotelPage({
|
||||
params,
|
||||
@@ -64,10 +31,6 @@ export default async function SelectHotelPage({
|
||||
|
||||
if (!city) return notFound()
|
||||
|
||||
const isCityWithCountry = (city: any): city is { country: string } =>
|
||||
"country" in city
|
||||
|
||||
const intl = await getIntl()
|
||||
const selectHotelParams = new URLSearchParams(searchParams)
|
||||
const selectHotelParamsObject =
|
||||
getHotelReservationQueryParams(selectHotelParams)
|
||||
@@ -79,157 +42,30 @@ export default async function SelectHotelPage({
|
||||
return notFound()
|
||||
}
|
||||
|
||||
const adults = selectHotelParamsObject.room[0].adults // TODO: Handle multiple rooms
|
||||
const adultsParams = selectHotelParamsObject.room[0].adults // TODO: Handle multiple rooms
|
||||
const childrenParams = selectHotelParamsObject.room[0].child
|
||||
? generateChildrenString(selectHotelParamsObject.room[0].child)
|
||||
: undefined // TODO: Handle multiple rooms
|
||||
const child = selectHotelParamsObject.room[0].child // TODO: Handle multiple rooms
|
||||
const children = child ? generateChildrenString(child) : undefined
|
||||
|
||||
const hotels = await fetchAvailableHotels({
|
||||
cityId: city.id,
|
||||
roomStayStartDate: searchParams.fromDate,
|
||||
roomStayEndDate: searchParams.toDate,
|
||||
adults,
|
||||
children,
|
||||
})
|
||||
|
||||
const arrivalDate = new Date(searchParams.fromDate)
|
||||
const departureDate = new Date(searchParams.toDate)
|
||||
|
||||
const validHotels = hotels.filter(
|
||||
(hotel): hotel is HotelData => hotel !== null
|
||||
)
|
||||
|
||||
const filterList = getFiltersFromHotels(validHotels)
|
||||
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)
|
||||
|
||||
const pageTrackingData: TrackingSDKPageData = {
|
||||
pageId: "select-hotel",
|
||||
domainLanguage: params.lang as Lang,
|
||||
channel: TrackingChannelEnum["hotelreservation"],
|
||||
pageName: "hotelreservation|select-hotel",
|
||||
siteSections: "hotelreservation|select-hotel",
|
||||
pageType: "bookinghotelspage",
|
||||
siteVersion: "new-web",
|
||||
}
|
||||
|
||||
const hotelsTrackingData: TrackingSDKHotelInfo = {
|
||||
availableResults: hotels.length,
|
||||
searchTerm: searchParams.city,
|
||||
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
|
||||
departureDate: format(departureDate, "yyyy-MM-dd"),
|
||||
noOfAdults: adults,
|
||||
noOfChildren: child?.length,
|
||||
ageOfChildren: child?.map((c) => c.age).join(","),
|
||||
childBedPreference: child?.map((c) => ChildBedMapEnum[c.bed]).join("|"),
|
||||
noOfRooms: 1, // // TODO: Handle multiple rooms
|
||||
duration: differenceInCalendarDays(departureDate, arrivalDate),
|
||||
leadTime: differenceInCalendarDays(arrivalDate, new Date()),
|
||||
searchType: "destination",
|
||||
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
|
||||
country: validHotels?.[0].hotelData.address.country,
|
||||
region: validHotels?.[0].hotelData.address.city,
|
||||
const reservationParams = {
|
||||
selectHotelParams,
|
||||
searchParams,
|
||||
adultsParams,
|
||||
childrenParams,
|
||||
child,
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<header className={styles.header}>
|
||||
<Suspense fallback={<BreadcrumbsSkeleton />}>
|
||||
<Breadcrumbs breadcrumbs={breadcrumbs} />
|
||||
</Suspense>
|
||||
<div className={styles.title}>
|
||||
<div className={styles.cityInformation}>
|
||||
<Subtitle>{city.name}</Subtitle>
|
||||
<HotelCount />
|
||||
</div>
|
||||
<div className={styles.sorter}>
|
||||
<HotelSorter discreet />
|
||||
</div>
|
||||
</div>
|
||||
<MobileMapButtonContainer filters={filterList} />
|
||||
</header>
|
||||
<main className={styles.main}>
|
||||
<div className={styles.sideBar}>
|
||||
{hotels.length > 0 ? ( // TODO: Temp fix until API returns hotels that are not available
|
||||
<Link
|
||||
className={styles.link}
|
||||
color="burgundy"
|
||||
href={selectHotelMap(params.lang)}
|
||||
keepSearchParams
|
||||
>
|
||||
<div className={styles.mapContainer}>
|
||||
<StaticMap
|
||||
city={searchParams.city}
|
||||
country={isCityWithCountry(city) ? city.country : undefined}
|
||||
width={340}
|
||||
height={180}
|
||||
zoomLevel={11}
|
||||
mapType="roadmap"
|
||||
altText={`Map of ${searchParams.city} city center`}
|
||||
/>
|
||||
<Button wrapping size="medium" intent="text" theme="base">
|
||||
{intl.formatMessage({ id: "See map" })}
|
||||
<ChevronRightIcon
|
||||
color="baseButtonTextOnFillNormal"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</Link>
|
||||
) : (
|
||||
<div className={styles.mapContainer}>
|
||||
<StaticMap
|
||||
city={searchParams.city}
|
||||
width={340}
|
||||
height={180}
|
||||
zoomLevel={11}
|
||||
mapType="roadmap"
|
||||
altText={`Map of ${searchParams.city} city center`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<HotelFilter filters={filterList} className={styles.filter} />
|
||||
</div>
|
||||
<div className={styles.hotelList}>
|
||||
{isAllUnavailable && (
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({ id: "No availability" })}
|
||||
text={intl.formatMessage({
|
||||
id: "There are no rooms available that match your request.",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
<HotelCardListing hotelData={validHotels} />
|
||||
</div>
|
||||
<Suspense fallback={null}>
|
||||
<TrackingSDK
|
||||
pageData={pageTrackingData}
|
||||
hotelInfo={hotelsTrackingData}
|
||||
/>
|
||||
</Suspense>
|
||||
</main>
|
||||
</>
|
||||
<Suspense
|
||||
key={`${city.name}-${searchParams.fromDate}-${searchParams.toDate}-${adultsParams}-${childrenParams}`}
|
||||
fallback={<SelectHotelSkeleton />}
|
||||
>
|
||||
<SelectHotel
|
||||
city={city}
|
||||
params={params}
|
||||
reservationParams={reservationParams}
|
||||
/>
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Dayjs } from "dayjs"
|
||||
|
||||
import { dt } from "@/lib/dt"
|
||||
|
||||
import type { Dayjs } from "dayjs"
|
||||
|
||||
/**
|
||||
* 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")
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.container {
|
||||
width: var(--max-width-page);
|
||||
|
||||
grid-template-columns: 1fr 340px;
|
||||
grid-template-rows: auto 1fr;
|
||||
width: var(--max-width-page);
|
||||
margin: var(--Spacing-x5) auto 0;
|
||||
/* simulates padding on viewport smaller than --max-width-navigation */
|
||||
}
|
||||
|
||||
.content {
|
||||
|
||||
@@ -35,12 +35,11 @@ import EnterDetailsTracking from "./enterDetailsTracking"
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
|
||||
import { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import {
|
||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type {
|
||||
TrackingChannelEnum,
|
||||
TrackingSDKHotelInfo,
|
||||
TrackingSDKPageData,
|
||||
} from "@/types/components/tracking"
|
||||
TrackingSDKPageData} from "@/types/components/tracking";
|
||||
import { StepEnum } from "@/types/enums/step"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NextRequest, NextResponse } from "next/server"
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { AuthError } from "next-auth"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
@@ -117,7 +117,7 @@ export async function GET(
|
||||
/** Record<string, any> is next-auth typings */
|
||||
const params: Record<string, any> = {
|
||||
ui_locales: context.params.lang,
|
||||
scope: ["openid", "profile"],
|
||||
scope: ["openid", "profile", "booking"],
|
||||
/**
|
||||
* The `acr_values` param is used to make Curity display the proper login
|
||||
* page for Scandic. Without the parameter Curity presents some choices
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { NextRequest, NextResponse } from "next/server"
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { AuthError } from "next-auth"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
import { login } from "@/constants/routes/handleAuth"
|
||||
import { env } from "@/env/server"
|
||||
import { badRequest, internalServerError } from "@/server/errors/next"
|
||||
import { getPublicURL } from "@/server/utils"
|
||||
|
||||
import { signIn } from "@/auth"
|
||||
|
||||
import type { Lang } from "@/constants/languages"
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
context: { params: { lang: Lang } }
|
||||
|
||||
@@ -2,7 +2,7 @@ import { env } from "@/env/server"
|
||||
|
||||
import BookingWidget, { preload } from "@/components/BookingWidget"
|
||||
|
||||
import { PageArgs } from "@/types/params"
|
||||
import type { PageArgs } from "@/types/params"
|
||||
|
||||
export default async function BookingWidgetPage({
|
||||
searchParams,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import BookingWidget, { preload } from "@/components/BookingWidget"
|
||||
|
||||
import { PageArgs } from "@/types/params"
|
||||
import type { PageArgs } from "@/types/params"
|
||||
|
||||
export default async function BookingWidgetPage({
|
||||
searchParams,
|
||||
|
||||
@@ -4,7 +4,7 @@ import CurrentFooter from "@/components/Current/Footer"
|
||||
import Footer, { preload } from "@/components/Footer"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default function FooterSlot({ params }: PageArgs<LangParams>) {
|
||||
setLang(params.lang)
|
||||
|
||||
@@ -7,7 +7,7 @@ import HeaderFallback from "@/components/Current/Header/HeaderFallback"
|
||||
import Header from "@/components/Header"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default function HeaderPage({ params }: PageArgs<LangParams>) {
|
||||
setLang(params.lang)
|
||||
|
||||
@@ -16,7 +16,7 @@ import { findLang } from "@/utils/languages"
|
||||
|
||||
import styles from "./error.module.css"
|
||||
|
||||
import { LangParams } from "@/types/params"
|
||||
import type { LangParams } from "@/types/params"
|
||||
|
||||
export default function Error({
|
||||
error,
|
||||
|
||||
@@ -3,7 +3,6 @@ import "@scandic-hotels/design-system/style.css"
|
||||
|
||||
import Script from "next/script"
|
||||
|
||||
import { env } from "@/env/server"
|
||||
import TrpcProvider from "@/lib/trpc/Provider"
|
||||
|
||||
import TokenRefresher from "@/components/Auth/TokenRefresher"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import NotFound from "@/components/Current/NotFound"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
export default function NotFoundPage({ params }: PageArgs<LangParams>) {
|
||||
setLang(params.lang)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { LangParams, LayoutArgs, StatusParams } from "@/types/params"
|
||||
import type { LangParams, LayoutArgs, StatusParams } from "@/types/params"
|
||||
|
||||
export default function MiddlewareError({
|
||||
params,
|
||||
|
||||
Reference in New Issue
Block a user