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;