Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autocomplete not creating correct urls in nextjs. #6000

Open
1 task done
dharmveer97 opened this issue Jan 16, 2024 · 1 comment
Open
1 task done

Autocomplete not creating correct urls in nextjs. #6000

dharmveer97 opened this issue Jan 16, 2024 · 1 comment
Labels
Library: React InstantSearch ≥ 7 Issues in any of the react-instantsearch@7 packages (formerly named react-instantsearch-hooks) Type: Question

Comments

@dharmveer97
Copy link

🐛 Current behavior

Routing is not correct how to create custom URLs according to search text

🔍 Steps to reproduce

import { useConnector } from 'react-instantsearch';

Live reproduction

InstantSearch.js

💭 Expected behavior

'use client';

import { useState, useMemo } from 'react';
import { useConnector } from 'react-instantsearch';
import connectAutocomplete from 'instantsearch.js/es/connectors/autocomplete/connectAutocomplete';
import { uniqBy } from 'lodash';
import { ModalFooter, Button, Chip } from '@nextui-org/react';
import { usePathname, useRouter } from 'next/navigation';
import ModalBox from '../elements/Modal';
import InputGroup from '../elements/TextInput';

export function useAutocomplete(props) {
  return useConnector(connectAutocomplete, props);
}

const getLabeledArray = (flattenedArray) =>
  uniqBy(flattenedArray, 'title').map((item) => ({
    label: item.title,
    value: item.title,
    slug: item.slug,
    categories: item?.categories || [],
  }));

const updateSearchQuery = (pathName, router, refine, shopPath, value) => {
  if (pathName !== shopPath) {
    router.push(`${shopPath}?prod_shdevices%5Bquery%5D=${value}`);
  } else {
    refine(value);
  }
};

const SHOP_PATH = '/shop';

const getListBoxItemClasses = () =>
  'text-left hover:opacity-80 hover:bg-gray-300 !dark:text-white dark:hover:bg-gray-800 ' +
  'flex group gap-2 items-center justify-between relative px-2 py-1.5 w-full h-full ' +
  'box-border rounded-small subpixel-antialiased tap-highlight-transparent outline-none ' +
  'data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus ' +
  'data-[focus-visible=true]:outline-offset-2 data-[focus-visible=true]:dark:ring-offset-background-content1 ' +
  'data-[hover=true]:transition-colors data-[hover=true]:bg-default data-[hover=true]:text-default-foreground ' +
  'data-[selectable=true]:focus:bg-default data-[selectable=true]:focus:text-default-foreground cursor-pointer text-sm';

const SearchResultsList = ({ items, onClick, onClose }) => (
  <div className="-mb-2 max-h-72 scroll-py-2 overflow-y-auto py-2 text-sm">
    {items.map((item, i) => {
      const key = `${i}${item?.label}`;
      return (
        <SearchResultItem
          key={key}
          item={item}
          onClick={onClick}
          onClose={onClose}
        />
      );
    })}
  </div>
);

const SearchResultItem = ({ item, onClick, onClose }) => (
  <div className={getListBoxItemClasses()} onClick={onClose}>
    <span onClick={() => onClick(item.label)}>{item.label}</span>
    {item?.categories &&
      item.categories.map((element) => (
        <Chip
          key={element.title}
          size="sm"
          onClick={() => onClick(element.title)}
        >
          {element.title}
        </Chip>
      ))}
  </div>
);

function SearchBarModal({ isOpen, onOpenChange, onClose, ...props }) {
  const pathName = usePathname();
  const router = useRouter();
  const { refine, indices } = useAutocomplete(props);
  const flattenedArray = useMemo(
    () => indices?.flatMap((index) => index.hits) || [],
    [indices],
  );

  const labeledArray = getLabeledArray(flattenedArray);
  const [query, setQuery] = useState('');

  const handleInputChange = (e) => {
    const value = e?.target?.value;
    setQuery(value);
    updateSearchQuery(pathName, router, refine, SHOP_PATH, value);
  };

  const handleListItemClick = (val) => {
    if (val) {
      updateSearchQuery(pathName, router, refine, SHOP_PATH, val);
    }
  };

  return (
    <ModalBox
      enableClickOutside
      isOpen={isOpen}
      onOpenChange={onOpenChange}
      title="Search new products..."
      size="3xl"
    >
      <div>
        <div>
          <InputGroup
            size="sm"
            placeholder="Search products..."
            onChange={handleInputChange}
            name="search"
          />
          {labeledArray.length > 0 && (
            <SearchResultsList
              items={labeledArray}
              onClick={handleListItemClick}
              onClose={onClose}
            />
          )}

          {query !== '' && labeledArray.length === 0 && (
            <div className="px-4 py-14 text-center sm:px-14">
              <p className="mt-4 text-sm">
                No people found using that search term.
              </p>
            </div>
          )}
        </div>
      </div>

      <ModalFooter className="!px-0">
        <Button color="default" variant="ghost" onPress={onClose}>
          Search
        </Button>
      </ModalFooter>
    </ModalBox>
  );
}

export default SearchBarModal;

import algoliasearch from 'algoliasearch/lite';
import { InstantSearchNext } from 'react-instantsearch-nextjs';
import { Configure } from 'react-instantsearch';

const searchClient = algoliasearch(
  process.env.ALGOLIA_APPLICATION_ID,
  process.env.ALGOLIA_ADMIN_KEY,
);

const Layout = ({ children }) => {
  const indexName = process.env.ALGOLIA_INDEX;
  return (
    <InstantSearchNext
      searchClient={searchClient}
      indexName={indexName}
      routing
    >
      <Configure
        // attributesToSnippet={['description:10']}
        snippetEllipsisText="…"
        // removeWordsIfNoResults="allOptional"
        filters="status:active"
      />
      {children}
    </InstantSearchNext>
  );
};

export default Layout;

Package version

 "react-instantsearch": "^7.5.0",     "react-instantsearch-nextjs": "^0.1.7",     "react-instantsearch-router-nextjs": "^7.5.0",

Operating system

maxOs 13.6.3

Browser

Ms. Edge

Code of Conduct

  • I agree to follow this project's Code of Conduct
@dharmveer97 dharmveer97 added the triage Issues to be categorized by the team label Jan 16, 2024
@Haroenv
Copy link
Contributor

Haroenv commented Jan 16, 2024

Thanks for sharing your code, but as this isn't runnable example, can you create what you have so far in a sandbox environment? We have a template available for that purpose here. Thanks!

Which URL is wrong that you're talking about? I see you have an updateSearchQuery that doesn't use InstantSearch so I'm confused to what exactly doesn't work

@Haroenv Haroenv added Type: Question Library: React InstantSearch ≥ 7 Issues in any of the react-instantsearch@7 packages (formerly named react-instantsearch-hooks) and removed triage Issues to be categorized by the team labels Jan 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Library: React InstantSearch ≥ 7 Issues in any of the react-instantsearch@7 packages (formerly named react-instantsearch-hooks) Type: Question
Projects
None yet
Development

No branches or pull requests

2 participants