Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React from 'react';
- import PropTypes from 'prop-types';
- import styled from 'styled-components';
- import { withApollo } from 'react-apollo';
- import debounce from 'lodash/debounce';
- import InputLoader from 'ui/atoms/loaders/input-loader/InputLoader';
- import { textCss } from 'ui/atoms/texts/base/style';
- import CustomScrollbar, { ScrollThumb } from 'ui/atoms/containers/custom-scrollbar/CustomScrollbar';
- import Overlay from 'ui/molecules/search-overlay/SearchOverlay';
- import SearchItem from 'ui/components/items/search-item/SearchItem';
- import ErrorText from 'ui/atoms/texts/error-text/ErrorText';
- import SearchResultsHeading from 'ui/molecules/search-results-heading/SearchResultsHeading';
- import SearchInput from 'ui/molecules/search-input/SearchInput';
- import TabList from 'ui/organisms/tab-list/TabList';
- import LangContext from 'ui/context/lang/LangContext';
- import SearchOverlayContext from 'app/structure/search-overlay/SearchOverlayContext';
- import { openModal } from 'app/structure/modal/utils';
- import View from 'app/structure/view/View';
- import searchQuery from 'graphql/queries/search';
- const ContainerSearch = styled.div`
- position: relative;
- `;
- const TotalResults = styled.span`
- ${textCss};
- margin-top: 15px;
- display: block;
- `;
- const StyledOverlay = styled(Overlay)`
- position: fixed;
- width: 100%;
- height: 100%;
- z-index: 50;
- `;
- const ResultContainer = styled.div`
- display: flex;
- flex-direction: column;
- flex: 1;
- height: 633px;
- ${ScrollThumb} {
- right: 9px;
- top: 13px;
- };
- `;
- const Heading = styled(SearchResultsHeading)`
- padding: 0 15px;
- `;
- const DataContainer = styled.div`
- background: ${({ theme }) => theme.colors.lightgray};
- padding: 15px;
- border-radius: 15px;
- `;
- const Tabs = styled(TabList)`
- margin-top: 5px;
- margin-bottom: 40px;
- .Tab:last-child {
- }
- `;
- const Item = styled(SearchItem)`
- margin-bottom: 15px;
- `;
- const AllResultsContainer = styled.div`
- display: flex;
- `;
- const Loader = styled(InputLoader)`
- &::after {
- position: absolute;
- bottom: 1px;
- }
- `;
- export const getSearchInputQuery = () => {
- return searchQuery([
- { 'datatypes': ['key', 'value'] },
- { 'results': [
- 'iddatatype',
- 'title',
- 'summary',
- 'thumb',
- {
- 'status': [
- 'title',
- 'uik',
- 'color'
- ]
- }
- ] }
- ]);
- };
- export const debounceSearchDelay = 1000;
- /**
- *
- * Search Input[SearchInput](http://styleguide.yoomap.tech/#!/SearchInput)
- *
- * @exports: __ getSearchInputQuery() __
- */
- class SearchOverlay extends React.Component {
- static displayName = 'SearchOverlay';
- static propTypes = {
- /** Client React */
- client: PropTypes.object,
- /** Number of [ui/molecules/Tab](#!/Tab) selected */
- activeTabCount: PropTypes.number,
- /** Min characters for search */
- minCaracters: PropTypes.number
- };
- static contextType = SearchOverlayContext;
- state = {
- search: '',
- searchdata: '',
- index: 0,
- isLoading: false,
- error: false,
- isEmpty: false
- };
- static defaultProps = {
- activeTabCount: 3,
- minCaracters: 3
- };
- getData = debounce((search) => {
- const { client, minCaracters } = this.props;
- if (search.length >= minCaracters) {
- this.setState({ isLoading: true });
- client.query({
- query: getSearchInputQuery(),
- variables: { searchString: search }
- })
- .then(res => {
- this.setState({ isLoading: false, error: false });
- this.setSearchData(res);
- });
- } else {
- this.setState({ error: true });
- }
- }, debounceSearchDelay);
- handleTabClick = obj => {
- const { searchdata } = this.state;
- // Get index of the clicked obj in newResults array
- const index = searchdata.findIndex(result => result.datatype === obj.id);
- this.setState({ index });
- };
- handleClear = () => {
- this.setState({ search: '', searchdata: [], isEmpty: false });
- }
- setQuery = (e) => {
- const { minCaracters } = this.props;
- const search = e.currentTarget.value;
- const doSearch = search.length >= minCaracters;
- const state = doSearch
- ? { search }
- : { search, searchdata: [] };
- this.setState(state);
- if (!search) {
- this.setState({ error: false, isEmpty: true });
- } else {
- this.getData(search);
- }
- }
- getMinMax = () => {
- let min;
- let max;
- const { index, searchdata } = this.state;
- const { activeTabCount } = this.props;
- max = index + (activeTabCount - 1);
- if (max > this.state.searchdata.length - 1) {
- max = searchdata.length - 1;
- }
- min = min < 0 ? 0 : max - 2;
- return { min, max };
- }
- renderTabList = (min, max) => {
- const { searchdata } = this.state;
- const tabs = searchdata.map((result, i) => {
- return {
- id: result.datatype,
- text: result.datatype,
- active: i >= min && i <= max,
- count: result.count
- };
- });
- return <Tabs tabs={tabs} onTabClick={this.handleTabClick} />;
- };
- resultsCount = () => {
- const { searchdata } = this.state;
- if (searchdata.length < 1) {
- return null;
- }
- return searchdata.reduce((count, result) => result.items.length + count, 0);
- };
- // TODO: Temporary results JSON
- renderResultsItems = (min, max) => {
- const { searchdata } = this.state;
- return (
- <AllResultsContainer>
- {searchdata.slice(min, max + 1).map(
- (result, index) =>
- (
- <ResultContainer key={index}>
- <Heading count={result.count}>
- {result.datatype}
- </Heading>
- <CustomScrollbar>
- <DataContainer>
- {result.items.map((item, index) => (
- <Item
- onClick={() => this.openModal(item.iddatatype)}
- key={index}
- title={item.title}
- image={item.thumb}
- description='Lorem ipsum its a test'
- status={item.status.title}
- statusColor={item.status.color}
- />
- ))}
- </DataContainer>
- </CustomScrollbar>
- </ResultContainer>
- )
- )}
- </AllResultsContainer>
- );
- };
- setSearchData = ({ data }) => {
- if (!(data && data.search && data.search.datatypes)) {
- return null;
- }
- const { datatypes, results } = data.search;
- const res = results.reduce(function(obj, result) {
- const key = result.iddatatype;
- if (!obj[key]) {
- obj[key] = [];
- }
- obj[key].push(result);
- return obj;
- }, {});
- const searchdata = datatypes.map(({ key, value }, index) => ({
- datatype: value,
- count: res[key] ? res[key].length : 0,
- items: res[key]
- }));
- this.setState({ searchdata });
- };
- renderError = (contextTypes) => {
- return (
- <ErrorText>
- {contextTypes.lang.errors.minCaracter}
- </ErrorText>
- );
- }
- renderTotalResults = (contextTypes) => {
- const { error, searchdata } = this.state;
- return (
- <TotalResults>
- {error && this.renderError(contextTypes)}
- {searchdata.length > 0 &&
- this.resultsCount() + ' ' + contextTypes.lang.common.results
- }
- </TotalResults>
- );
- }
- renderSearchResults = () => {
- const { min, max } = this.getMinMax();
- const { searchdata } = this.state;
- return (
- <React.Fragment>
- <LangContext.Consumer>
- {this.renderTotalResults}
- </LangContext.Consumer>
- {searchdata.length > 0 &&
- <React.Fragment>
- {this.renderTabList(min, max)}
- {this.renderResultsItems(min, max)}
- </React.Fragment>
- }
- </React.Fragment>
- );
- }
- openModal(id) {
- openModal({
- id,
- title: 'nop',
- render: () => <View id={id} />
- });
- }
- renderOverlay = ({ hideOverlay }) => {
- const { isEmpty, isLoading, search, error } = this.state;
- return (
- <StyledOverlay onClose={hideOverlay}>
- <ContainerSearch>
- <SearchInput
- error={error || error}
- isEmpty={isEmpty || isEmpty}
- value={search}
- onClear={this.handleClear}
- onChange={this.setQuery}
- />
- {isLoading && <Loader error={error || error} />}
- </ContainerSearch>
- {this.renderSearchResults()}
- </StyledOverlay>
- );
- };
- render() {
- return (
- <SearchOverlayContext.Consumer>
- {this.renderOverlay}
- </SearchOverlayContext.Consumer>
- );
- }
- }
- export default withApollo(SearchOverlay);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement