Merged in feat/SW-1889 (pull request #1670)
Feat/SW-1889 * fix: remove download invoice from confirmation page * feat: remove EnterDetails Accordions Approved-by: Simon.Emanuelsson
This commit is contained in:
@@ -58,8 +58,7 @@ export default function BedType() {
|
||||
return
|
||||
}
|
||||
|
||||
const subscription = methods.watch(() => methods.handleSubmit(onSubmit)())
|
||||
return () => subscription.unsubscribe()
|
||||
methods.watch(() => methods.handleSubmit(onSubmit)())
|
||||
}, [methods, onSubmit])
|
||||
|
||||
return (
|
||||
|
||||
@@ -58,8 +58,7 @@ export default function Breakfast() {
|
||||
if (methods.formState.isSubmitting) {
|
||||
return
|
||||
}
|
||||
const subscription = methods.watch(() => methods.handleSubmit(onSubmit)())
|
||||
return () => subscription.unsubscribe()
|
||||
methods.watch(() => methods.handleSubmit(onSubmit)())
|
||||
}, [methods, onSubmit])
|
||||
|
||||
return (
|
||||
|
||||
@@ -24,23 +24,20 @@ const formID = "enter-details"
|
||||
export default function Details() {
|
||||
const intl = useIntl()
|
||||
|
||||
const { activeRoom, canProceedToPayment, lastRoom } = useEnterDetailsStore(
|
||||
(state) => ({
|
||||
activeRoom: state.activeRoom,
|
||||
canProceedToPayment: state.canProceedToPayment,
|
||||
lastRoom: state.lastRoom,
|
||||
})
|
||||
)
|
||||
const { canProceedToPayment, lastRoom } = useEnterDetailsStore((state) => ({
|
||||
canProceedToPayment: state.canProceedToPayment,
|
||||
lastRoom: state.lastRoom,
|
||||
}))
|
||||
|
||||
const {
|
||||
actions: { updateDetails },
|
||||
idx,
|
||||
room,
|
||||
roomNr,
|
||||
} = useRoomContext()
|
||||
const initialData = room.guest
|
||||
|
||||
const isPaymentNext = activeRoom === lastRoom
|
||||
|
||||
const isPaymentNext = idx === lastRoom
|
||||
const methods = useForm<MultiroomDetailsSchema>({
|
||||
criteriaMode: "all",
|
||||
mode: "all",
|
||||
|
||||
@@ -31,22 +31,20 @@ export default function Details({ user }: DetailsProps) {
|
||||
const intl = useIntl()
|
||||
const [isMemberPriceModalOpen, setIsMemberPriceModalOpen] = useState(false)
|
||||
|
||||
const { activeRoom, canProceedToPayment, lastRoom } = useEnterDetailsStore(
|
||||
(state) => ({
|
||||
activeRoom: state.activeRoom,
|
||||
canProceedToPayment: state.canProceedToPayment,
|
||||
lastRoom: state.lastRoom,
|
||||
})
|
||||
)
|
||||
const { canProceedToPayment, lastRoom } = useEnterDetailsStore((state) => ({
|
||||
canProceedToPayment: state.canProceedToPayment,
|
||||
lastRoom: state.lastRoom,
|
||||
}))
|
||||
const {
|
||||
actions: { updateDetails },
|
||||
idx,
|
||||
room,
|
||||
roomNr,
|
||||
} = useRoomContext()
|
||||
const initialData = room.guest
|
||||
const memberRate = "member" in room.roomRate ? room.roomRate.member : null
|
||||
|
||||
const isPaymentNext = activeRoom === lastRoom
|
||||
const memberRate = "member" in room.roomRate ? room.roomRate.member : null
|
||||
const isPaymentNext = idx === lastRoom
|
||||
|
||||
const methods = useForm<DetailsSchema>({
|
||||
criteriaMode: "all",
|
||||
|
||||
@@ -67,13 +67,13 @@ export default function PaymentClient({
|
||||
|
||||
const [showPaymentAlert, setShowPaymentAlert] = useState(false)
|
||||
|
||||
const { booking, canProceedToPayment, rooms, totalPrice } =
|
||||
useEnterDetailsStore((state) => ({
|
||||
booking: state.booking,
|
||||
canProceedToPayment: state.canProceedToPayment,
|
||||
rooms: state.rooms,
|
||||
totalPrice: state.totalPrice,
|
||||
}))
|
||||
const { booking, rooms, totalPrice } = useEnterDetailsStore((state) => ({
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
totalPrice: state.totalPrice,
|
||||
}))
|
||||
|
||||
const allRoomsComplete = rooms.every((r) => r.isComplete)
|
||||
|
||||
const bookingMustBeGuaranteed = rooms.some(({ room }, idx) => {
|
||||
if (idx === 0 && isUserLoggedIn && room.memberMustBeGuaranteed) {
|
||||
@@ -390,7 +390,7 @@ export default function PaymentClient({
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.paymentSection} ${canProceedToPayment ? "" : styles.disabled}`}
|
||||
className={`${styles.paymentSection} ${allRoomsComplete ? "" : styles.disabled}`}
|
||||
>
|
||||
<header>
|
||||
<Title level="h2" as="h4">
|
||||
|
||||
@@ -7,7 +7,7 @@ import BedType from "@/components/HotelReservation/EnterDetails/BedType"
|
||||
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
|
||||
import Details from "@/components/HotelReservation/EnterDetails/Details/Multiroom"
|
||||
import Header from "@/components/HotelReservation/EnterDetails/Room/Header"
|
||||
import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion"
|
||||
import Section from "@/components/HotelReservation/EnterDetails/Section"
|
||||
import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
import { useRoomContext } from "@/contexts/Details/Room"
|
||||
@@ -16,12 +16,31 @@ import { StepEnum } from "@/types/enums/step"
|
||||
|
||||
export default function Multiroom() {
|
||||
const intl = useIntl()
|
||||
const { room, roomNr } = useRoomContext()
|
||||
const breakfastPackages = useEnterDetailsStore(
|
||||
(state) => state.breakfastPackages
|
||||
)
|
||||
const { idx, room, roomNr, steps } = useRoomContext()
|
||||
const { breakfastPackages, rooms } = useEnterDetailsStore((state) => ({
|
||||
breakfastPackages: state.breakfastPackages,
|
||||
rooms: state.rooms,
|
||||
}))
|
||||
|
||||
const showBreakfastStep =
|
||||
!room.breakfastIncluded && !!breakfastPackages?.length
|
||||
|
||||
const arePreviousRoomsValid = rooms.slice(0, idx).every((r) => r.isComplete)
|
||||
|
||||
const isBreakfastStepValid = showBreakfastStep
|
||||
? steps[StepEnum.breakfast]?.isValid
|
||||
: true
|
||||
|
||||
const isBreakfastDisabled = !(
|
||||
arePreviousRoomsValid && steps[StepEnum.selectBed].isValid
|
||||
)
|
||||
|
||||
const isDetailsDisabled = !(
|
||||
arePreviousRoomsValid &&
|
||||
steps[StepEnum.selectBed].isValid &&
|
||||
isBreakfastStepValid
|
||||
)
|
||||
|
||||
return (
|
||||
<section>
|
||||
<Header>
|
||||
@@ -38,34 +57,37 @@ export default function Multiroom() {
|
||||
<SelectedRoom />
|
||||
|
||||
{room.bedTypes ? (
|
||||
<SectionAccordion
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Select bed" })}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
step={StepEnum.selectBed}
|
||||
disabled={!arePreviousRoomsValid}
|
||||
>
|
||||
<BedType />
|
||||
</SectionAccordion>
|
||||
</Section>
|
||||
) : null}
|
||||
|
||||
{showBreakfastStep ? (
|
||||
<SectionAccordion
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Food options" })}
|
||||
label={intl.formatMessage({
|
||||
id: "Select breakfast options",
|
||||
})}
|
||||
step={StepEnum.breakfast}
|
||||
disabled={isBreakfastDisabled}
|
||||
>
|
||||
<Breakfast />
|
||||
</SectionAccordion>
|
||||
</Section>
|
||||
) : null}
|
||||
|
||||
<SectionAccordion
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Details" })}
|
||||
step={StepEnum.details}
|
||||
label={intl.formatMessage({ id: "Enter your details" })}
|
||||
disabled={isDetailsDisabled}
|
||||
>
|
||||
<Details />
|
||||
</SectionAccordion>
|
||||
</Section>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import BedType from "@/components/HotelReservation/EnterDetails/BedType"
|
||||
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
|
||||
import Details from "@/components/HotelReservation/EnterDetails/Details/RoomOne"
|
||||
import Header from "@/components/HotelReservation/EnterDetails/Room/Header"
|
||||
import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion"
|
||||
import Section from "@/components/HotelReservation/EnterDetails/Section"
|
||||
import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
import { useRoomContext } from "@/contexts/Details/Room"
|
||||
@@ -17,13 +17,12 @@ import type { SafeUser } from "@/types/user"
|
||||
|
||||
export default function RoomOne({ user }: { user: SafeUser }) {
|
||||
const intl = useIntl()
|
||||
const { room } = useRoomContext()
|
||||
const { breakfastPackages, rooms } = useEnterDetailsStore((state) => ({
|
||||
const { room, steps } = useRoomContext()
|
||||
const { breakfastPackages, isMultiroom } = useEnterDetailsStore((state) => ({
|
||||
breakfastPackages: state.breakfastPackages,
|
||||
rooms: state.rooms,
|
||||
isMultiroom: state.rooms.length > 1,
|
||||
}))
|
||||
|
||||
const isMultiroom = rooms.length > 1
|
||||
const showBreakfastStep =
|
||||
!room.breakfastIncluded && !!breakfastPackages?.length
|
||||
return (
|
||||
@@ -44,34 +43,41 @@ export default function RoomOne({ user }: { user: SafeUser }) {
|
||||
<SelectedRoom />
|
||||
|
||||
{room.bedTypes ? (
|
||||
<SectionAccordion
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Select bed" })}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
step={StepEnum.selectBed}
|
||||
>
|
||||
<BedType />
|
||||
</SectionAccordion>
|
||||
</Section>
|
||||
) : null}
|
||||
|
||||
{showBreakfastStep ? (
|
||||
<SectionAccordion
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Food options" })}
|
||||
label={intl.formatMessage({
|
||||
id: "Select breakfast options",
|
||||
})}
|
||||
step={StepEnum.breakfast}
|
||||
disabled={!steps[StepEnum.selectBed].isValid}
|
||||
>
|
||||
<Breakfast />
|
||||
</SectionAccordion>
|
||||
</Section>
|
||||
) : null}
|
||||
|
||||
<SectionAccordion
|
||||
<Section
|
||||
header={intl.formatMessage({ id: "Details" })}
|
||||
step={StepEnum.details}
|
||||
label={intl.formatMessage({ id: "Enter your details" })}
|
||||
disabled={
|
||||
!(
|
||||
steps[StepEnum.selectBed].isValid &&
|
||||
steps[StepEnum.breakfast]?.isValid !== false
|
||||
)
|
||||
}
|
||||
>
|
||||
<Details user={user} />
|
||||
</SectionAccordion>
|
||||
</Section>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
"use client"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
import { useRoomContext } from "@/contexts/Details/Room"
|
||||
|
||||
import styles from "./section.module.css"
|
||||
|
||||
import type { SectionProps } from "@/types/components/hotelReservation/enterDetails/section"
|
||||
import { StepEnum } from "@/types/enums/step"
|
||||
|
||||
export default function Section({
|
||||
children,
|
||||
header,
|
||||
label,
|
||||
step,
|
||||
disabled,
|
||||
}: React.PropsWithChildren<SectionProps>) {
|
||||
const intl = useIntl()
|
||||
|
||||
const {
|
||||
room: { bedType, breakfast },
|
||||
} = useRoomContext()
|
||||
|
||||
const [title, setTitle] = useState(label)
|
||||
|
||||
const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" })
|
||||
const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" })
|
||||
|
||||
useEffect(() => {
|
||||
if (step === StepEnum.selectBed && bedType) {
|
||||
setTitle(bedType.description)
|
||||
}
|
||||
// If breakfast step, check if an option has been selected
|
||||
if (step === StepEnum.breakfast && breakfast !== undefined) {
|
||||
if (breakfast === false) {
|
||||
setTitle(noBreakfastTitle)
|
||||
} else {
|
||||
setTitle(breakfastTitle)
|
||||
}
|
||||
}
|
||||
}, [bedType, breakfast, setTitle, step, breakfastTitle, noBreakfastTitle])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.accordion} ${disabled ? styles.disabled : ""}`}
|
||||
data-step={step}
|
||||
>
|
||||
<header className={styles.header}>
|
||||
<Footnote
|
||||
className={styles.title}
|
||||
asChild
|
||||
textTransform="uppercase"
|
||||
type="label"
|
||||
>
|
||||
<h2>{header}</h2>
|
||||
</Footnote>
|
||||
<Subtitle className={styles.selection} type="two">
|
||||
{title}
|
||||
</Subtitle>
|
||||
</header>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.contentWrapper}>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
.accordion {
|
||||
--header-height: 2.4em;
|
||||
--circle-height: 24px;
|
||||
gap: var(--Spacing-x3);
|
||||
width: 100%;
|
||||
padding-top: var(--Spacing-x3);
|
||||
display: grid;
|
||||
grid-template-areas: "header" "content";
|
||||
grid-template-rows: var(--header-height) 1fr;
|
||||
column-gap: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.header {
|
||||
grid-area: header;
|
||||
}
|
||||
|
||||
.title {
|
||||
grid-area: title;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.selection {
|
||||
grid-area: selection;
|
||||
}
|
||||
|
||||
.contentWrapper {
|
||||
padding-bottom: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.content {
|
||||
grid-area: content;
|
||||
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.accordion {
|
||||
column-gap: var(--Spacing-x3);
|
||||
grid-template-areas: "header" "content";
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
"use client"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons"
|
||||
|
||||
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
import { useRoomContext } from "@/contexts/Details/Room"
|
||||
import useStickyPosition from "@/hooks/useStickyPosition"
|
||||
|
||||
import styles from "./sectionAccordion.module.css"
|
||||
|
||||
import type { SectionAccordionProps } from "@/types/components/hotelReservation/selectRate/sectionAccordion"
|
||||
import { StepEnum } from "@/types/enums/step"
|
||||
|
||||
export default function SectionAccordion({
|
||||
children,
|
||||
header,
|
||||
label,
|
||||
step,
|
||||
}: React.PropsWithChildren<SectionAccordionProps>) {
|
||||
const intl = useIntl()
|
||||
const stickyPosition = useStickyPosition({})
|
||||
const {
|
||||
actions: { setStep },
|
||||
currentStep,
|
||||
isActiveRoom,
|
||||
room: { bedType, breakfast, isAvailable },
|
||||
steps,
|
||||
} = useRoomContext()
|
||||
|
||||
const isStepComplete = !!(steps[step]?.isValid && isAvailable)
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [title, setTitle] = useState(label)
|
||||
|
||||
const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" })
|
||||
const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" })
|
||||
|
||||
// useScrollToActiveSection(step, steps, currentStep === step)
|
||||
|
||||
useEffect(() => {
|
||||
if (step === StepEnum.selectBed && bedType) {
|
||||
setTitle(bedType.description)
|
||||
}
|
||||
// If breakfast step, check if an option has been selected
|
||||
if (step === StepEnum.breakfast && breakfast !== undefined) {
|
||||
if (breakfast === false) {
|
||||
setTitle(noBreakfastTitle)
|
||||
} else {
|
||||
setTitle(breakfastTitle)
|
||||
}
|
||||
}
|
||||
}, [bedType, breakfast, setTitle, step, breakfastTitle, noBreakfastTitle])
|
||||
|
||||
const accordionRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const shouldBeOpen = currentStep === step && isActiveRoom && isAvailable
|
||||
setIsOpen(shouldBeOpen)
|
||||
|
||||
// Scroll to this section when it is opened,
|
||||
// but wait for the accordion animations to finish,
|
||||
// else the height calculations will not be correct and
|
||||
// the scroll position will be off.
|
||||
if (shouldBeOpen) {
|
||||
const handleTransitionEnd = () => {
|
||||
if (accordionRef.current) {
|
||||
window.scrollTo({
|
||||
top: accordionRef.current.offsetTop - stickyPosition.getTopOffset(),
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
accordionRef.current?.removeEventListener(
|
||||
"transitionend",
|
||||
handleTransitionEnd
|
||||
)
|
||||
}
|
||||
|
||||
if (accordionRef.current) {
|
||||
accordionRef.current.addEventListener(
|
||||
"transitionend",
|
||||
handleTransitionEnd,
|
||||
{ once: true }
|
||||
)
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentStep, isActiveRoom, isAvailable, setIsOpen, step])
|
||||
|
||||
function goToStep() {
|
||||
setStep(step)
|
||||
}
|
||||
|
||||
function close() {
|
||||
setIsOpen(false)
|
||||
goToStep()
|
||||
}
|
||||
|
||||
const textColor =
|
||||
isStepComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled"
|
||||
return (
|
||||
<div
|
||||
className={styles.accordion}
|
||||
data-section-open={isOpen}
|
||||
data-step={step}
|
||||
ref={accordionRef}
|
||||
>
|
||||
<div className={styles.iconWrapper}>
|
||||
<div className={styles.circle} data-checked={isStepComplete}>
|
||||
{isStepComplete ? (
|
||||
<MaterialIcon icon="check" color="Icon/Inverted" size={16} />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<header className={styles.header}>
|
||||
<button
|
||||
onClick={isOpen ? close : goToStep}
|
||||
disabled={!isStepComplete}
|
||||
className={styles.modifyButton}
|
||||
>
|
||||
<Footnote
|
||||
className={styles.title}
|
||||
asChild
|
||||
textTransform="uppercase"
|
||||
type="label"
|
||||
color={textColor}
|
||||
>
|
||||
<h2>{header}</h2>
|
||||
</Footnote>
|
||||
<Subtitle className={styles.selection} type="two" color={textColor}>
|
||||
{title}
|
||||
</Subtitle>
|
||||
{isStepComplete && (
|
||||
<MaterialIcon
|
||||
icon="keyboard_arrow_down"
|
||||
className={`${styles.button} ${isOpen ? styles.buttonOpen : ""}`}
|
||||
color="Icon/Interactive/Default"
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
</header>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.contentWrapper}>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
.accordion {
|
||||
--header-height: 2.4em;
|
||||
--circle-height: 24px;
|
||||
|
||||
gap: var(--Spacing-x3);
|
||||
width: 100%;
|
||||
padding-top: var(--Spacing-x3);
|
||||
transition: 0.3s ease-out;
|
||||
|
||||
display: grid;
|
||||
grid-template-areas: "circle header" "content content";
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-rows: var(--header-height) 0fr;
|
||||
|
||||
column-gap: var(--Spacing-x-one-and-half);
|
||||
transform-origin: top;
|
||||
}
|
||||
|
||||
.header {
|
||||
grid-area: header;
|
||||
}
|
||||
|
||||
.modifyButton {
|
||||
display: grid;
|
||||
grid-template-areas: "title button" "selection button";
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modifyButton:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.title {
|
||||
grid-area: title;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.button {
|
||||
grid-area: button;
|
||||
justify-self: flex-end;
|
||||
transform-origin: 50% 50%;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.buttonOpen {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.selection {
|
||||
grid-area: selection;
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
position: relative;
|
||||
grid-area: circle;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: var(--circle-height);
|
||||
height: var(--circle-height);
|
||||
border-radius: 100px;
|
||||
transition: background-color 0.4s;
|
||||
border: 2px solid var(--Base-Border-Inverted);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.circle[data-checked="true"] {
|
||||
background-color: var(--UI-Input-Controls-Fill-Selected);
|
||||
}
|
||||
|
||||
.accordion[data-section-open="true"] .circle[data-checked="false"] {
|
||||
background-color: var(--UI-Text-Placeholder);
|
||||
}
|
||||
|
||||
.accordion[data-section-open="false"] .circle[data-checked="false"] {
|
||||
background-color: var(--Base-Surface-Subtle-Hover);
|
||||
}
|
||||
|
||||
.accordion[data-section-open="true"] {
|
||||
grid-template-rows: var(--header-height) 1fr;
|
||||
}
|
||||
|
||||
.contentWrapper {
|
||||
opacity: 0;
|
||||
padding-bottom: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.accordion[data-section-open="true"] .contentWrapper {
|
||||
opacity: 1;
|
||||
}
|
||||
.content {
|
||||
overflow: hidden;
|
||||
grid-area: content;
|
||||
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
transform-origin: top;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
|
||||
.accordion[data-section-open="true"] .content {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.accordion {
|
||||
column-gap: var(--Spacing-x3);
|
||||
grid-template-areas: "circle header" "circle content";
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
top: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.accordion:not(:last-child) .iconWrapper::after {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
bottom: calc(0px - var(--Spacing-x5));
|
||||
top: var(--circle-height);
|
||||
|
||||
content: "";
|
||||
border-left: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ export default function SelectedRoom() {
|
||||
const lang = useLang()
|
||||
const router = useRouter()
|
||||
const [isPending, startTransition] = useTransition()
|
||||
const { room, roomNr } = useRoomContext()
|
||||
const { room, idx } = useRoomContext()
|
||||
const { hotelId, searchParamsStr } = useEnterDetailsStore((state) => ({
|
||||
hotelId: state.booking.hotelId,
|
||||
searchParamsStr: state.searchParamString,
|
||||
@@ -33,8 +33,8 @@ export default function SelectedRoom() {
|
||||
|
||||
function changeRoom() {
|
||||
const searchParams = new URLSearchParams(searchParamsStr)
|
||||
// rooms are index based, thus need for subtraction
|
||||
searchParams.set("modifyRateIndex", `${roomNr - 1}`)
|
||||
|
||||
searchParams.set("modifyRateIndex", `${idx}`)
|
||||
startTransition(() => {
|
||||
router.push(`${selectRate(lang)}?${searchParams.toString()}`)
|
||||
})
|
||||
|
||||
@@ -41,24 +41,6 @@
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 100px;
|
||||
border: 2px solid var(--Base-Border-Inverted);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.circle {
|
||||
background-color: var(--UI-Input-Controls-Fill-Selected);
|
||||
}
|
||||
|
||||
.wrapper[data-available="false"] .circle {
|
||||
background-color: var(--Base-Surface-Subtle-Hover);
|
||||
}
|
||||
@@ -92,14 +74,4 @@
|
||||
.rate::after {
|
||||
content: ")";
|
||||
}
|
||||
|
||||
.wrapper:not(:last-child)::after {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
bottom: 0;
|
||||
top: var(--Spacing-x7);
|
||||
height: 100%;
|
||||
content: "";
|
||||
border-left: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user