feat: booking confirmation page with hardcoded data

This commit is contained in:
Simon Emanuelsson
2024-10-22 11:43:08 +02:00
parent 445bde8e2e
commit 2d23f9bbf3
42 changed files with 859 additions and 533 deletions

View File

@@ -0,0 +1,6 @@
.main {
display: grid;
background-color: var(--Scandic-Brand-Warm-White);
min-height: 100dvh;
grid-template-columns: 420px 1fr;
}

View File

@@ -0,0 +1,58 @@
import { env } from "@/env/server"
import {
fetchAvailableHotels,
getFiltersFromHotels,
} from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils"
import SelectHotelMap from "@/components/HotelReservation/SelectHotel/SelectHotelMap"
import { setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
import {
PointOfInterest,
PointOfInterestCategoryNameEnum,
PointOfInterestGroupEnum,
} from "@/types/hotel"
import { LangParams, PageArgs } from "@/types/params"
export default async function SelectHotelMapPage({
params,
}: PageArgs<LangParams, {}>) {
const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID
const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY
setLang(params.lang)
const hotels = await fetchAvailableHotels({
cityId: "8ec4bba3-1c38-4606-82d1-bbe3f6738e54",
roomStayStartDate: "2024-11-02",
roomStayEndDate: "2024-11-03",
adults: 1,
})
const filters = getFiltersFromHotels(hotels)
// TODO: this is just a quick transformation to get something there. May need rework
const pointOfInterests: PointOfInterest[] = hotels.map((hotel) => ({
coordinates: {
lat: hotel.hotelData.location.latitude,
lng: hotel.hotelData.location.longitude,
},
name: hotel.hotelData.name,
distance: hotel.hotelData.location.distanceToCentre,
categoryName: PointOfInterestCategoryNameEnum.HOTEL,
group: PointOfInterestGroupEnum.LOCATION,
}))
return (
<main className={styles.main}>
<SelectHotelMap
apiKey={googleMapsApiKey}
// TODO: use correct coordinates. The city center?
coordinates={{ lat: 59.32, lng: 18.01 }}
pointsOfInterest={pointOfInterests}
mapId={googleMapId}
/>
</main>
)
}

View File

@@ -0,0 +1,26 @@
.main {
display: flex;
gap: var(--Spacing-x4);
padding: var(--Spacing-x4) var(--Spacing-x4) 0 var(--Spacing-x4);
background-color: var(--Scandic-Brand-Warm-White);
min-height: 100dvh;
flex-direction: column;
max-width: var(--max-width);
margin: 0 auto;
}
.section {
display: flex;
flex-direction: column;
}
.link {
display: flex;
padding: var(--Spacing-x2) var(--Spacing-x0);
}
@media (min-width: 768px) {
.main {
flex-direction: row;
}
}

View File

@@ -0,0 +1,63 @@
import { selectHotelMap } from "@/constants/routes/hotelReservation"
import {
fetchAvailableHotels,
getFiltersFromHotels,
} from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils"
import HotelCardListing from "@/components/HotelReservation/HotelCardListing"
import HotelFilter from "@/components/HotelReservation/SelectHotel/HotelFilter"
import { ChevronRightIcon } from "@/components/Icons"
import StaticMap from "@/components/Maps/StaticMap"
import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
import { LangParams, PageArgs } from "@/types/params"
export default async function SelectHotelPage({
params,
}: PageArgs<LangParams>) {
setLang(params.lang)
const tempSearchTerm = "Stockholm"
const intl = await getIntl()
const hotels = await fetchAvailableHotels({
cityId: "8ec4bba3-1c38-4606-82d1-bbe3f6738e54",
roomStayStartDate: "2024-11-02",
roomStayEndDate: "2024-11-03",
adults: 1,
})
const filterList = getFiltersFromHotels(hotels)
return (
<main className={styles.main}>
<section className={styles.section}>
<Link href={selectHotelMap[params.lang]} keepSearchParams>
<StaticMap
city={tempSearchTerm}
width={340}
height={180}
zoomLevel={11}
mapType="roadmap"
altText={`Map of ${tempSearchTerm} city center`}
/>
</Link>
<Link
className={styles.link}
color="burgundy"
href={selectHotelMap[params.lang]}
keepSearchParams
>
{intl.formatMessage({ id: "Show map" })}
<ChevronRightIcon color="burgundy" />
</Link>
<HotelFilter filters={filterList} />
</section>
<HotelCardListing hotelData={hotels} />
</main>
)
}

View File

@@ -0,0 +1,43 @@
import { serverClient } from "@/lib/trpc/server"
import { getLang } from "@/i18n/serverContext"
import { AvailabilityInput } from "@/types/components/hotelReservation/selectHotel/availabilityInput"
import { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import { Filter } from "@/types/components/hotelReservation/selectHotel/hotelFilters"
export async function fetchAvailableHotels(
input: AvailabilityInput
): Promise<HotelData[]> {
const availableHotels = await serverClient().hotel.availability.hotels(input)
if (!availableHotels) throw new Error()
const language = getLang()
const hotels = availableHotels.availability.map(async (hotel) => {
const hotelData = await serverClient().hotel.hotelData.get({
hotelId: hotel.hotelId.toString(),
language,
})
if (!hotelData) throw new Error()
return {
hotelData: hotelData.data.attributes,
price: hotel.bestPricePerNight,
}
})
return await Promise.all(hotels)
}
export function getFiltersFromHotels(hotels: HotelData[]) {
const filters = hotels.flatMap((hotel) => hotel.hotelData.detailedFacilities)
const uniqueFilterIds = [...new Set(filters.map((filter) => filter.id))]
const filterList: Filter[] = uniqueFilterIds
.map((filterId) => filters.find((filter) => filter.id === filterId))
.filter((filter): filter is Filter => filter !== undefined)
return filterList
}