import DatePicker from "@/src/Components/Common/DatePicker"
import { SEARCH_PAGE } from "@/src/Constants/AppPaths"
import { DATE_FORMATS } from "@/src/Constants/GenericConstants"
import { strings } from "@/src/Constants/Strings"
import { useDetectOutsideClick } from "@/src/Hooks/useDetectOutsideClick"
import useOptions from "@/src/Hooks/useOptions"
import React, { useRef, useState, useEffect, Fragment } from "react"
import { getCategories, getCities, getCountries } from "@/src/Network/RequestBuilder"
import {
capitalize,
getDateString,
splitAndMergeStringByHyphen,
stringToDate,
useIfMobile,
} from "@/src/Utils/GenericUtils"
import Heading from "@/src/Components/Common/Heading"
import cx from "clsx"
import { ChevronRight } from "react-feather"
import { BiCalendar, BiCategory, BiListUl, BiSearch, BiUser } from "react-icons/bi"
import { HiOutlineChevronDown, HiOutlineSearch, HiSearch } from "react-icons/hi"
import { IoLocationOutline } from "react-icons/io5"
import Select, { components } from "react-select"
import { CancelIcon, IconFilter } from "../../icons/svg-icons"
import SearchChips from "../../SearchPage/SearchChips"
import { BottomSheet } from "../BottomSheet"
import Button from "../Button"
import InputMobile from "../FormInputMobile"
import styles from "./index.module.scss"
import MobileOptions from "./MobileOptions"
const RenderComponent = ({ children, ...props }) => {
const { isMobile, setOpen, router } = props.selectProps
return (
<>
{isMobile && <span className={styles.selectIcon}>{<HiSearch />}</span>}
<div className={cx(styles.selectContent, "flexGrow")}>{children}</div>
{isMobile && (
<span
// This method does not execute upon Click
onClick={() => {
console.log("BRU")
router.push("#filters", null, {
shallow: true,
})
setOpen(true)
}}
className={styles.selectIcon}
>
<IconFilter />
</span>
)}
</>
)
}
const Control = ({ children, ...props }) => (
<Fragment>
<components.Control {...props}>
<RenderComponent {...props}>{children}</RenderComponent>
</components.Control>
</Fragment>
)
const SearchBar = (props) => {
const isMobile = useIfMobile()
const screenOptionsRef = useRef()
const {
router,
searchChips: ChipsComponent,
// setTypedValue
} = props
const [showOptionsScreen, setShowOptionsScreen] = useDetectOutsideClick(screenOptionsRef, false)
const { addToRecentSearches, recentSearches, formatOptions, options, RecentSearchComponent, AllCategoriesBtn } =
useOptions(getCategories)
let prefillValue = ""
// prefilling keyword search
if (router?.query?.keyword) {
let target = router?.query?.keyword
options?.forEach((optionLabel) => {
optionLabel?.options?.forEach((option) => {
if (option?.slug === target || option?.value === target) {
prefillValue = option
}
})
})
}
const [value, setValue] = useState("")
const [inputValue, setInputValue] = useState("")
const [isMenuOpen, setIsMenuOpen] = useState(false)
const [noOptions, setNoOptions] = useState(false)
const [open, setOpen] = useState(false)
useEffect(() => {
!isMobile && setOpen(false)
}, [isMobile])
const typeQuery = () => {
return router.query?.browse_by ?? "search"
}
useEffect(() => {
props.setShowContent(!showOptionsScreen)
}, [showOptionsScreen])
const handleInputSearch = () => {
const { browse_by } = router.query
if (inputValue) {
setIsMenuOpen(false)
addToRecentSearches(inputValue, browse_by)
const queryObj = { ...router.query }
delete queryObj["browse_by"]
router.push({ pathname: `/${typeQuery()}`, query: { ...queryObj, keyword: inputValue } }, null, {
shallow: true,
})
} else {
const routerObj = { ...router.query }
delete routerObj.keyword
router.push({ pathname: `/${typeQuery()}`, query: {} }, null, { shallow: true })
}
}
const handleSearchClick = (item, e) => {
setIsMenuOpen(false)
if (!item) {
if (router.pathname === "/") return
if (inputValue) {
setInputValue("")
// setTypedValue("")
}
setValue("")
const queryObj = { ...router.query }
const isKeyword = e?.removedValues[0]?.id ? false : true
isKeyword ? delete queryObj.keyword : delete queryObj.category
router.push({ pathname: SEARCH_PAGE, query: { ...queryObj } }, null, { shallow: true })
} else {
if (item.isCached) {
setValue(item)
const routerQuery = { ...router.query }
// use the type associated with the recent search rather using what's in the URL query
delete routerQuery["browse_by"]
if (item?.label) {
routerQuery["keyword"] = item.label
}
router.push({ pathname: item?.type ? `/${item.type}` : `/${typeQuery()}`, query: { ...routerQuery } }, null, {
shallow: true,
})
} else {
const routerQuery = { ...router.query }
delete routerQuery["browse_by"]
if (item?.slug) {
routerQuery["category"] = item.slug
}
router.push({ pathname: `/${typeQuery()}`, query: { ...routerQuery } }, null, {
shallow: true,
})
}
}
}
const customStyles = {
indicatorSeparator: (provided) => ({
...provided,
display: "none",
}),
placeholder: (provided) => ({
...provided,
color: "#a3a3a3",
}),
control: (provided, { isFocused, isMenuOpen }) => ({
...provided,
boxShadow: "none",
minHeight: isMobile ? "48px" : "56px",
backgroundColor: props.compactView ? "#fff" : "rgba(227, 227, 227, 0.2)",
borderColor: isFocused ? "#dbdee1" : props.compactView ? "#e3e3e3" : "#e3e3e3",
"&:hover": {
borderColor: isMenuOpen ? "#436347" : "",
cursor: "text",
},
}),
indicatorsContainer: (provided) => ({
...provided,
width: "2.125rem",
justifyContent: "center",
fontSize: "1.3rem",
color: "#00a651",
cursor: "pointer",
}),
dropdownIndicator: (provided) => ({
...provided,
display: "none",
}),
valueContainer: (provided) => ({
...provided,
padding: "2px 1rem",
}),
menu: (provided) => ({
...provided,
width: "100%",
zIndex: 2,
}),
option: (provided, state) => ({
...provided,
display: "flex",
alignItems: "center",
gap: "1rem",
cursor: "pointer",
backgroundColor: "#fff",
color: "#1e1e1e",
"&:hover": {
backgroundColor: "#f9f9f9",
},
}),
}
// if there are no options that matches your input string, execute a new keyword search on Enter
const handleKeyPressDown = (e) => {
if (isMobile && e.code === "Enter") {
handleInputSearch()
setShowOptionsScreen(false)
return
}
if (noOptions && inputValue) {
if (e.code === "Enter") {
handleInputSearch()
}
}
}
return (
<>
<div
className={cx(
styles.searchBarOuter,
props.className && props.className,
props.compactView && styles.compactView
)}
>
<div className={isMobile ? cx(styles.searchMobile, "flex") : "flexGrow"}>
<Select
router={router}
setOpen={setOpen}
isMobile={isMobile}
key={JSON.stringify(recentSearches.length)}
value={prefillValue || value}
inputValue={inputValue}
options={options}
placeholder="Search the website"
formatOptionLabel={formatOptions}
onChange={handleSearchClick}
menuIsOpen={isMenuOpen}
// menuIsOpen={true}
closeMenuOnSelect={false}
indicatorsContainer={false}
onKeyDown={handleKeyPressDown}
onMenuOpen={() => {
if (props.showSingleScreen) {
setShowOptionsScreen(true)
} else {
setIsMenuOpen(true)
}
}}
onInputChange={(value, action) => {
if (action.action === "input-change") {
// setTypedValue(value)
setInputValue(value)
}
}}
onMenuClose={() => setIsMenuOpen(false)}
noOptionsMessage={() => {
setNoOptions(true)
return null
}}
isClearable={true}
debounceTimeout={200}
classNamePrefix="select"
className={cx(styles.selectOuter, "flexGrow")}
styles={customStyles}
components={{ Control, DropdownIndicator: () => null }}
/>
</div>
{isMobile ? (
<></>
) : (
<Button
onClick={handleInputSearch}
icon={<HiOutlineSearch />}
size="lg"
style={{ "--btn-min-width": props.compactView ? "62px" : "130px" }}
>
{!props.compactView && strings.search}
</Button>
)}
</div>
{/* {showOptionsScreen && (
<MobileOptions
RecentSearchComponent={RecentSearchComponent}
screenOptionsRef={screenOptionsRef}
handleSearchClick={handleSearchClick}
setShowFooter={props.setShowFooter}
options={options}
setShowOptionsScreen={setShowOptionsScreen}
/>
)} */}
</>
)
}
export default SearchBar
SearchBar.defaultProps = {
setTypedValue: () => {},
}
在
Mobile View
中,在我的RenderComponent
中,单击包含IconFilter
的span 标签时,没有任何反应。点击事件不会被捕获,相应的onClick
方法也不会被执行。但是,如果我要省略 isMobile
检查,则 Click 事件会被捕获。相同的代码适用于桌面视图,但对于mobile view
,不会捕获点击方法。我正在使用React Select
。如何在移动视图中单击 span 标签?