Merge remote-tracking branch 'origin' into feat/tracking-payment

This commit is contained in:
Linus Flood
2025-01-10 09:13:04 +01:00
111 changed files with 2371 additions and 875 deletions

View File

@@ -65,9 +65,6 @@ export default function RoomFilter({
const tooltipText = intl.formatMessage({
id: "Pet-friendly rooms have an additional fee of 20 EUR per stay",
})
const showTooltip = isAboveMobile && petFriendly
const submitFilter = useCallback(() => {
const data = getValues()
onFilter(data)
@@ -94,19 +91,14 @@ export default function RoomFilter({
</div>
<div className={styles.infoMobile}>
<div className={styles.filterInfo}>
{!isAboveMobile ? (
<Tooltip
text={tooltipText}
position="bottom"
arrow="left"
isTouchable
>
<InfoCircleIcon
color="uiTextHighContrast"
height={20}
width={20}
/>
<Tooltip
text={tooltipText}
position="bottom"
arrow="left"
isTouchable
>
<InfoCircleIcon color="uiTextHighContrast" height={20} width={20} />
<div className={styles.filter}>
<Caption
type="label"
color="baseTextMediumContrast"
@@ -114,30 +106,14 @@ export default function RoomFilter({
>
{intl.formatMessage({ id: "Filter" })}
</Caption>
<Caption type="label" color="baseTextMediumContrast">
<Caption type="regular" color="baseTextMediumContrast">
{Object.entries(selectedFilters)
.filter(([_, value]) => value)
.map(([key]) => intl.formatMessage({ id: key }))
.join(", ")}
</Caption>
</Tooltip>
) : (
<>
<Caption
type="label"
color="baseTextMediumContrast"
textTransform="uppercase"
>
{intl.formatMessage({ id: "Filter" })}
</Caption>
<Caption type="label" color="baseTextMediumContrast">
{Object.entries(selectedFilters)
.filter(([_, value]) => value)
.map(([key]) => intl.formatMessage({ id: key }))
.join(", ")}
</Caption>
</>
)}
</div>
</Tooltip>
</div>
<Caption color="uiTextHighContrast">
{intl.formatMessage(
@@ -170,12 +146,13 @@ export default function RoomFilter({
/>
)
return showTooltip ? (
return isPetRoom && isAboveMobile ? (
<Tooltip
key={option.code}
text={tooltipText}
position="bottom"
arrow="right"
isTouchable
>
{checkboxChip}
</Tooltip>

View File

@@ -12,6 +12,13 @@
align-items: center;
}
.filter {
display: flex;
gap: var(--Spacing-x-half);
margin-left: var(--Spacing-x-half);
align-items: baseline;
}
.filterInfo {
display: flex;
flex-direction: row;

View File

@@ -77,24 +77,15 @@ input[type="radio"]:checked + .card .checkIcon {
margin: 0 auto var(--Spacing-x2);
}
.popover {
background-color: var(--Main-Grey-White);
border-radius: var(--Corner-radius-Medium);
left: 0px;
max-height: 400px;
padding: var(--Spacing-x2);
top: calc(55px + var(--Spacing-x1));
width: 100%;
box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1);
.terms {
margin-top: var(--Spacing-x3);
margin-bottom: var(--Spacing-x3);
}
.popover section:focus-visible {
outline: none;
}
.popover .popoverText {
margin-bottom: var(--Spacing-x-half);
}
.popover .popoverHeading {
.termsText:nth-child(n) {
display: flex;
align-items: center;
margin-bottom: var(--Spacing-x1);
font-weight: 600; /* TODO: Remove when this is updated in Design system */
}
.termsIcon {
margin-right: var(--Spacing-x1);
}

View File

@@ -4,9 +4,11 @@ import { useSearchParams } from "next/navigation"
import { useEffect, useRef } from "react"
import { useIntl } from "react-intl"
import { CheckIcon, InfoCircleIcon } from "@/components/Icons"
import { CheckCircleIcon, CheckIcon, InfoCircleIcon } from "@/components/Icons"
import Modal from "@/components/Modal"
import Button from "@/components/TempDesignSystem/Button"
import Label from "@/components/TempDesignSystem/Form/Label"
import Popover from "@/components/TempDesignSystem/Popover"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import { RATE_CARD_EQUAL_HEIGHT_CLASS } from "../utils"
@@ -116,33 +118,37 @@ export default function FlexibilityOption({
/>
<div className={`${styles.card} ${RATE_CARD_EQUAL_HEIGHT_CLASS}`}>
<div className={styles.header}>
<Popover
placement="bottom left"
triggerContent={
<InfoCircleIcon
width={16}
height={16}
color="uiTextMediumContrast"
/>
<Modal
trigger={
<Button intent="text">
<InfoCircleIcon
width={16}
height={16}
color="uiTextMediumContrast"
/>
</Button>
}
title={name}
subtitle={paymentTerm}
>
<Caption
color="uiTextHighContrast"
type="bold"
className={styles.popoverHeading}
>
{name}
</Caption>
{priceInformation?.map((info) => (
<Caption
key={info}
color="uiTextHighContrast"
className={styles.popoverText}
>
{info}
</Caption>
))}
</Popover>
<div className={styles.terms}>
{priceInformation?.map((info) => (
<Body
key={info}
color="uiTextHighContrast"
className={styles.termsText}
>
<CheckIcon
color="uiSemanticSuccess"
width={20}
height={20}
className={styles.termsIcon}
></CheckIcon>
{info}
</Body>
))}
</div>
</Modal>
<div className={styles.priceType}>
<Caption color="uiTextHighContrast">{name}</Caption>
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption>

View File

@@ -85,7 +85,7 @@ export default function RoomCard({
)
)
const { name, roomSize, occupancy, images } = selectedRoom || {}
const { name, roomSize, totalOccupancy, images } = selectedRoom || {}
const freeCancelation = intl.formatMessage({ id: "Free cancellation" })
const nonRefundable = intl.formatMessage({ id: "Non-refundable" })
@@ -150,13 +150,13 @@ export default function RoomCard({
</div>
<div className={styles.specification}>
{occupancy?.total && (
{totalOccupancy && (
<Caption color="uiTextMediumContrast" className={styles.guests}>
{intl.formatMessage(
{
id: "booking.guests",
},
{ nrOfGuests: occupancy.total }
{ max: totalOccupancy.max, range: totalOccupancy.range }
)}
</Caption>
)}

View File

@@ -1,8 +1,10 @@
"use client"
import { useRouter, useSearchParams } from "next/navigation"
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { useSession } from "next-auth/react"
import { useCallback, useEffect, useMemo, useRef } from "react"
import { debounce } from "@/utils/debounce"
import { isValidSession } from "@/utils/session"
import RateSummary from "./RateSummary"
import RoomCard from "./RoomCard"
@@ -20,16 +22,16 @@ import type { RoomSelectionProps } from "@/types/components/hotelReservation/sel
export default function RoomSelection({
roomsAvailability,
roomCategories,
user,
availablePackages,
selectedPackages,
isUserLoggedIn,
setRateCode,
rateSummary,
hotelType,
}: RoomSelectionProps) {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
const isUserLoggedIn = !!user
const roomRefs = useRef<HTMLLIElement[]>([])
const { roomConfigurations, rateDefinitions } = roomsAvailability
@@ -109,9 +111,9 @@ export default function RoomSelection({
rateSummary.member.rateCode
)
}
if (selectedPackages.length > 0) {
params.set(`room[${index}].packages`, selectedPackages.join(","))
}
selectedPackages.length > 0
? params.set(`room[${index}].packages`, selectedPackages.join(","))
: params.delete(`room[${index}].packages`)
})
return params
@@ -119,6 +121,12 @@ export default function RoomSelection({
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
window.history.replaceState(
null,
"",
`${pathname}?${queryParams.toString()}`
)
router.push(`select-bed?${queryParams}`)
}

View File

@@ -2,11 +2,12 @@ import { dt } from "@/lib/dt"
import {
getHotelData,
getPackages,
getProfileSafely,
getRoomsAvailability,
} from "@/lib/trpc/memoizedRequests"
import { auth } from "@/auth"
import { safeTry } from "@/utils/safeTry"
import { isValidSession } from "@/utils/session"
import { generateChildrenString } from "../RoomSelection/utils"
import Rooms from "."
@@ -32,8 +33,8 @@ export async function RoomsContainer({
childArray,
lang,
}: Props) {
const user = await getProfileSafely()
const session = await auth()
const isUserLoggedIn = isValidSession(session)
const fromDateString = dt(fromDate).format("YYYY-MM-DD")
const toDateString = dt(toDate).format("YYYY-MM-DD")
@@ -92,11 +93,11 @@ export async function RoomsContainer({
return (
<Rooms
user={user}
availablePackages={packages ?? []}
roomsAvailability={roomsAvailability}
roomCategories={hotelData?.included?.rooms ?? []}
hotelType={hotelData?.data.attributes?.hotelType}
isUserLoggedIn={isUserLoggedIn}
/>
)
}

View File

@@ -23,9 +23,9 @@ import type { RoomConfiguration } from "@/server/routers/hotels/output"
export default function Rooms({
roomsAvailability,
roomCategories = [],
user,
availablePackages,
hotelType,
isUserLoggedIn,
}: SelectRateProps) {
const visibleRooms: RoomConfiguration[] = useMemo(() => {
const deduped = filterDuplicateRoomTypesByLowestPrice(
@@ -184,12 +184,12 @@ export default function Rooms({
<RoomSelection
roomsAvailability={rooms}
roomCategories={roomCategories}
user={user}
availablePackages={availablePackages}
selectedPackages={selectedPackages}
setRateCode={setSelectedRate}
rateSummary={rateSummary}
hotelType={hotelType}
isUserLoggedIn={isUserLoggedIn}
/>
</div>
)