react-instantsearch-dom#Hits JavaScript Examples

The following examples show how to use react-instantsearch-dom#Hits. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js    From my-personal-blog-gatsby with MIT License 6 votes vote down vote up
Search = ({ algolia }) => {
  const searchClient = algoliasearch(algolia.appId, algolia.searchOnlyApiKey);

  return (
    <s.SearchWrapper>
      <InstantSearch searchClient={searchClient} indexName={algolia.indexName}>
        <SearchBox autoFocus translations={{ placeholder: 'Pesquisar...' }} />

        <Stats
          translations={{
            stats(nbHits, timeSpentMs) {
              return `${nbHits} resultados encontrados em ${timeSpentMs}ms`;
            },
          }}
        />
        <Hits hitComponent={Hit} />
      </InstantSearch>
    </s.SearchWrapper>
  );
}
Example #2
Source File: index.js    From gatsby-plugin-typesense with Apache License 2.0 6 votes vote down vote up
export default function Home() {
  const Hit = ({ hit }) => (
    <p>
      {hit.title} - {hit.description}
    </p>
  )

  return (
    <div>
      <Header pageName="Home" />
      <div data-typesense-field={"description"}>
        This is some home page content
      </div>

      <InstantSearch searchClient={searchClient} indexName="pages_v1">
        <SearchBox />
        <Stats />
        <Hits hitComponent={Hit} />
      </InstantSearch>

      <Footer />
    </div>
  )
}
Example #3
Source File: MobileSearch.component.jsx    From nextjs-woocommerce with GNU General Public License v3.0 6 votes vote down vote up
MobileSearch = () => {
  const [search, setSearch] = useState(null);
  const [hasFocus, sethasFocus] = useState(false);
  return (
    <div className="inline mt-4 md:hidden">
      <InstantSearch
        indexName={process.env.NEXT_PUBLIC_ALGOLIA_INDEX_NAME}
        searchClient={searchClient}
      >
        <SearchBox
          translations={{
            submitTitle: 'Søk',
            resetTitle: 'Slett søketekst',
            placeholder: 'Søk etter produkter',
          }}
          className={`px-4 py-2 text-base bg-white border outline-none rounded ${
            hasFocus ? 'border-black' : 'border-gray-400'
          }`}
          onFocus={() => {
            sethasFocus(true);
          }}
          onBlur={() => {
            sethasFocus(false);
          }}
          onReset={() => {
            setSearch(null);
          }}
          onChange={(text) => {
            setSearch(text.target.value);
          }}
        />
        {search && <Hits className="absolute" hitComponent={SearchResults} />}
      </InstantSearch>
    </div>
  );
}
Example #4
Source File: Search.js    From adarshaacharya.com.np with MIT License 5 votes vote down vote up
Search = ({ props }) => {
  const { location } = props;

  const [searchState, setSearchState] = React.useState(
    urlToSearchState(location)
  );

  const onSearchStateChange = updatedSearchState => {
    setSearchState(updatedSearchState);
  };

  const searchClient = algoliasearch(
    process.env.GATSBY_ALGOLIA_APP_ID,
    process.env.GATSBY_ALGOLIA_SEARCH_KEY
  );

  return (
    <StyledSearch>
      <InstantSearch
        indexName={process.env.GATSBY_ALGOLIA_INDEX_NAME}
        searchClient={searchClient}
        searchState={searchState}
        onSearchStateChange={onSearchStateChange}
      >
        <SearchBox
          translations={{
            placeholder: 'Search by title, tags or description..',
          }}
        />

        {searchState && searchState.query ? (
          <>
            <Stats
              translations={{
                stats(nbHits) {
                  return `${nbHits} Results found`;
                },
              }}
            />

            <Hits hitComponent={Hit} />
          </>
        ) : (
          <Posts />
        )}
      </InstantSearch>
    </StyledSearch>
  );
}
Example #5
Source File: index.js    From website with MIT License 5 votes vote down vote up
export default function Search({ indices, collapse, hitsAsGrid }) {
  const [query, setQuery] = useState(``)
  const [setFocus] = useState(false)
  const searchClient = algoliasearch(
    "V0X7Z4KE9D",
    "544bec33383dc791bcbca3e1ceaec11b"
  )
  return (
    <InstantSearch
      searchClient={searchClient}
      indexName={indices[0].name}
      onSearchStateChange={({ query }) => {
        if (typeof query !== "undefined") {
          setQuery(query)
        }
      }}
    >
      <div tw="relative shadow appearance-none border rounded w-full py-3 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-inner rounded-r-none">
        <SearchBox
          tw="w-full px-8"
          translations={{
            placeholder: "Find analysis tools, formatters, and linters...",
          }}
          startValue=""
          submit={
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="16"
              height="16"
              viewBox="0 0 18 18"
            >
              <g
                fill="none"
                fillRule="evenodd"
                stroke="currentColor"
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth="1.67"
                transform="translate(1 1)"
              >
                <circle cx="7.11" cy="7.11" r="7.11" />
                <path d="M16 16l-3.87-3.87" />
              </g>
            </svg>
          }
        />
      </div>
      {query && (
        <HitsWrapper
          show={query.length > 0}
          asGrid="false"
          tw="max-h-screen overflow-scroll border shadow bg-white absolute w-full"
        >
          {indices.map(({ name, title, hitComp }) => (
            <Index key={name} indexName={name}>
              <Results>
                <Hits hitComponent={hitComps[hitComp](() => setFocus(false))} />
              </Results>
            </Index>
          ))}
          <PoweredBy />
        </HitsWrapper>
      )}
    </InstantSearch>
  )
}
Example #6
Source File: index.js    From learningHub with MIT License 5 votes vote down vote up
export default function SearchComponent({ indices, collapse, hitsAsGrid }) {
  const ref = createRef();

  const [query, setQuery] = useState(``);

  const [focus, setFocus] = useState(false);

  const searchClient = algoliasearch(
    config.header.search.algoliaAppId,
    config.header.search.algoliaSearchKey
  );

  useClickOutside(ref, () => setFocus(false));
  const displayResult = query.length > 0 && focus ? 'showResults' : 'hideResults';

  return (
    <InstantSearch
      searchClient={searchClient}
      indexName={indices[0].name}
      onSearchStateChange={({ query }) => setQuery(query)}
      root={{ Root, props: { ref } }}
    >
      <Input onFocus={() => setFocus(true)} {...{ collapse, focus }} />
      <HitsWrapper
        className={'hitWrapper ' + displayResult}
        show={query.length > 0 && focus}
        asGrid={hitsAsGrid}
      >
        {indices.map(({ name, title, hitComp, type }) => {
          return (
            <Index key={name} indexName={name}>
              <Results />
              <Hits hitComponent={hitComps[hitComp](() => setFocus(false))} />
            </Index>
          );
        })}
        <PoweredBy />
      </HitsWrapper>
      <Configure hitsPerPage={5} />
    </InstantSearch>
  );
}
Example #7
Source File: RelatedSolutions.js    From plataforma-sabia with MIT License 5 votes vote down vote up
RelatedSolutions = ({ technology }) => {
	const { colors } = useTheme();
	const { t } = useTranslation(['common']);
	const [searchLength, setSearchLength] = useState({
		technology: 0,
		service: 0,
	});

	const filters = useMemo(() => {
		const keywords = technology.keywords
			.map((keyword) => `keywords:"${keyword.term.trim()}"`)
			.join(' OR ');

		return keywords.length ? `NOT objectID:"${technology.objectID}" AND (${keywords})` : '';
	}, [technology.keywords, technology.objectID]);

	return (
		<>
			{(!!searchLength.technology || !!searchLength.service) && (
				<SectionTitle bgColor={colors.whiteSmoke} noMargin>
					{t('common:relatedSolutions')}
				</SectionTitle>
			)}

			<AlgoliaSearchProvider indexName={algoliaDefaultConfig.technology.indexName}>
				<>
					<Configure filters={filters} maxFacetHits={4} />
					<Results
						type="technology"
						current={searchLength.technology}
						onChange={setSearchLength}
					/>

					{!!searchLength.technology && (
						<SolutionsWrapper bgColor={colors.whiteSmoke} overwriteAlgoliaStyles>
							<Hits
								hitComponent={connectHits(({ hit }) => (
									<SolutionCard type="technology" data={hit} />
								))}
							/>
						</SolutionsWrapper>
					)}
				</>
			</AlgoliaSearchProvider>

			<AlgoliaSearchProvider indexName={algoliaDefaultConfig.service.indexName}>
				<>
					<Configure filters={filters} maxFacetHits={4} />
					<Results
						type="service"
						current={searchLength.service}
						onChange={setSearchLength}
					/>

					{!!searchLength.service && (
						<SolutionsWrapper bgColor={colors.whiteSmoke} overwriteAlgoliaStyles>
							<Hits
								hitComponent={connectHits(({ hit }) => (
									<SolutionCard type="service" data={hit} />
								))}
							/>
						</SolutionsWrapper>
					)}
				</>
			</AlgoliaSearchProvider>
		</>
	);
}
Example #8
Source File: index.js    From plataforma-sabia with MIT License 5 votes vote down vote up
SolutionList = ({
	indexName,
	searchState,
	resultsState,
	onSearchStateChange,
	onSearchParameters,
	widgetsCollector,
}) => {
	const filters = '__meta__.technologies_count > 0 OR __meta__.services_count > 0';

	return (
		<AlgoliaSearchProvider
			indexName={indexName}
			searchState={searchState}
			resultsState={resultsState}
			onSearchStateChange={onSearchStateChange}
			onSearchParameters={onSearchParameters}
			widgetsCollector={widgetsCollector}
		>
			<ThemeProvider>
				<S.Wrapper>
					<S.Container>
						<S.Top>
							<S.Title>Organização</S.Title>
							<DebouncedSearchBox
								placeholder="Qual instituição você busca?"
								secondary
							/>
							<S.SortWrapper>
								<HitsPerPage
									items={[
										{
											label: `${ITEMS_PER_PAGE} resultados por página`,
											value: ITEMS_PER_PAGE,
										},
									]}
									defaultRefinement={ITEMS_PER_PAGE}
								/>
							</S.SortWrapper>
						</S.Top>
						<S.Content>
							<Configure filters={filters} />

							<ScrollTo>
								<Hits hitComponent={HitCard} />
							</ScrollTo>
						</S.Content>
						<Pagination />
					</S.Container>
				</S.Wrapper>
			</ThemeProvider>
		</AlgoliaSearchProvider>
	);
}
Example #9
Source File: AlgoliaSearchBox.component.jsx    From nextjs-woocommerce with GNU General Public License v3.0 5 votes vote down vote up
AlgoliaSearchBox = () => {
  const [search, setSearch] = useState(null);
  const [hasFocus, sethasFocus] = useState(false);

  return (
    <div className="hidden mt-2 md:inline xl:inline">
      <div className="">
        <InstantSearch
          indexName={process.env.NEXT_PUBLIC_ALGOLIA_INDEX_NAME}
          searchClient={searchClient}
        >
          {/*We need to conditionally add a border because the element has position:fixed*/}
          <SearchBox
            aria-label="Søk her"
            translations={{
              submitTitle: 'Søk',
              resetTitle: 'Slett søketekst',
              placeholder: 'Søk etter produkter',
            }}
            className={`px-4 py-2 text-base bg-white border outline-none rounded ${
              hasFocus ? 'border-black' : 'border-gray-400'
            }`}
            onFocus={() => {
              sethasFocus(true);
            }}
            onBlur={() => {
              sethasFocus(false);
            }}
            onReset={() => {
              setSearch(null);
            }}
            onChange={(text) => {
              setSearch(text.target.value);
            }}
          />
          {search && <Hits className="absolute" hitComponent={SearchResults} />}
        </InstantSearch>
      </div>
    </div>
  );
}
Example #10
Source File: AlgoliaProductList.jsx    From emprezzo with MIT License 4 votes vote down vote up
AlgoliaProductList = ({ defaultFilter, defaultSearchTerm, itemsPerPage, hideLeftPanel, hideCTAButton, showClearFilter, facetsToShow, showSearchBox, showSearchSuggestions, searchIndexName, enableShopProductSwitch, enableCart, noResultMessage }) => {

  const [currentIndexName, setCurrentIndexName] = React.useState(searchIndexName || `empProducts`)
  const changeCurrentIndexName = (e) => { setCurrentIndexName(e.target.value); setCurrentSuggestionIndexName(getSuggestionIndex(e.target.value)); setSuggestionQuery(''); }

  const getSuggestionIndex = (mainIndexName) => {
    if (mainIndexName == 'empProducts') return ('empProducts_query_suggestions');
    if (mainIndexName == 'uncommonry') return ('uncommonry_query_suggestions')
  }
  const [currentSuggestionIndexName, setCurrentSuggestionIndexName] = React.useState(getSuggestionIndex(currentIndexName))
  const [suggestionQuery, setSuggestionQuery] = React.useState();

  const algoliaClient = algoliasearch(
    process.env.GATSBY_ALGOLIA_APP_ID,
    process.env.GATSBY_ALGOLIA_SEARCH_KEY
  );
  const searchClient = {
    search(requests) {
      if (requests.length > 0 && defaultSearchTerm) requests[0].params.query = defaultSearchTerm
      return algoliaClient.search(requests);
    },
  };
  noResultMessage = noResultMessage || `No result found`;
  enableCart = enableCart || false;
  itemsPerPage = itemsPerPage || 12;
  
  aa('init', {
    appId: process.env.GATSBY_ALGOLIA_APP_ID,
    apiKey: process.env.GATSBY_ALGOLIA_SEARCH_KEY
  });

  const [currentHitComponent, setCurrentHitComponent] = React.useState();
  React.useEffect(() => {
    if (currentIndexName == 'empProducts') setCurrentHitComponent(() => connectHitInsights(aa)(AlgoliaProductItem));
    if (currentIndexName == 'uncommonry') setCurrentHitComponent(() => connectHitInsights(aa)(AlgoliaUncommonryItem));
    if (currentIndexName == 'emails') setCurrentHitComponent(() => connectHitInsights(aa)(AlgoliaEmailsItem));
  }, [currentIndexName]);

  const AlgoliaSuggestions = ({ hit }) => {
    return (
      <a href="javascript:" onClick={() => setSuggestionQuery(hit.query)}>{hit.query}</a>
    );
  }

  return (
    <SearchWrapper>
      {!enableCart &&
        <Global
          styles={css`
            .cart-section {
              display: none;
            }
        `}
        />
      }
      <InstantSearch indexName={currentIndexName} searchClient={searchClient}>
        <VirtualSearchBox defaultRefinement={suggestionQuery} />
        {!hideLeftPanel &&
          <LeftPanel>

            {showClearFilter &&
              <ClearRefinements />
            }
            {facetsToShow && facetsToShow.indexOf("category") >= 0 &&
              <>
                <FilterHeading>Category</FilterHeading>
                <RefinementList attribute="shopCategory" showMore='true' limit='5' />
              </>
            }
            {facetsToShow && facetsToShow.indexOf("brands") >= 0 && currentIndexName != 'uncommonry' &&
              <>
                <FilterHeading>Brands</FilterHeading>
                <RefinementList attribute="shopName" showMore='true' limit='5' />
              </>
            }
            {facetsToShow && facetsToShow.indexOf("payments") >= 0 && currentIndexName == 'uncommonry' &&
              <>
                <FilterHeading>Payments</FilterHeading>
                <RefinementList
                  attribute="shopifyPay"
                  transformItems={items =>
                    items.filter(item => (item.label == '1')).map(item => ({
                      ...item,
                      label: "Shop Pay",
                    }))
                  }
                />
                <RefinementList
                  attribute="paypal"
                  transformItems={items =>
                    items.filter(item => (item.label == '1')).map(item => ({
                      ...item,
                      label: "Paypal",
                    }))
                  }
                />
                <RefinementList
                  attribute="applePay"
                  transformItems={items =>
                    items.filter(item => (item.label == '1')).map(item => ({
                      ...item,
                      label: "Apple Pay",
                    }))
                  }
                />
                <RefinementList
                  attribute="amazonPay"
                  transformItems={items =>
                    items.filter(item => (item.label == '1')).map(item => ({
                      ...item,
                      label: "Amazon Pay",
                    }))
                  }
                />
              </>
            }
            {facetsToShow && facetsToShow.indexOf("pricerangeslider") >= 0 && currentIndexName == 'uncommonry' &&
              <>
                <FilterHeading>Average Price</FilterHeading>
                <AlgoliaRangeSlider attribute="price" />
              </>
            }
            {facetsToShow && facetsToShow.indexOf("prices") >= 0 && currentIndexName == 'empProducts' &&
              <>
                <FilterHeading>Prices</FilterHeading>
                <NumericMenu
                  attribute="price"
                  items={[
                    { label: 'All' },
                    { label: 'Under $50', end: 50 },
                    { label: '$50 - $100', start: 50, end: 100 },
                    { label: '$100 - $200', start: 100, end: 200 },
                    { label: '$200+', start: 200 },
                  ]}
                />
              </>
            }
            {/*
            {facetsToShow && facetsToShow.indexOf("giftcard") >= 0 && currentIndexName == 'empProducts' &&
              <>
                <FilterHeading>Gift Card</FilterHeading>
                <RefinementList
                  attribute="name"
                  transformItems={items =>
                    items.filter(item => (item.label.toLowerCase().indexOf('gift') >= 0))
                  }
                />
              </>
            }
            {facetsToShow && facetsToShow.indexOf("gifimage") >= 0 && currentIndexName == 'empProducts' &&
              <>
                <FilterHeading>GIF</FilterHeading>
                <RefinementList
                  attribute="imageURL"
                  transformItems={items =>
                    items.filter(item => (item.label.indexOf('.gif') >= 0)).map(item => ({
                      ...item,
                      label: "GIF",
                    }))
                  }
                />
              </>
            }
            */}

            {facetsToShow && facetsToShow.indexOf("storeoffers") >= 0 &&
              <>
                <FilterHeading>Store Offers</FilterHeading>
                <RefinementList
                  attribute="freeShipMin"
                  transformItems={items =>
                    items.filter(item => (item.label == 0)).map(item => ({
                      ...item,
                      label: "Free Shipping",
                    }))
                  }
                />
                <RefinementList
                  attribute="returnShipFree"
                  transformItems={items =>
                    items.filter(item => (item.label == 'Yes')).map(item => ({
                      ...item,
                      label: "Free Returns",
                    }))
                  }
                />
              </>
            }
          </LeftPanel>
        }
        <RightPanel>
          <Configure clickAnalytics={true} hitsPerPage={itemsPerPage} filters={defaultFilter} />
          <div class="searchline">
            <div class="indexSelect">
              {enableShopProductSwitch &&
                <div style={{ paddingBottom: '0.75rem' }}>
                  <select value={currentIndexName} onChange={changeCurrentIndexName}>
                    <option value="uncommonry">Shops</option>
                    <option value="empProducts">Products</option>
                  </select>
                </div>
              }
            </div>
            {facetsToShow && facetsToShow.indexOf("onsale") >= 0 &&
              <div class="saleFacet">
                <RefinementList
                  attribute="onSale"
                  transformItems={items =>
                    items.filter(item => (item.label == '1')).map(item => ({
                      ...item,
                      label: "On Sale",
                    }))
                  }
                />
              </div>
            }
          <div class="searchContainer">
            {showSearchBox &&
              <>
                <SearchBox defaultRefinement={suggestionQuery} />
              </>
            }<br style={{ clear: 'both' }} />
  {showSearchSuggestions && currentSuggestionIndexName &&
    <span style={{ 'font-weight': 'bold', 'padding': '0 1em 1em 0' }}>Trending </span>
  }
            {showSearchSuggestions && currentSuggestionIndexName &&

              <div className="suggestions">

                <InstantSearch
                  searchClient={searchClient}
                  indexName={currentSuggestionIndexName}
                >
                  <Configure hitsPerPage={5} />
                  <InfiniteHits hitComponent={AlgoliaSuggestions} />
                </InstantSearch>
              </div>
            }
            </div>
            {!hideCTAButton &&
              <div class="giftCard">
                <BuyGiftCard />
              </div>
            }
          </div>

          <AlgoliaStateResults noResultMessage={noResultMessage} />
          <Hits hitComponent={currentHitComponent} />
          <Pagination />
        </RightPanel>
      </InstantSearch>
    </SearchWrapper>
  );
}
Example #11
Source File: index.js    From showcase-nextjs-typesense-ecommerce-store with Apache License 2.0 4 votes vote down vote up
export default function Home({
                               searchClient = typesenseInstantsearchAdapter.searchClient,
                               searchState,
                               resultsState,
                               onSearchParameters,
                               widgetsCollector,
                               ...props
                             }) {
  return (
    <div>
      <Head>
        <title>Ecommerce Store with Typesense + Next.js + Vercel</title>
        <link rel="icon" href="/favicon.png"/>
      </Head>

      <main>
        <InstantSearch indexName="products"
                       {...props}
                       searchClient={searchClient}
                       searchState={searchState}
                       resultsState={resultsState}
                       onSearchParameters={onSearchParameters}
                       widgetsCollector={widgetsCollector}>
          <div className="container-fluid px-md-5 pt-4">
            <div className="row d-flex align-items-center">
              <div className="col-md">
                <h1 className="display-6">
                  Ecommerce Store with Typesense + Next.js + Vercel
                </h1>
              </div>
              <div className="col-md-2 d-none d-md-block">
                <SearchBox/>
              </div>
            </div>

            <div className="lead mt-2">
              Besides search experiences,
              Typesense can also be used to build <strong className="marker-highlight">blazing fast</strong>, <strong
              className="marker-highlight">browsing
              experiences</strong> like
              product listing pages in an ecommerce
              store.
            </div>
            <ul className="lead mt-1">
              <li>Product data to render the grid is fetched by the front-end from a <strong>Geo-Distributed Typesense
                Cloud cluster</strong> with nodes in Oregon, Frankfurt and Mumbai.
              </li>
              {/* eslint-disable-next-line react/no-unescaped-entities */}
              <li>Product API Requests are routed to the node that is closest to the user's location, like a CDN. Since
                data is geographically distributed, this reduces latency even more for your users, as they browse
                products.
              </li>
              <li>The front-end uses Next.js, is statically generated and is hosted on Vercel.</li>
              <li>See <a href="https://github.com/typesense/showcase-nextjs-typesense-ecommerce-store" target="_blank"
                         rel="noreferrer">Source
                Code</a>.
              </li>
            </ul>

            <div className="row mt-4">
              <div className="col-md-3 pr-md-5">
                <h5>Browse by Categories</h5>
                <HierarchicalMenu
                  className="mt-3"
                  attributes={[
                    'categories.lvl0',
                    'categories.lvl1',
                    'categories.lvl2',
                    'categories.lvl3',
                  ]}
                  showParentLevel={true}
                  rootPath={"Cell Phones"}
                  limit={50}
                />

                <h5 className="mt-5">Filter by Brands</h5>
                <RefinementList
                  className="mt-3"
                  attribute="brand"
                  limit={10}
                  showMore={true}
                  showMoreLimit={50}
                  searchable={true}
                  transformItems={items =>
                    items.sort((a, b) => a.label > b.label ? 1 : -1)
                  }
                />

                <div className="mt-2">&nbsp;</div>

                <ToggleRefinement
                  className="mt-5"
                  attribute="free_shipping"
                  label="Free Shipping"
                  value={true}
                />

                <div className="mt-1">&nbsp;</div>

                <h5 className="mt-5">Filter by Price</h5>
                <RangeSlider attribute="price"/>

                <div className="mt-1">&nbsp;</div>

                <h5 className="mt-5">Filter by Rating</h5>
                <RatingMenu
                  className="mt-3"
                  attribute="rating"
                />

                <div className="mt-1">&nbsp;</div>

                <ClearRefinements className="mt-5"/>
              </div>
              <div className="col-md">

                <div className="row mt-5 mt-md-0">
                  <div className="col-md">
                    <div className="row">
                      <div className="col-md-4">
                      </div>
                      <div className="col-md-8 d-flex justify-content-end align-items-center">
                        <Stats translations={{
                          stats(nbHits, processingTimeMS) {
                            let hitCountPhrase
                            if (nbHits === 0) {
                              hitCountPhrase = 'No products'
                            } else if (nbHits === 1) {
                              hitCountPhrase = '1 product'
                            } else {
                              hitCountPhrase = `${nbHits.toLocaleString()} products`
                            }
                            return `${hitCountPhrase} found in ${processingTimeMS.toLocaleString()}ms`;
                          },
                        }}/>
                        <HitsPerPage
                          className="ms-4"
                          items={[
                            {label: '9 per page', value: 9},
                            {label: '18 per page', value: 18}
                          ]}
                          defaultRefinement={9}
                        />
                        <SortBy
                          items={[
                            {label: 'Relevancy', value: 'products'},
                            {label: 'Price (asc)', value: 'products/sort/price:asc'},
                            {label: 'Price (desc)', value: 'products/sort/price:desc'},
                          ]}
                          defaultRefinement="products"
                        />
                      </div>
                    </div>
                  </div>
                </div>

                <div className="row mt-1">
                  <div className="col-sm">
                    <Hits hitComponent={Hit}/>
                  </div>
                </div>

                <div className="row">
                  <div className="col-sm">
                    <Pagination/>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </InstantSearch>
      </main>
    </div>
  )
}
Example #12
Source File: MainSearch.js    From plataforma-sabia with MIT License 4 votes vote down vote up
MainSearch = ({
	searchState,
	resultsState,
	onSearchStateChange,
	createURL,
	onSearchParameters,
	widgetsCollector,
}) => {
	const { t } = useTranslation(['search', 'common']);
	const [openMobileFilters, setOpenMobileFilters] = useState(false);

	const tabs = useMemo(() => getTabs(t), [t]);
	const solutionsComponents = useMemo(() => getSolutionsComponents(t), [t]);

	const [activeSolutionTab, setActiveSolutionTab] = useState(
		tabs.find((tab) => tab.slug === searchState.solution)?.slug || 'technologies',
	);

	const handleOpenMobileFilters = () => {
		setOpenMobileFilters(true);
		window.scrollTo({ top: 0 });
	};

	return (
		<AlgoliaSearchProvider
			indexName={solutionsComponents[activeSolutionTab].indexName}
			widgetsCollector={widgetsCollector}
			searchState={searchState}
			resultsState={resultsState}
			onSearchStateChange={onSearchStateChange}
			createURL={createURL}
			onSearchParameters={onSearchParameters}
		>
			<ThemeProvider>
				<ScrollTo alignToTop={false} scrollOn="query">
					<DebouncedSearchBox placeholder={t('search:searchPlaceholder')} />
				</ScrollTo>
				<Wrapper>
					<Container
						onSelect={(index) => {
							setActiveSolutionTab(tabs[index].slug);
						}}
						selectedIndex={tabs.findIndex((tab) => tab.slug === activeSolutionTab)}
					>
						<FilterContainer openMobile={openMobileFilters}>
							<FilterContainerHeader>
								<h2>{t('common:filters')}</h2>
								<ClearRefinements placeholder={t('common:clear')} />
								<MobileCloseButton onClick={() => setOpenMobileFilters(false)}>
									<AiOutlineClose />
								</MobileCloseButton>
							</FilterContainerHeader>
							<Stats />
							<FilterContainerBody>
								{solutionsComponents[activeSolutionTab].filters.map((filter) => (
									<Panel key={filter.header} header={filter.header}>
										<filter.component
											{...filter.componentProps}
											placeholder={filter.componentProps.placeholder}
											label={filter.componentProps.label}
										/>
									</Panel>
								))}
								<MobileButtonsContainer>
									<ResultsButton onClick={() => setOpenMobileFilters(false)} />
									<ClearFiltersButton />
								</MobileButtonsContainer>
							</FilterContainerBody>
						</FilterContainer>
						<ResultsContainer>
							<TabsHeader>
								<TabList>
									{tabs.map((tab) => (
										<Tab key={tab.slug} data-testid={tab.id}>
											{tab.label}
										</Tab>
									))}
								</TabList>
							</TabsHeader>

							{tabs.map((tab) => (
								<TabPanel key={tab.id}>
									<ResultsContainerHeader>
										<SortBy
											defaultRefinement={
												tab.components.sortBy.defaultRefinement
											}
											items={tab.components.sortBy.items.map((item) => ({
												label: item.label,
												value: item.value,
											}))}
										/>
										<HitsPerPage
											items={[
												{
													label: t('search:perPage', { results: 12 }),
													value: 12,
												},
												{
													label: t('search:perPage', { results: 24 }),
													value: 24,
												},
												{
													label: t('search:perPage', { results: 36 }),
													value: 36,
												},
											]}
											defaultRefinement={12}
										/>
									</ResultsContainerHeader>
									<HitsWrapper>
										<Hits hitComponent={tab.components.hits.hitComponent} />
									</HitsWrapper>
								</TabPanel>
							))}

							<MobileFilterButton onClick={handleOpenMobileFilters}>
								{t('search:filter')}
							</MobileFilterButton>
							<ResultsFooter>
								<Pagination />
							</ResultsFooter>
						</ResultsContainer>
					</Container>
				</Wrapper>
			</ThemeProvider>
		</AlgoliaSearchProvider>
	);
}
Example #13
Source File: index.js    From plataforma-sabia with MIT License 4 votes vote down vote up
SolutionList = ({
	indexName,
	searchState,
	resultsState,
	onSearchStateChange,
	onSearchParameters,
	widgetsCollector,
	institutionId,
}) => {
	const [searchLength, setSearchLength] = useState({
		technology: 0,
		service: 0,
	});
	const theme = useTheme();

	const filters = `institution_id:"${institutionId}"`;

	return (
		<AlgoliaSearchProvider
			indexName={indexName}
			searchState={searchState}
			resultsState={resultsState}
			onSearchStateChange={onSearchStateChange}
			onSearchParameters={onSearchParameters}
			widgetsCollector={widgetsCollector}
		>
			<ThemeProvider>
				<S.Wrapper>
					<S.Container>
						<S.Top>
							<S.Title>Vitrine tecnológica</S.Title>
							<DebouncedSearchBox placeholder="Qual solução você busca?" secondary />
							<S.SortWrapper>
								<HitsPerPage
									items={[
										{
											label: `${ITEMS_PER_PAGE} resultados por página`,
											value: ITEMS_PER_PAGE,
										},
									]}
									defaultRefinement={ITEMS_PER_PAGE}
								/>
							</S.SortWrapper>
						</S.Top>
						<S.Content>
							<Index indexName={algoliaDefaultConfig.technology.indexName}>
								<Configure filters={filters} />
								<Results
									type="technology"
									current={searchLength.technology}
									onChange={setSearchLength}
								/>

								{!!searchLength.technology && (
									<ScrollTo>
										<SolutionsWrapper
											containerPadding="3.2rem 0"
											header="Tecnologias em destaque"
											headerComponent="title"
											headerProps={{
												align: 'left',
												color: theme.colors.silver,
												centerInMobile: true,
											}}
											algoliaCustomCss={S.algoliaListCss}
											overwriteAlgoliaStyles
										>
											<Hits
												hitComponent={connectHits(({ hit }) => (
													<SolutionCard type="technology" data={hit} />
												))}
											/>
										</SolutionsWrapper>
										<Pagination />
									</ScrollTo>
								)}
							</Index>

							<Index indexName={algoliaDefaultConfig.service.indexName}>
								<Configure filters={filters} />
								<Results
									type="service"
									current={searchLength.service}
									onChange={setSearchLength}
								/>
								{!!searchLength.service && (
									<ScrollTo>
										<SolutionsWrapper
											containerPadding="3.2rem 0"
											header="Serviços em destaque"
											headerComponent="title"
											headerProps={{
												align: 'left',
												color: theme.colors.silver,
												centerInMobile: true,
											}}
											algoliaCustomCss={S.algoliaListCss}
											overwriteAlgoliaStyles
										>
											<Hits
												hitComponent={connectHits(({ hit }) => (
													<SolutionCard type="service" data={hit} />
												))}
											/>
										</SolutionsWrapper>
										<Pagination />
									</ScrollTo>
								)}
							</Index>
						</S.Content>
					</S.Container>
				</S.Wrapper>
			</ThemeProvider>
		</AlgoliaSearchProvider>
	);
}