feat(sw-452): Implement select room form submit

This commit is contained in:
Pontus Dreij
2024-10-15 15:48:23 +02:00
parent 3a3491c534
commit fd3cd053a2
7 changed files with 101 additions and 20 deletions

View File

@@ -18,6 +18,7 @@ export default function FlexibilityOption({
paymentTerm, paymentTerm,
priceInformation, priceInformation,
roomType, roomType,
roomTypeCode,
handleSelectRate, handleSelectRate,
}: FlexibilityOptionProps) { }: FlexibilityOptionProps) {
const [rootDiv, setRootDiv] = useState<Element | undefined>(undefined) const [rootDiv, setRootDiv] = useState<Element | undefined>(undefined)
@@ -46,6 +47,7 @@ export default function FlexibilityOption({
function onChange() { function onChange() {
const rate = { const rate = {
roomTypeCode: roomTypeCode,
roomType: roomType, roomType: roomType,
priceName: name, priceName: name,
public: publicPrice, public: publicPrice,

View File

@@ -24,17 +24,15 @@ export default function RateSummary({
</div> </div>
<div className={styles.summaryPrice}> <div className={styles.summaryPrice}>
<div className={styles.summaryPriceText}> <div className={styles.summaryPriceText}>
<> <Subtitle color={isUserLoggedIn ? "red" : "uiTextHighContrast"}>
<Subtitle color={isUserLoggedIn ? "red" : "uiTextHighContrast"}> {priceToShow?.localPrice.pricePerStay}{" "}
{priceToShow?.localPrice.pricePerStay}{" "} {priceToShow?.localPrice.currency}
{priceToShow?.localPrice.currency} </Subtitle>
</Subtitle> <Body color="uiTextMediumContrast">
<Body color="uiTextMediumContrast"> {intl.formatMessage({ id: "Approx." })}{" "}
{intl.formatMessage({ id: "Approx." })}{" "} {priceToShow?.requestedPrice?.pricePerStay}{" "}
{priceToShow?.requestedPrice?.pricePerStay}{" "} {priceToShow?.requestedPrice?.currency}
{priceToShow?.requestedPrice?.currency} </Body>
</Body>
</>
</div> </div>
<Button type="submit" theme="base"> <Button type="submit" theme="base">
{intl.formatMessage({ id: "Continue" })} {intl.formatMessage({ id: "Continue" })}

View File

@@ -116,6 +116,7 @@ export default function RoomCard({
priceInformation={getPriceForRate(saveRate)} priceInformation={getPriceForRate(saveRate)}
handleSelectRate={handleSelectRate} handleSelectRate={handleSelectRate}
roomType={roomConfiguration.roomType} roomType={roomConfiguration.roomType}
roomTypeCode={roomConfiguration.roomTypeCode}
/> />
<FlexibilityOption <FlexibilityOption
name={intl.formatMessage({ id: "Free rebooking" })} name={intl.formatMessage({ id: "Free rebooking" })}
@@ -125,6 +126,7 @@ export default function RoomCard({
priceInformation={getPriceForRate(changeRate)} priceInformation={getPriceForRate(changeRate)}
handleSelectRate={handleSelectRate} handleSelectRate={handleSelectRate}
roomType={roomConfiguration.roomType} roomType={roomConfiguration.roomType}
roomTypeCode={roomConfiguration.roomTypeCode}
/> />
<FlexibilityOption <FlexibilityOption
name={intl.formatMessage({ id: "Free cancellation" })} name={intl.formatMessage({ id: "Free cancellation" })}
@@ -134,6 +136,7 @@ export default function RoomCard({
priceInformation={getPriceForRate(flexRate)} priceInformation={getPriceForRate(flexRate)}
handleSelectRate={handleSelectRate} handleSelectRate={handleSelectRate}
roomType={roomConfiguration.roomType} roomType={roomConfiguration.roomType}
roomTypeCode={roomConfiguration.roomTypeCode}
/> />
</div> </div>
</div> </div>

View File

@@ -4,6 +4,7 @@ import { useState } from "react"
import RateSummary from "./RateSummary" import RateSummary from "./RateSummary"
import RoomCard from "./RoomCard" import RoomCard from "./RoomCard"
import { getHotelReservationQueryParams } from "./utils"
import styles from "./roomSelection.module.css" import styles from "./roomSelection.module.css"
@@ -19,12 +20,43 @@ export default function RoomSelection({
const router = useRouter() const router = useRouter()
const searchParams = useSearchParams() const searchParams = useSearchParams()
const isUserLoggedIn = !!user
function handleSubmit(e: React.FormEvent<HTMLFormElement>) { function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault() e.preventDefault()
const searchParamsObject = getHotelReservationQueryParams(searchParams)
/**
* These are the query params that are used on current web and should come from the Booking Widget Search Submit.
* Might need to be changed when Search Submit in the Booking Widget is implemented.
*/
const queryParams = new URLSearchParams(searchParams) const queryParams = new URLSearchParams(searchParams)
queryParams.set("roomClass", e.currentTarget.roomClass?.value)
queryParams.set("flexibility", e.currentTarget.flexibility?.value) searchParamsObject.room.forEach((item, index) => {
queryParams.set(`room[${index}].adults`, item.adults.toString())
if (Array.isArray(item.child)) {
item.child.forEach((child, childIndex) => {
queryParams.set(
`room[${index}].child[${childIndex}].age`,
child.age.toString()
)
queryParams.set(`room[${index}].child[${childIndex}].bed`, child.bed)
})
}
queryParams.set(
`room[${index}].roomtypecode`,
rateSummary?.roomTypeCode || ""
)
queryParams.set(
`room[${index}].ratecode`,
isUserLoggedIn
? rateSummary?.member?.rateCode || ""
: rateSummary?.public?.rateCode || ""
)
})
router.push(`select-bed?${queryParams}`) router.push(`select-bed?${queryParams}`)
} }
@@ -48,7 +80,10 @@ export default function RoomSelection({
))} ))}
</ul> </ul>
{rateSummary && ( {rateSummary && (
<RateSummary rateSummary={rateSummary} isUserLoggedIn={!!user} /> <RateSummary
rateSummary={rateSummary}
isUserLoggedIn={isUserLoggedIn}
/>
)} )}
</form> </form>
</div> </div>

View File

@@ -0,0 +1,23 @@
import { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
function getHotelReservationQueryParams(searchParams: URLSearchParams) {
const searchParamsObject: SelectRateSearchParams = Array.from(
searchParams.entries()
).reduce((acc, [key, value]) => {
const keys = key.replace(/\]/g, "").split(/\[|\./) // Split keys by '[' or '.'
keys.reduce((nestedAcc, k, i) => {
if (i === keys.length - 1) {
nestedAcc[k] = value // Assign value at the last key
} else {
if (!nestedAcc[k]) {
nestedAcc[k] = isNaN(Number(keys[i + 1])) ? {} : [] // Initialize as array or object
}
}
return nestedAcc[k]
}, acc)
return acc
}, {} as SelectRateSearchParams)
return searchParamsObject
}
export { getHotelReservationQueryParams }

View File

@@ -1,6 +1,10 @@
import { z } from "zod" import { z } from "zod"
import { Product, productTypePriceSchema } from "@/server/routers/hotels/output" import {
Product,
productTypePriceSchema,
RoomConfiguration,
} from "@/server/routers/hotels/output"
import { Rate } from "./selectRate" import { Rate } from "./selectRate"
@@ -12,7 +16,8 @@ export type FlexibilityOptionProps = {
value: string value: string
paymentTerm: string paymentTerm: string
priceInformation?: Array<string> priceInformation?: Array<string>
roomType: string roomType: RoomConfiguration["roomType"]
roomTypeCode: RoomConfiguration["roomTypeCode"]
handleSelectRate: (rate: Rate) => void handleSelectRate: (rate: Rate) => void
} }

View File

@@ -1,13 +1,28 @@
import { Product } from "@/server/routers/hotels/output" import { Product, RoomConfiguration } from "@/server/routers/hotels/output"
interface Child {
bed: string
age: number
}
interface Room {
adults: number
roomtypecode: string
ratecode: string
child: Child[]
}
export interface SelectRateSearchParams { export interface SelectRateSearchParams {
fromDate: string
toDate: string
hotel: string hotel: string
fromdate: string
todate: string
room: Room[]
[key: string]: any
} }
export interface Rate { export interface Rate {
roomType: string roomType: RoomConfiguration["roomType"]
roomTypeCode: RoomConfiguration["roomTypeCode"]
priceName: string priceName: string
public: Product["productType"]["public"] public: Product["productType"]["public"]
member: Product["productType"]["member"] member: Product["productType"]["member"]