Feature/autocomplete search * wip autocomplete search * add skeletons to loading * Using aumlauts/accents when searching will still give results remove unused reducer sort autocomplete results * remove testcode * Add tests for autocomplete * cleanup tests * use node@20 * use node 22 * use node22 * merge fix: search button outside of viewport * merge * remove more unused code * fix: error message when empty search field in booking widget * fix: don't display empty white box when search field is empty and no searchHistory is present * merge * fix: set height of shimmer for search skeleton * rename autocomplete trpc -> destinationsAutocomplete * more accute cache key naming * fix: able to control wether bookingwidget is visible on startPage fix: sticky booking widget under alert * remove unused code * fix: skeletons fix: error overlay on search startpage * remove extra .nvmrc * merge Approved-by: Linus Flood
92 lines
2.2 KiB
TypeScript
92 lines
2.2 KiB
TypeScript
"use client"
|
|
|
|
import { useCallback, useEffect, useRef } from "react"
|
|
|
|
import { trpc } from "@/lib/trpc/client"
|
|
import { StickyElementNameEnum } from "@/stores/sticky-position"
|
|
|
|
import Alert from "@/components/TempDesignSystem/Alert"
|
|
import useLang from "@/hooks/useLang"
|
|
import useStickyPosition from "@/hooks/useStickyPosition"
|
|
import { debounce } from "@/utils/debounce"
|
|
|
|
import styles from "./sitewideAlert.module.css"
|
|
|
|
import { AlertTypeEnum } from "@/types/enums/alert"
|
|
|
|
export default function SiteWideAlert() {
|
|
const alertRef = useRef<HTMLDivElement>(null)
|
|
const lang = useLang()
|
|
const { data: siteConfig, isLoading } =
|
|
trpc.contentstack.base.siteConfig.useQuery(
|
|
{ lang },
|
|
{ refetchInterval: 60_000 }
|
|
)
|
|
|
|
const alert = siteConfig?.sitewideAlert
|
|
|
|
const isAlarm = alert?.type === AlertTypeEnum.Alarm
|
|
useStickyPosition({
|
|
ref: isAlarm ? alertRef : undefined,
|
|
name: StickyElementNameEnum.SITEWIDE_ALERT,
|
|
})
|
|
|
|
const updateHeight = useCallback(() => {
|
|
if (alertRef.current) {
|
|
const height = alertRef.current.offsetHeight
|
|
|
|
document.documentElement.style.setProperty(
|
|
"--sitewide-alert-height",
|
|
`${height}px`
|
|
)
|
|
|
|
document.documentElement.style.setProperty(
|
|
"--sitewide-alert-sticky-height",
|
|
isAlarm ? `${height}px` : "0px"
|
|
)
|
|
}
|
|
}, [isAlarm])
|
|
|
|
useEffect(() => {
|
|
const alertElement = alertRef.current
|
|
const debouncedResizeHandler = debounce(() => {
|
|
updateHeight()
|
|
}, 100)
|
|
const observer = new ResizeObserver(debouncedResizeHandler)
|
|
|
|
if (alertElement) {
|
|
observer.observe(alertElement)
|
|
}
|
|
|
|
return () => {
|
|
if (alertElement) {
|
|
observer.unobserve(alertElement)
|
|
}
|
|
observer.disconnect()
|
|
}
|
|
}, [updateHeight])
|
|
|
|
if (isLoading || !alert) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div
|
|
id="sitewide-alert"
|
|
ref={alertRef}
|
|
className={`${styles.sitewideAlert} ${isAlarm ? styles.alarm : ""}`}
|
|
>
|
|
<Alert
|
|
variant="banner"
|
|
type={alert.type}
|
|
link={alert.link}
|
|
phoneContact={alert.phoneContact}
|
|
sidepeekCtaText={alert.sidepeekButton?.cta_text}
|
|
sidepeekContent={alert.sidepeekContent}
|
|
heading={alert.heading}
|
|
text={alert.text}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|