Merge branch 'develop' into feature/tracking

This commit is contained in:
Linus Flood
2024-10-15 07:46:54 +02:00
209 changed files with 4413 additions and 1046 deletions

View File

@@ -1,5 +1,4 @@
.layout {
background-color: var(--Base-Background-Primary-Normal);
display: grid;
font-family: var(--typography-Body-Regular-fontFamily);
gap: var(--Spacing-x3);
@@ -9,6 +8,10 @@
margin: 0 auto;
}
.container {
background-color: var(--Base-Background-Primary-Normal);
}
.content {
display: grid;
padding-bottom: var(--Spacing-x9);

View File

@@ -9,12 +9,14 @@ export default async function MyPagesLayout({
breadcrumbs: React.ReactNode
}>) {
return (
<section className={styles.layout}>
{breadcrumbs}
<section className={styles.content}>
<Sidebar />
{children}
<div className={styles.container}>
<section className={styles.layout}>
{breadcrumbs}
<section className={styles.content}>
<Sidebar />
{children}
</section>
</section>
</section>
</div>
)
}

View File

@@ -1,10 +1,11 @@
.layout {
background-color: var(--Base-Background-Primary-Normal);
display: grid;
font-family: var(--typography-Body-Regular-fontFamily);
gap: var(--Spacing-x3);
grid-template-rows: auto 1fr;
position: relative;
max-width: var(--max-width);
margin: 0 auto;
}
.container {
background-color: var(--Base-Background-Primary-Normal);
}

View File

@@ -16,9 +16,11 @@ export default function ContentTypeLayout({
}
>) {
return (
<section className={styles.layout}>
{breadcrumbs}
{children}
</section>
<div className={styles.container}>
<section className={styles.layout}>
{breadcrumbs}
{children}
</section>
</div>
)
}

View File

@@ -9,8 +9,12 @@
grid-template-columns: 1fr 340px;
grid-template-rows: auto 1fr;
margin: var(--Spacing-x5) auto 0;
max-width: var(--max-width-navigation);
padding: var(--Spacing-x6) var(--Spacing-x2) 0;
padding-top: var(--Spacing-x6);
/* simulates padding on viewport smaller than --max-width-navigation */
width: min(
calc(100dvw - (var(--Spacing-x2) * 2)),
var(--max-width-navigation)
);
}
.summary {

View File

@@ -2,18 +2,22 @@ import { redirect } from "next/navigation"
import { serverClient } from "@/lib/trpc/server"
import EnterDetailsProvider from "@/components/HotelReservation/EnterDetails/Provider"
import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom"
import Summary from "@/components/HotelReservation/EnterDetails/Summary"
import HotelSelectionHeader from "@/components/HotelReservation/HotelSelectionHeader"
import Summary from "@/components/HotelReservation/SelectRate/Summary"
import { setLang } from "@/i18n/serverContext"
import styles from "./layout.module.css"
import { StepEnum } from "@/types/components/enterDetails/step"
import type { LangParams, LayoutArgs } from "@/types/params"
export default async function StepLayout({
children,
params,
}: React.PropsWithChildren<LayoutArgs<LangParams>>) {
}: React.PropsWithChildren<LayoutArgs<LangParams & { step: StepEnum }>>) {
setLang(params.lang)
const hotel = await serverClient().hotel.hotelData.get({
hotelId: "811",
language: params.lang,
@@ -24,15 +28,17 @@ export default async function StepLayout({
}
return (
<main className={styles.layout}>
<HotelSelectionHeader hotel={hotel.data.attributes} />
<div className={styles.content}>
<SelectedRoom />
{children}
<aside className={styles.summary}>
<Summary />
</aside>
</div>
</main>
<EnterDetailsProvider step={params.step}>
<main className={styles.layout}>
<HotelSelectionHeader hotel={hotel.data.attributes} />
<div className={styles.content}>
<SelectedRoom />
{children}
<aside className={styles.summary}>
<Summary />
</aside>
</div>
</main>
</EnterDetailsProvider>
)
}

View File

@@ -1,110 +1,67 @@
"use client"
import { notFound } from "next/navigation"
import { useState } from "react"
import { useIntl } from "react-intl"
import { trpc } from "@/lib/trpc/client"
import { getProfileSafely } from "@/lib/trpc/memoizedRequests"
import { serverClient } from "@/lib/trpc/server"
import BedType from "@/components/HotelReservation/EnterDetails/BedType"
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
import Details from "@/components/HotelReservation/EnterDetails/Details"
import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion"
import Payment from "@/components/HotelReservation/SelectRate/Payment"
import SectionAccordion from "@/components/HotelReservation/SelectRate/SectionAccordion"
import LoadingSpinner from "@/components/LoadingSpinner"
import { getIntl } from "@/i18n"
import { StepEnum } from "@/types/components/enterDetails/step"
import type { LangParams, PageArgs } from "@/types/params"
enum StepEnum {
selectBed = "select-bed",
breakfast = "breakfast",
details = "details",
payment = "payment",
}
function isValidStep(step: string): step is StepEnum {
return Object.values(StepEnum).includes(step as StepEnum)
}
export default function StepPage({
export default async function StepPage({
params,
}: PageArgs<LangParams & { step: StepEnum }>) {
const { step } = params
const [activeStep, setActiveStep] = useState<StepEnum>(step)
const intl = useIntl()
const { step, lang } = params
if (!isValidStep(activeStep)) {
const intl = await getIntl()
const hotel = await serverClient().hotel.hotelData.get({
hotelId: "811",
language: lang,
})
const user = await getProfileSafely()
if (!isValidStep(step) || !hotel) {
return notFound()
}
const { data: hotel, isLoading: loadingHotel } =
trpc.hotel.hotelData.get.useQuery({
hotelId: "811",
language: params.lang,
})
if (loadingHotel) {
return <LoadingSpinner />
}
if (!hotel) {
// TODO: handle case with hotel missing
return notFound()
}
switch (activeStep) {
case StepEnum.breakfast:
//return <div>Select BREAKFAST</div>
case StepEnum.details:
//return <div>Select DETAILS</div>
case StepEnum.payment:
//return <div>Select PAYMENT</div>
case StepEnum.selectBed:
// return <div>Select BED</div>
}
function onNav(step: StepEnum) {
setActiveStep(step)
if (typeof window !== "undefined") {
window.history.pushState({}, "", step)
}
}
return (
<section>
<SectionAccordion
header="Select bed"
isCompleted={true}
isOpen={activeStep === StepEnum.selectBed}
step={StepEnum.selectBed}
label={intl.formatMessage({ id: "Request bedtype" })}
path="/select-bed"
>
<BedType />
</SectionAccordion>
<SectionAccordion
header="Food options"
isCompleted={true}
isOpen={activeStep === StepEnum.breakfast}
step={StepEnum.breakfast}
label={intl.formatMessage({ id: "Select breakfast options" })}
path="/breakfast"
>
<Breakfast />
</SectionAccordion>
<SectionAccordion
header="Details"
isCompleted={false}
isOpen={activeStep === StepEnum.details}
step={StepEnum.details}
label={intl.formatMessage({ id: "Enter your details" })}
path="/details"
>
<Details user={null} />
<Details user={user} />
</SectionAccordion>
<SectionAccordion
header="Payment"
isCompleted={false}
isOpen={activeStep === StepEnum.payment}
step={StepEnum.payment}
label={intl.formatMessage({ id: "Select payment method" })}
path="/hotelreservation/select-bed"
>
<Payment hotel={hotel.data.attributes} />
</SectionAccordion>

View File

@@ -4,6 +4,8 @@
padding: var(--Spacing-x4);
background-color: var(--Scandic-Brand-Warm-White);
min-height: 100dvh;
max-width: var(--max-width);
margin: 0 auto;
}
.section {
@@ -11,10 +13,4 @@
flex-direction: column;
gap: var(--Spacing-x4);
width: 100%;
max-width: 365px;
}
@media screen and (min-width: 1367px) {
.section {
max-width: 525px;
}
}

View File

@@ -1,6 +1,4 @@
.layout {
min-height: 100dvh;
max-width: var(--max-width);
margin: 0 auto;
background-color: var(--Base-Background-Primary-Normal);
}

View File

@@ -4,6 +4,9 @@
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 {
@@ -15,3 +18,9 @@
display: flex;
padding: var(--Spacing-x2) var(--Spacing-x0);
}
@media (min-width: 768px) {
.main {
flex-direction: row;
}
}

View File

@@ -7,13 +7,12 @@
}
.content {
max-width: 1134px;
margin-top: var(--Spacing-x5);
margin-left: auto;
margin-right: auto;
max-width: var(--max-width);
margin: 0 auto;
display: flex;
justify-content: space-between;
flex-direction: column;
gap: var(--Spacing-x7);
padding: var(--Spacing-x2);
}
.main {

View File

@@ -15,8 +15,11 @@ export default async function SelectRatePage({
}: PageArgs<LangParams & { section: string }, SelectRateSearchParams>) {
setLang(params.lang)
// TODO: Use real endpoint.
const hotel = tempHotelData.data.attributes
const hotelData = await serverClient().hotel.hotelData.get({
hotelId: searchParams.hotel,
language: params.lang,
include: ["RoomCategories"],
})
const roomConfigurations = await serverClient().hotel.availability.rooms({
hotelId: parseInt(searchParams.hotel, 10),
@@ -24,18 +27,27 @@ export default async function SelectRatePage({
roomStayEndDate: "2024-11-03",
adults: 1,
})
if (!roomConfigurations) {
return "No rooms found"
return "No rooms found" // TODO: Add a proper error message
}
if (!hotelData) {
return "No hotel data found" // TODO: Add a proper error message
}
const roomCategories = hotelData?.included
return (
<div>
{/* TODO: Add Hotel Listing Card */}
<div>Hotel Listing Card TBI</div>
<div className={styles.content}>
{/* TODO: Add Hotel Listing Card */}
<div>Hotel Listing Card TBI</div>
<div className={styles.main}>
<RoomSelection roomConfigurations={roomConfigurations} />
<RoomSelection
roomConfigurations={roomConfigurations}
roomCategories={roomCategories ?? []}
/>
</div>
</div>
</div>