|
1 | 1 | /* eslint-disable react/jsx-props-no-spreading */ |
2 | | -import { useCombobox } from 'downshift'; |
3 | | -import React, { useEffect, useState } from 'react'; |
4 | | -import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; |
5 | | -import { fetchAutoCompleteResults } from '../../utils'; |
6 | | -import { loadStatuses } from '../../utils/constants'; |
| 2 | +import React from 'react'; |
| 3 | +import { useNavigate } from 'react-router-dom'; |
| 4 | +import { CioAutocomplete } from '@constructor-io/constructorio-ui-autocomplete'; |
| 5 | +import cioClient from '../../app/cioClient'; |
7 | 6 |
|
8 | 7 | function AutocompleteSearch() { |
9 | | - const [params] = useSearchParams(); |
10 | | - const location = useLocation(); |
11 | | - const query = params.get('q'); |
12 | | - const [searchTerm, setSearchTerm] = useState(query || ''); |
13 | 8 | const navigate = useNavigate(); |
14 | | - const [products, setProducts] = useState([]); |
15 | | - const [searchSuggestions, setSearchSuggestions] = useState([]); |
16 | | - const [, setLoadStatus] = useState(loadStatuses.SUCCESS); |
17 | | - |
18 | | - const itemToString = (item) => (item ? item.name : ''); |
19 | | - |
20 | | - const { |
21 | | - isOpen, |
22 | | - getMenuProps, |
23 | | - getItemProps, |
24 | | - getInputProps, |
25 | | - getComboboxProps, |
26 | | - toggleMenu, |
27 | | - } = useCombobox({ |
28 | | - items: [...searchSuggestions, ...products], |
29 | | - itemToString, |
30 | | - onInputValueChange: async ({ inputValue }) => { |
31 | | - setSearchTerm(inputValue); |
32 | | - }, |
33 | | - onSelectedItemChange({ selectedItem }) { |
34 | | - // Item is product - do nothing |
35 | | - if (selectedItem.data.id) { |
36 | | - return; |
37 | | - } |
38 | | - |
39 | | - setSearchTerm(selectedItem.value); |
40 | | - navigate(`/search?q=${selectedItem.value}`); |
41 | | - }, |
42 | | - }); |
43 | 9 |
|
44 | 10 | const submitSearch = (e) => { |
45 | | - e.preventDefault(); |
46 | | - navigate(`/search?q=${searchTerm}`); |
47 | | - toggleMenu(); |
48 | | - }; |
49 | | - |
50 | | - let timeout; |
51 | | - useEffect(() => { |
52 | | - if (!searchTerm) { |
53 | | - setProducts([]); |
54 | | - setSearchSuggestions([]); |
55 | | - } else { |
56 | | - (async () => { |
57 | | - timeout = setTimeout(async () => { |
58 | | - try { |
59 | | - setLoadStatus(loadStatuses.LOADING); |
60 | | - const res = await fetchAutoCompleteResults(searchTerm); |
61 | | - if (res.sections.Products?.length) { |
62 | | - setProducts(res.sections.Products); |
63 | | - } |
64 | | - if (res.sections['Search Suggestions']?.length) { |
65 | | - setSearchSuggestions(res.sections['Search Suggestions']); |
66 | | - } |
67 | | - } catch (error) { |
68 | | - setLoadStatus(loadStatuses.FAILED); |
69 | | - } |
70 | | - setLoadStatus(loadStatuses.SUCCESS); |
71 | | - }, 300); |
72 | | - })(); |
73 | | - } |
74 | | - |
75 | | - return () => { |
76 | | - window.clearTimeout(timeout); |
77 | | - }; |
78 | | - }, [searchTerm]); |
| 11 | + const { query, item } = e; |
79 | 12 |
|
80 | | - useEffect(() => { |
81 | | - if (location.pathname.includes('browse')) { |
82 | | - setSearchTerm(''); |
| 13 | + if (query) { |
| 14 | + navigate(`/search?q=${query}`); |
| 15 | + } else if (item?.value) { |
| 16 | + navigate(`/search?q=${item?.value}`); |
83 | 17 | } |
84 | | - }, [location]); |
| 18 | + }; |
85 | 19 |
|
86 | 20 | return ( |
87 | | - <form |
88 | | - id="search-form" |
| 21 | + <CioAutocomplete |
| 22 | + cioJsClient={ cioClient } |
89 | 23 | onSubmit={ submitSearch } |
90 | | - className="flex place-items-center" |
91 | | - > |
92 | | - |
93 | | - <div className="relative w-full"> |
94 | | - <div { ...getComboboxProps() }> |
95 | | - <input |
96 | | - { ...getInputProps() } |
97 | | - value={ searchTerm } |
98 | | - className="bg-gray-200 w-full sm:w-96 border-2 border-gray-200 rounded-3xl px-4 text-gray-700 |
99 | | - leading-tight focus:outline-none focus:bg-white focus:border-blue-800 mb-0 mt-2 md:mt-0 p-3" |
100 | | - id="search-input" |
101 | | - placeholder="Search..." |
102 | | - data-cnstrc-search-input |
103 | | - /> |
104 | | - </div> |
105 | | - <div data-cnstrc-autosuggest> |
106 | | - <ul |
107 | | - { ...getMenuProps() } |
108 | | - className="shadow-lg absolute right-0 py-8 px-8 list-none z-50 bg-white w-full md:w-[600px] lg:w-[1000px] flex flex-col md:flex-row gap-4 sm:gap-2 border" |
109 | | - style={ !isOpen || !searchTerm ? { display: 'none' } : { } } |
110 | | - > |
111 | | - {isOpen && ( |
112 | | - <div className="basis-1/3"> |
113 | | - <div className="text-lg font-bold mb-2">Search Suggestions</div> |
114 | | - {searchSuggestions.map((item, index) => ( |
115 | | - <li |
116 | | - data-cnstrc-item-section="Search Suggestions" |
117 | | - data-cnstrc-item-name={ item.value } |
118 | | - data-cnstrc-item-id={ item.data?.id } |
119 | | - className="mb-1 cursor-pointer hover:underline" |
120 | | - key={ `${item.value} ${item.data?.id} ` } |
121 | | - { ...getItemProps({ item, index }) } |
122 | | - > |
123 | | - {item.value} |
124 | | - </li> |
125 | | - ))} |
126 | | - </div> |
127 | | - )} |
128 | | - |
129 | | - {isOpen && ( |
130 | | - <div> |
131 | | - <div className="text-lg font-bold mb-2">Products</div> |
132 | | - <div className="basis-2/3 grid gap-4 grid-cols-3"> |
133 | | - {products.map((item, index) => ( |
134 | | - <li |
135 | | - data-cnstrc-item-section="Products" |
136 | | - data-cnstrc-item-name={ item.value } |
137 | | - data-cnstrc-item-id={ item.data?.id } |
138 | | - className="basis-1/3 flex flex-col content-center space-x-2" |
139 | | - key={ `${item.value} ${item.data?.id} ` } |
140 | | - { ...getItemProps({ item, index: (index + searchSuggestions.length) }) } |
141 | | - > |
142 | | - <div className="hover:underline flex flex-col items-center sm:items-start"> |
143 | | - <img width="200" src={ item.data?.image_url } alt="" /> |
144 | | - <div className="text-sm"> |
145 | | - {item.value} |
146 | | - </div> |
147 | | - </div> |
148 | | - </li> |
149 | | - ))} |
150 | | - </div> |
151 | | - </div> |
152 | | - )} |
153 | | - </ul> |
154 | | - </div> |
155 | | - </div> |
156 | | - </form> |
| 24 | + placeholder="Search..." |
| 25 | + /> |
157 | 26 | ); |
158 | 27 | } |
159 | 28 |
|
|
0 commit comments