107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
"use client"
|
|
import { useEffect, useState } from "react"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import { useDetailsStore } from "@/stores/details"
|
|
import { useStepsStore } from "@/stores/steps"
|
|
|
|
import { CheckIcon, ChevronDownIcon } from "@/components/Icons"
|
|
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
|
|
|
import styles from "./sectionAccordion.module.css"
|
|
|
|
import { StepStoreKeys } from "@/types/components/hotelReservation/enterDetails/step"
|
|
import { SectionAccordionProps } from "@/types/components/hotelReservation/selectRate/sectionAccordion"
|
|
import { StepEnum } from "@/types/enums/step"
|
|
|
|
export default function SectionAccordion({
|
|
header,
|
|
label,
|
|
step,
|
|
children,
|
|
}: React.PropsWithChildren<SectionAccordionProps>) {
|
|
const intl = useIntl()
|
|
const currentStep = useStepsStore((state) => state.currentStep)
|
|
const [isComplete, setIsComplete] = useState(false)
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
const isValid = useDetailsStore((state) => state.isValid[step])
|
|
const navigate = useStepsStore((state) => state.navigate)
|
|
const stepData = useDetailsStore((state) => state.data)
|
|
const stepStoreKey = StepStoreKeys[step]
|
|
const [title, setTitle] = useState(label)
|
|
|
|
useEffect(() => {
|
|
if (step === StepEnum.selectBed) {
|
|
const value = stepData.bedType
|
|
value && setTitle(value.description)
|
|
}
|
|
// If breakfast step, check if an option has been selected
|
|
if (
|
|
step === StepEnum.breakfast &&
|
|
(stepData.breakfast || stepData.breakfast === false)
|
|
) {
|
|
const value = stepData.breakfast
|
|
if (value === false) {
|
|
setTitle(intl.formatMessage({ id: "No breakfast" }))
|
|
} else {
|
|
setTitle(intl.formatMessage({ id: "Breakfast buffet" }))
|
|
}
|
|
}
|
|
}, [stepData, stepStoreKey, step, intl])
|
|
|
|
useEffect(() => {
|
|
// We need to set the state on mount because of hydration errors
|
|
setIsComplete(isValid)
|
|
}, [isValid])
|
|
|
|
useEffect(() => {
|
|
setIsOpen(currentStep === step)
|
|
}, [currentStep, step])
|
|
|
|
function onModify() {
|
|
navigate(step)
|
|
}
|
|
|
|
const textColor =
|
|
isComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled"
|
|
return (
|
|
<div className={styles.accordion} data-open={isOpen} data-step={step}>
|
|
<div className={styles.iconWrapper}>
|
|
<div className={styles.circle} data-checked={isComplete}>
|
|
{isComplete ? (
|
|
<CheckIcon color="white" height="16" width="16" />
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
<header className={styles.header}>
|
|
<button
|
|
onClick={onModify}
|
|
disabled={!isComplete}
|
|
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>
|
|
|
|
{isComplete && !isOpen && (
|
|
<ChevronDownIcon className={styles.button} color="burgundy" />
|
|
)}
|
|
</button>
|
|
</header>
|
|
<div className={styles.content}>
|
|
<div className={styles.contentWrapper}>{children}</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|