From d6fe6a33b404fcaf43583cd88c18909a80c20e9f Mon Sep 17 00:00:00 2001 From: Niclas Edenvin Date: Mon, 8 Jul 2024 11:06:58 +0200 Subject: [PATCH] feat(SW-70): create base for rate selection page This is the foundation for the rate selection. Since we don't have UX and UI ready yet this is on a best effort basis. Things that will be changed later includes proper API fetching, correct design, internationalization of text and form handling. --- .../hotelreservation/layout.module.css | 2 +- .../(public)/hotelreservation/layout.tsx | 9 +- .../select-rate/page.module.css | 41 +++++++ .../hotelreservation/select-rate/page.tsx | 114 ++++++++++++++++++ .../SelectRate/RoomCard/index.tsx | 42 +++++++ .../SelectRate/RoomCard/roomCard.module.css | 42 +++++++ .../SelectRate/RoomCard/roomCard.ts | 11 ++ .../TempDesignSystem/Text/Title/index.tsx | 7 ++ middlewares/bookingFlow.ts | 7 +- 9 files changed, 264 insertions(+), 11 deletions(-) create mode 100644 app/[lang]/(live)/(public)/hotelreservation/select-rate/page.module.css create mode 100644 app/[lang]/(live)/(public)/hotelreservation/select-rate/page.tsx create mode 100644 components/HotelReservation/SelectRate/RoomCard/index.tsx create mode 100644 components/HotelReservation/SelectRate/RoomCard/roomCard.module.css create mode 100644 components/HotelReservation/SelectRate/RoomCard/roomCard.ts diff --git a/app/[lang]/(live)/(public)/hotelreservation/layout.module.css b/app/[lang]/(live)/(public)/hotelreservation/layout.module.css index 8f162ce84..4478bdb18 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/layout.module.css +++ b/app/[lang]/(live)/(public)/hotelreservation/layout.module.css @@ -1,3 +1,3 @@ .layout { - height: 100vh; + min-height: 100dvh; } diff --git a/app/[lang]/(live)/(public)/hotelreservation/layout.tsx b/app/[lang]/(live)/(public)/hotelreservation/layout.tsx index 75fa8edd6..bf0fbed95 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/layout.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/layout.tsx @@ -7,12 +7,5 @@ import { LangParams, LayoutArgs } from "@/types/params" export default function HotelReservationLayout({ children, }: React.PropsWithChildren>) { - return ( -
- - Lorem, ipsum. - - {children} -
- ) + return
{children}
} diff --git a/app/[lang]/(live)/(public)/hotelreservation/select-rate/page.module.css b/app/[lang]/(live)/(public)/hotelreservation/select-rate/page.module.css new file mode 100644 index 000000000..e7f7cf928 --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/select-rate/page.module.css @@ -0,0 +1,41 @@ +.header { + margin-top: var(--Spacing-x2); + margin-bottom: var(--Spacing-x2); +} + +.hotelInfo { + margin-bottom: 64px; +} + +.page { + min-height: 100dvh; + padding-top: var(--Spacing-x6); + padding-left: var(--Spacing-x2); + padding-right: var(--Spacing-x2); + background-color: var(--Scandic-Brand-Warm-White); +} + +.content { + max-width: 1134px; + margin-left: auto; + margin-right: auto; +} + +.page input[type="radio"] { + opacity: 0; + position: fixed; + width: 0; +} + +.roomList { + margin-top: var(--Spacing-x4); + list-style: none; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + column-gap: var(--Spacing-x2); + row-gap: var(--Spacing-x4); +} + +.roomList > li { + width: 100%; +} diff --git a/app/[lang]/(live)/(public)/hotelreservation/select-rate/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/select-rate/page.tsx new file mode 100644 index 000000000..6649762d9 --- /dev/null +++ b/app/[lang]/(live)/(public)/hotelreservation/select-rate/page.tsx @@ -0,0 +1,114 @@ +import RoomCard from "@/components/HotelReservation/SelectRate/RoomCard" +import { Room } from "@/components/HotelReservation/SelectRate/RoomCard/roomCard" +import Header from "@/components/Section/Header" + +import styles from "./page.module.css" + +const getRooms: () => Promise = () => { + return new Promise((resolve) => + resolve([ + { + id: 1, + name: "Cabin", + description: + "Stylish, peaceful and air-conditioned room. The rooms have small clerestory windows.", + size: "17 - 24 m² (1 - 2 persons)", + pricePerNight: 1348, + currency: "SEK", + imageSrc: + "https://www.scandichotels.se/imageVault/publishedmedia/xnmqnmz6mz0uhuat0917/scandic-helsinki-hub-room-standard-KR-7.jpg", + }, + { + id: 2, + name: "Standard", + description: + "Stylish, peaceful and air-conditioned room. The rooms have small clerestory windows.", + size: "19 - 30 m² (1 - 2 persons)", + pricePerNight: 1548, + currency: "SEK", + imageSrc: + "https://www.scandichotels.se/imageVault/publishedmedia/xnmqnmz6mz0uhuat0917/scandic-helsinki-hub-room-standard-KR-7.jpg", + }, + { + id: 3, + name: "Superior", + description: + "Stylish, peaceful and air-conditioned room. The rooms have small clerestory windows.", + size: "22 - 40 m² (1 - 3 persons)", + pricePerNight: 1744, + currency: "SEK", + imageSrc: + "https://www.scandichotels.se/imageVault/publishedmedia/xnmqnmz6mz0uhuat0917/scandic-helsinki-hub-room-standard-KR-7.jpg", + }, + { + id: 4, + name: "Superior Family", + description: + "Stylish, peaceful and air-conditioned room. The rooms have small clerestory windows.", + size: "29 - 49 m² (3 - 4 persons)", + pricePerNight: 2032, + currency: "SEK", + imageSrc: + "https://www.scandichotels.se/imageVault/publishedmedia/xnmqnmz6mz0uhuat0917/scandic-helsinki-hub-room-standard-KR-7.jpg", + }, + { + id: 5, + name: "Superior PLUS", + description: + "Stylish, peaceful and air-conditioned room. The rooms have small clerestory windows.", + size: "21 - 28 m² (2 - 3 persons)", + pricePerNight: 2065, + currency: "SEK", + imageSrc: + "https://www.scandichotels.se/imageVault/publishedmedia/xnmqnmz6mz0uhuat0917/scandic-helsinki-hub-room-standard-KR-7.jpg", + }, + { + id: 6, + name: "Junior Suite", + description: + "Stylish, peaceful and air-conditioned room. The rooms have small clerestory windows.", + size: "35 - 43 m² (2 - 4 persons)", + pricePerNight: 3012, + currency: "SEK", + imageSrc: + "https://www.scandichotels.se/imageVault/publishedmedia/xnmqnmz6mz0uhuat0917/scandic-helsinki-hub-room-standard-KR-7.jpg", + }, + ]) + ) +} + +export default async function SelectRate() { + const rooms = await getRooms() + + return ( +
+
+
Hotel info TBI
+
+
+
+ +
    + {rooms.map((room) => ( +
  • + + +
  • + ))} +
+
+
+ ) +} diff --git a/components/HotelReservation/SelectRate/RoomCard/index.tsx b/components/HotelReservation/SelectRate/RoomCard/index.tsx new file mode 100644 index 000000000..8c20ffb4a --- /dev/null +++ b/components/HotelReservation/SelectRate/RoomCard/index.tsx @@ -0,0 +1,42 @@ +import Button from "@/components/TempDesignSystem/Button" +import Caption from "@/components/TempDesignSystem/Text/Caption" +import Title from "@/components/TempDesignSystem/Text/Title" + +import { RoomProps } from "./roomCard" + +import styles from "./roomCard.module.css" + +export default function RoomCard({ room }: RoomProps) { + return ( +
+
+
+ + {room.name} + +
i
+
+ 17 - 24 m² (1 - 2 persons) + {room.description} + + + From {room.pricePerNight}{" "} + {room.currency}/night + + + +
+ {/* TODO: maybe use the `Image` component instead of the `img` tag. Waiting until we know how to get the image */} + {/* eslint-disable-next-line @next/next/no-img-element */} + A photo of the room +
+ ) +} diff --git a/components/HotelReservation/SelectRate/RoomCard/roomCard.module.css b/components/HotelReservation/SelectRate/RoomCard/roomCard.module.css new file mode 100644 index 000000000..e7f137a65 --- /dev/null +++ b/components/HotelReservation/SelectRate/RoomCard/roomCard.module.css @@ -0,0 +1,42 @@ +.card { + font-size: 14px; + text-align: center; + display: flex; + flex-direction: column-reverse; + background-color: #fff; + border-radius: 4px; + border: 1px solid rgba(77, 0, 27, 0.1); +} + +.cardBody { + padding: var(--Spacing-x2); + display: flex; + flex-direction: column; + gap: var(--Spacing-x1); +} + +.nameContainer { +} + +.name { + display: inline-block; +} +.nameInfo { + float: right; +} + +.price { + font-size: 24px; + font-weight: 600; + text-align: center; +} + +.card .button { + display: inline; +} + +.card img { + max-width: 100%; + aspect-ratio: 2.45; + object-fit: cover; +} diff --git a/components/HotelReservation/SelectRate/RoomCard/roomCard.ts b/components/HotelReservation/SelectRate/RoomCard/roomCard.ts new file mode 100644 index 000000000..c42f9304e --- /dev/null +++ b/components/HotelReservation/SelectRate/RoomCard/roomCard.ts @@ -0,0 +1,11 @@ +export type Room = { + id: number + name: string + description: string + size: string + pricePerNight: number + currency: string + imageSrc: string +} + +export type RoomProps = { room: Room } diff --git a/components/TempDesignSystem/Text/Title/index.tsx b/components/TempDesignSystem/Text/Title/index.tsx index d43d28cb4..7e36829b7 100644 --- a/components/TempDesignSystem/Text/Title/index.tsx +++ b/components/TempDesignSystem/Text/Title/index.tsx @@ -4,10 +4,17 @@ import { headingVariants } from "./variants" import type { HeadingProps } from "./title" export default function Title({ + /** + * What styling to use, based on heading level. If not provided `level` + * will determine the styling. + */ as, children, className = "", color, + /** + * What HTML tag to use. Defaults to h1. + */ level = "h1", textAlign, textTransform, diff --git a/middlewares/bookingFlow.ts b/middlewares/bookingFlow.ts index 88d820df7..79d9f0737 100644 --- a/middlewares/bookingFlow.ts +++ b/middlewares/bookingFlow.ts @@ -1,6 +1,8 @@ import { NextResponse } from "next/server" -import { bookingFlow } from "@/constants/routes/hotelReservation" +import { hotelReservation } from "@/constants/routes/hotelReservation" + +import { findLang } from "@/utils/languages" import type { NextMiddleware } from "next/server" @@ -11,5 +13,6 @@ export const middleware: NextMiddleware = () => { } export const matcher: MiddlewareMatcher = (request) => { - return bookingFlow.includes(request.nextUrl.pathname) + const lang = findLang(request.nextUrl.pathname)! + return request.nextUrl.pathname.startsWith(hotelReservation[lang]) }