import { action, runInAction } from "mobx"; import { observer } from "mobx-react"; import PropTypes from "prop-types"; import { useEffect, useRef, type FC } from "react"; import { useTranslation } from "react-i18next"; import styled, { useTheme } from "styled-components"; import { addMarker, removeMarker } from "../../Models/LocationMarkerUtils"; import Box from "../../Styled/Box"; import { RawButton } from "../../Styled/Button"; import Icon, { StyledIcon } from "../../Styled/Icon"; import Spacing from "../../Styled/Spacing"; import Text from "../../Styled/Text"; import { useViewState } from "../Context"; import LocationSearchResults from "./LocationSearchResults"; import SearchBox from "./SearchBox"; export function SearchInDataCatalog({ handleClick }: { handleClick: () => void; }) { const viewState = useViewState(); const locationSearchText = viewState.searchState.locationSearchText; const { t } = useTranslation(); return ( { const { searchState } = viewState; // Set text here as a separate action so that it doesn't get batched up and the catalog // search text has a chance to set isWaitingToStartCatalogSearch searchState.setCatalogSearchText(searchState.locationSearchText); viewState.searchInCatalog(searchState.locationSearchText); if (handleClick) { handleClick(); } }} > {t("search.searchInDataCatalog", { locationSearchText: locationSearchText })} ); } SearchInDataCatalog.propTypes = { handleClick: PropTypes.func.isRequired, viewState: PropTypes.object.isRequired }; const PresentationBox = styled(Box).attrs({ fullWidth: true })<{ highlightBottom: boolean }>` ${(props) => props.highlightBottom && ` // styled-components doesn't seem to prefix linear-gradient.. soo background-image: linear-gradient(bottom, ${props.theme.greyLightest} 50%, transparent 50%); background-image: -o-linear-gradient(bottom, ${props.theme.greyLightest} 50%, transparent 50%); background-image: -moz-linear-gradient(bottom, ${props.theme.greyLightest} 50%, transparent 50%); background-image: -webkit-linear-gradient(bottom, ${props.theme.greyLightest} 50%, transparent 50%); background-image: -ms-linear-gradient(bottom, ${props.theme.greyLightest} 50%, transparent 50%); `} `; export const LOCATION_SEARCH_INPUT_NAME = "LocationSearchInput"; interface SearchBoxAndResultsProps { placeholder: string; } export const SearchBoxAndResults: FC = observer( ({ placeholder }) => { const locationSearchRef = useRef(null); const viewState = useViewState(); const theme = useTheme(); useEffect(() => { viewState.updateAppRef(LOCATION_SEARCH_INPUT_NAME, locationSearchRef); }, [viewState]); const toggleShowLocationSearchResults = action((bool: boolean) => { viewState.searchState.showLocationSearchResults = bool; }); const changeSearchText = (newText: string) => { runInAction(() => { viewState.searchState.locationSearchText = newText; }); if (newText.length === 0) { removeMarker(viewState.terria); runInAction(() => { toggleShowLocationSearchResults(false); }); } if ( newText.length > 0 && !viewState.searchState.showLocationSearchResults ) { runInAction(() => { toggleShowLocationSearchResults(true); }); } }; const search = () => { viewState.searchState.searchLocations(); }; const startLocationSearch = () => { toggleShowLocationSearchResults(true); }; const searchState = viewState.searchState; const locationSearchText = searchState.locationSearchText; const shouldShowResults = searchState.locationSearchText.length > 0 && searchState.showLocationSearchResults; return ( {/* Results */} {shouldShowResults && ( {/* search {searchterm} in data catalog */} {/* ~TODO: Put this back once we add a MobX DataCatalogSearch Provider~ */} {/* TODO2: Implement a more generic MobX DataCatalogSearch */} {viewState.terria.searchBarModel.showSearchInCatalog && searchState.catalogSearchProvider && ( { toggleShowLocationSearchResults(false); }} /> )} {!searchState.isWaitingToStartLocationSearch && searchState.locationSearchResults.map((search) => ( { if (!result.location) return; addMarker(viewState.terria, { name: result.name, location: result.location }); result.clickAction?.(); runInAction(() => { searchState.showLocationSearchResults = false; }); }} isWaitingForSearchToStart={ searchState.isWaitingToStartLocationSearch } /> ))} )} ); } ); SearchBoxAndResults.displayName = "SearchBoxAndResults"; export default SearchBoxAndResults;