"use client" import Downshift from "downshift" import { ChangeEvent, FocusEvent, FormEvent, useCallback, useReducer, } from "react" import { useFormContext, useWatch } from "react-hook-form" import { useIntl } from "react-intl" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" import Input from "../Input" import { init, localStorageKey, reducer, sessionStorageKey } from "./reducer" import SearchList from "./SearchList" import styles from "./search.module.css" import type { BookingWidgetSchema } from "@/types/components/bookingWidget" import { ActionType } from "@/types/components/form/bookingwidget" import type { SearchProps } from "@/types/components/search" import type { Location } from "@/types/trpc/routers/hotel/locations" const name = "search" export default function Search({ locations }: SearchProps) { const [state, dispatch] = useReducer( reducer, { defaultLocations: locations }, init ) const { register, setValue, trigger } = useFormContext() const intl = useIntl() const value = useWatch({ name }) const handleMatchLocations = useCallback( function (searchValue: string) { return locations.filter((location) => { return location.name.toLowerCase().includes(searchValue.toLowerCase()) }) }, [locations] ) function handleClearSearchHistory() { localStorage.removeItem(localStorageKey) dispatch({ type: ActionType.CLEAR_HISTORY_LOCATIONS }) } function handleOnBlur() { if (!value && state.searchData?.name) { setValue(name, state.searchData.name) // Always need to manually trigger // revalidation when setting value r-h-f trigger() } } function handleOnChange( evt: FormEvent | ChangeEvent ) { const value = evt.currentTarget.value if (value) { dispatch({ payload: { search: value }, type: ActionType.SEARCH_LOCATIONS, }) } else { dispatch({ type: ActionType.CLEAR_SEARCH_LOCATIONS }) } } function handleOnFocus(evt: FocusEvent) { const searchValue = evt.currentTarget.value if (searchValue) { const matchingLocations = handleMatchLocations(searchValue) if (matchingLocations.length) { dispatch({ payload: { search: searchValue }, type: ActionType.SEARCH_LOCATIONS, }) } } } function handleOnSelect(selectedItem: Location | null) { if (selectedItem) { const stringified = JSON.stringify(selectedItem) setValue("location", encodeURIComponent(stringified)) sessionStorage.setItem(sessionStorageKey, stringified) setValue(name, selectedItem.name) trigger() const searchHistoryMap = new Map() searchHistoryMap.set(selectedItem.name, selectedItem) if (state.searchHistory) { state.searchHistory.forEach((location) => { searchHistoryMap.set(location.name, location) }) } const searchHistory: Location[] = [] searchHistoryMap.forEach((location) => { searchHistory.push(location) }) localStorage.setItem(localStorageKey, JSON.stringify(searchHistory)) dispatch({ payload: { location: selectedItem, searchHistory, }, type: ActionType.SELECT_ITEM, }) } else { sessionStorage.removeItem(sessionStorageKey) } } return ( (value ? value.name : "")} onSelect={handleOnSelect} > {({ closeMenu, getInputProps, getItemProps, getLabelProps, getMenuProps, getRootProps, highlightedIndex, isOpen, openMenu, }) => (
)}
) }