summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-04-28 10:51:17 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-04-28 10:51:17 +0700
commit22afd4cf502a4dbd7bf68308cd92443545336645 (patch)
tree3287ec808d0610029d36c2e02c450b4dd5a7cafa /src
parent8b42783cd838b1da78d3d192860861ada5d13514 (diff)
search spell when not found
Diffstat (limited to 'src')
-rw-r--r--src/core/api/searchSpellApi.js14
-rw-r--r--src/lib/product/components/ProductSearch.jsx60
-rw-r--r--src/pages/api/shop/spell.js19
3 files changed, 83 insertions, 10 deletions
diff --git a/src/core/api/searchSpellApi.js b/src/core/api/searchSpellApi.js
new file mode 100644
index 00000000..4794c3e1
--- /dev/null
+++ b/src/core/api/searchSpellApi.js
@@ -0,0 +1,14 @@
+import axios from 'axios'
+
+const searchSpellApi = async ({ query }) => {
+ const dataSearchSpell = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/spell?q=${query.trim()}`
+ )
+ return dataSearchSpell
+}
+
+searchSpellApi.defaultProps = {
+ query: ''
+}
+
+export default searchSpellApi
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx
index 81e7948b..76dba005 100644
--- a/src/lib/product/components/ProductSearch.jsx
+++ b/src/lib/product/components/ProductSearch.jsx
@@ -1,4 +1,4 @@
-import { useEffect, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
import useProductSearch from '../hooks/useProductSearch'
import ProductCard from './ProductCard'
import Pagination from '@/core/components/elements/Pagination/Pagination'
@@ -12,6 +12,8 @@ import DesktopView from '@/core/components/views/DesktopView'
import NextImage from 'next/image'
import ProductFilterDesktop from './ProductFilterDesktop'
import { useRouter } from 'next/router'
+import searchSpellApi from '@/core/api/searchSpellApi'
+import Link from '@/core/components/elements/Link/Link'
const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
const router = useRouter()
@@ -19,6 +21,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
if (defaultBrand) query.brand = defaultBrand.toLowerCase()
const { productSearch } = useProductSearch({ query })
const [products, setProducts] = useState(null)
+ const [spellings, setSpellings] = useState(null)
const popup = useActive()
const pageCount = Math.ceil(
@@ -28,6 +31,30 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
const productRows = productSearch.data?.responseHeader.params.rows
const productFound = productSearch.data?.response.numFound
+ useEffect(() => {
+ if (productFound == 0 && query.q) {
+ searchSpellApi({ query: query.q }).then((response) => {
+ const oddIndexSuggestions = response.data.spellcheck.suggestions.filter(
+ (_, index) => index % 2 === 1
+ )
+ const oddIndexCollations = response.data.spellcheck.collations.filter(
+ (_, index) => index % 2 === 1
+ )
+ const dataSpellings = oddIndexSuggestions.reduce((acc, curr) => {
+ oddIndexCollations.forEach((collation) => {
+ acc.push(collation.collationQuery)
+ })
+ curr.suggestion.forEach((s) => {
+ if (!acc.includes(s.word)) acc.push(s.word)
+ })
+ return acc
+ }, [])
+
+ setSpellings(dataSpellings)
+ })
+ }
+ }, [productFound, query])
+
const brands = productSearch.data?.facetCounts?.facetFields?.manufactureName?.filter(
(value, index) => {
if (index % 2 === 0) {
@@ -66,6 +93,20 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
}
}, [query, products, productSearch])
+ const SpellingComponent = useMemo(() => {
+ return (
+ <>
+ Mungkin yang anda cari{' '}
+ {spellings?.map((spelling, i) => (
+ <Link href={`/shop/search?q=${spelling}`} key={i} className='inline'>
+ {spelling}
+ {i + 1 < spellings.length ? ', ' : ''}
+ </Link>
+ ))}
+ </>
+ )
+ }, [spellings])
+
return (
<>
<MobileView>
@@ -96,14 +137,14 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
</>
)}
</>
- ) : (
- 'Mungkin yang anda cari'
- )}
+ ) : SpellingComponent}
</div>
- <button className='btn-light mb-6 py-2 px-5' onClick={popup.activate}>
- Filter
- </button>
+ {productFound > 0 && (
+ <button className='btn-light mb-6 py-2 px-5' onClick={popup.activate}>
+ Filter
+ </button>
+ )}
<div className='grid grid-cols-2 gap-3'>
{products &&
@@ -127,6 +168,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
/>
</div>
</MobileView>
+
<DesktopView>
<div className='container mx-auto mt-10 flex mb-3'>
<div className='w-3/12'>
@@ -163,9 +205,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
</>
)}
</>
- ) : (
- 'Mungkin yang anda cari'
- )}
+ ) : SpellingComponent}
</div>
<div className='justify-end flex '>
<div className='ml-3'>
diff --git a/src/pages/api/shop/spell.js b/src/pages/api/shop/spell.js
new file mode 100644
index 00000000..634adb50
--- /dev/null
+++ b/src/pages/api/shop/spell.js
@@ -0,0 +1,19 @@
+import axios from 'axios'
+
+export default async function handler(req, res) {
+ const { q = '' } = req.query
+
+ let result = await axios(
+ process.env.SOLR_HOST +
+ `/solr/product/spell?indent=true&q.op=AND&q=${q}`
+ )
+
+ try {
+ res.status(200).json(result.data)
+ } catch (error) {
+ res.status(400).json({
+ numFound: 0,
+ suggestions: []
+ })
+ }
+}