feat: add multiroom signup

This commit is contained in:
Simon Emanuelsson
2025-02-17 15:10:48 +01:00
parent 95917e5e4f
commit 92c5566c59
78 changed files with 2035 additions and 1545 deletions

View File

@@ -1,6 +1,6 @@
"use client"
import { useRouter } from "next/navigation"
import { useTransition } from "react"
import { useState, useTransition } from "react"
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
@@ -39,6 +39,7 @@ export default function RateSummary({ isUserLoggedIn }: RateSummaryProps) {
searchParams: state.searchParams,
}))
const [isSubmitting, setIsSubmitting] = useState(false)
const intl = useIntl()
const router = useRouter()
const params = new URLSearchParams(searchParams)
@@ -111,6 +112,7 @@ export default function RateSummary({ isUserLoggedIn }: RateSummaryProps) {
function handleSubmit(e: React.FormEvent) {
e.preventDefault()
setIsSubmitting(true)
startTransition(() => {
router.push(`details?${params}`)
})
@@ -267,7 +269,7 @@ export default function RateSummary({ isUserLoggedIn }: RateSummaryProps) {
</div>
<Button
className={styles.continueButton}
disabled={!isAllRoomsSelected}
disabled={!isAllRoomsSelected || isSubmitting}
theme="base"
type="submit"
>

View File

@@ -1,5 +1,4 @@
"use client"
import { useSession } from "next-auth/react"
import { useIntl } from "react-intl"
import { useRatesStore } from "@/stores/select-rate"
@@ -12,19 +11,19 @@ import Chip from "@/components/TempDesignSystem/Chip"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { useRoomContext } from "@/contexts/Room"
import { isValidClientSession } from "@/utils/clientSession"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import styles from "./selectedRoomPanel.module.css"
export default function SelectedRoomPanel() {
const intl = useIntl()
const { data: session } = useSession()
const isUserLoggedIn = isValidClientSession(session)
const { rateDefinitions, roomCategories } = useRatesStore((state) => ({
rateDefinitions: state.roomsAvailability?.rateDefinitions,
roomCategories: state.roomCategories,
}))
const { isUserLoggedIn, rateDefinitions, roomCategories } = useRatesStore(
(state) => ({
isUserLoggedIn: state.isUserLoggedIn,
rateDefinitions: state.roomsAvailability?.rateDefinitions,
roomCategories: state.roomCategories,
})
)
const {
actions: { modifyRate },
isMainRoom,

View File

@@ -6,7 +6,7 @@ import { useRatesStore } from "@/stores/select-rate"
import { ChevronUpIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { useRoomContext } from "@/contexts/Room"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import SelectedRoomPanel from "./SelectedRoomPanel"
import { roomSelectionPanelVariants } from "./variants"

View File

@@ -1,14 +1,13 @@
import { useSearchParams } from "next/navigation"
import { useSession } from "next-auth/react"
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
import { useRatesStore } from "@/stores/select-rate"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { useRoomContext } from "@/contexts/Room"
import { isValidClientSession } from "@/utils/clientSession"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import { calculatePricesPerNight } from "./utils"
@@ -24,8 +23,7 @@ export default function PriceList({
}: PriceListProps) {
const intl = useIntl()
const { isMainRoom } = useRoomContext()
const { data: session } = useSession()
const isUserLoggedIn = isValidClientSession(session)
const isUserLoggedIn = useRatesStore((state) => state.isUserLoggedIn)
const { localPrice: publicLocalPrice, requestedPrice: publicRequestedPrice } =
publicPrice
@@ -166,20 +164,20 @@ export default function PriceList({
<Caption color="uiTextMediumContrast">
{isUserLoggedIn
? intl.formatMessage(
{ id: "{memberPrice} {currency}" },
{
memberPrice: totalMemberRequestedPricePerNight,
currency: publicRequestedPrice.currency,
}
)
{ id: "{memberPrice} {currency}" },
{
memberPrice: totalMemberRequestedPricePerNight,
currency: publicRequestedPrice.currency,
}
)
: intl.formatMessage(
{ id: "{publicPrice}/{memberPrice} {currency}" },
{
publicPrice: totalPublicRequestedPricePerNight,
memberPrice: totalMemberRequestedPricePerNight,
currency: publicRequestedPrice.currency,
}
)}
{ id: "{publicPrice}/{memberPrice} {currency}" },
{
publicPrice: totalPublicRequestedPricePerNight,
memberPrice: totalMemberRequestedPricePerNight,
currency: publicRequestedPrice.currency,
}
)}
</Caption>
</dd>
</div>

View File

@@ -1,15 +1,15 @@
"use client"
import { useSession } from "next-auth/react"
import { useIntl } from "react-intl"
import { useRatesStore } from "@/stores/select-rate"
import { CheckIcon, InfoCircleIcon } from "@/components/Icons"
import Modal from "@/components/Modal"
import Button from "@/components/TempDesignSystem/Button"
import Label from "@/components/TempDesignSystem/Form/Label"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import { useRoomContext } from "@/contexts/Room"
import { isValidClientSession } from "@/utils/clientSession"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import PriceTable from "./PriceList"
@@ -30,8 +30,7 @@ export default function FlexibilityOption({
rateTitle,
}: FlexibilityOptionProps) {
const intl = useIntl()
const { data: session } = useSession()
const isUserLoggedIn = isValidClientSession(session)
const isUserLoggedIn = useRatesStore((state) => state.isUserLoggedIn)
const {
actions: { selectRate },
isMainRoom,

View File

@@ -1,7 +1,6 @@
"use client"
import { useSearchParams } from "next/navigation"
import { useSession } from "next-auth/react"
import { createElement } from "react"
import { useIntl } from "react-intl"
@@ -15,8 +14,7 @@ import ImageGallery from "@/components/ImageGallery"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { useRoomContext } from "@/contexts/Room"
import { isValidClientSession } from "@/utils/clientSession"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { cardVariants } from "./cardVariants"
@@ -71,8 +69,6 @@ function getBreakfastMessage(
}
export default function RoomCard({ roomConfiguration }: RoomCardProps) {
const { data: session } = useSession()
const isUserLoggedIn = isValidClientSession(session)
const intl = useIntl()
const lessThanFiveRoomsLeft =
roomConfiguration.roomsLeft > 0 && roomConfiguration.roomsLeft < 5
@@ -83,12 +79,14 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
const {
hotelId,
hotelType,
isUserLoggedIn,
petRoomPackage,
rateDefinitions,
roomCategories,
} = useRatesStore((state) => ({
hotelId: state.booking.hotelId,
hotelType: state.hotelType,
isUserLoggedIn: state.isUserLoggedIn,
petRoomPackage: state.petRoomPackage,
rateDefinitions: state.roomsAvailability?.rateDefinitions,
roomCategories: state.roomCategories,
@@ -362,7 +360,7 @@ export default function RoomCard({ roomConfiguration }: RoomCardProps) {
product.productType.member?.rateCode !== undefined)
return (
<FlexibilityOption
key={product.productType.public.rateCode}
key={rate.title}
features={roomConfiguration.features}
isSelected={
isSelectedRateCode &&

View File

@@ -9,7 +9,7 @@ import { useIntl } from "react-intl"
import { useRatesStore } from "@/stores/select-rate"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import { useRoomContext } from "@/contexts/Room"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import styles from "./roomFilter.module.css"

View File

@@ -7,7 +7,7 @@ import { useBookingCodeFilterStore } from "@/stores/bookingCode-filter"
import BookingCodeFilter from "@/components/HotelReservation/SelectHotel/BookingCodeFilter"
import Alert from "@/components/TempDesignSystem/Alert"
import { useRoomContext } from "@/contexts/Room"
import { useRoomContext } from "@/contexts/SelectRate/Room"
import useLang from "@/hooks/useLang"
import RoomCard from "./RoomCard"

View File

@@ -3,7 +3,7 @@ import { useEffect } from "react"
import { useRatesStore } from "@/stores/select-rate"
import RoomProvider from "@/providers/RoomProvider"
import RoomProvider from "@/providers/SelectRate/RoomProvider"
import { trackLowestRoomPrice } from "@/utils/tracking"
import MultiRoomWrapper from "./MultiRoomWrapper"

View File

@@ -1,11 +1,8 @@
"use client"
import { useSession } from "next-auth/react"
import { dt } from "@/lib/dt"
import useLang from "@/hooks/useLang"
import RatesProvider from "@/providers/RatesProvider"
import { isValidClientSession } from "@/utils/clientSession"
import { useHotelPackages, useRoomsAvailability } from "../utils"
import RateSummary from "./RateSummary"
@@ -19,12 +16,11 @@ export function RoomsContainer({
booking,
childArray,
fromDate,
hotelId,
hotelData,
hotelId,
isUserLoggedIn,
toDate,
}: RoomsContainerProps) {
const { data: session } = useSession()
const isUserLoggedIn = isValidClientSession(session)
const lang = useLang()
const fromDateString = dt(fromDate).format("YYYY-MM-DD")