Skip to content

Commit

Permalink
searchbar revised
Browse files Browse the repository at this point in the history
  • Loading branch information
wilhelmrauston committed Jan 24, 2024
1 parent 7366a2b commit 1faa085
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 109 deletions.
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/components/Global/NavbarGlobal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import clsx from 'clsx'
import { Container } from '../utils/Container'
import { HomeIcon } from '@heroicons/react/24/outline'
import Example from '../UI/Forms/UserDropdown'
import SearchBar from './SearchBar'

export function Header(props) {
const router = useRouter()
Expand All @@ -16,6 +17,9 @@ export function Header(props) {
<a href='#' className='h-full'>
<HomeIcon className='h-full cursor-pointer rounded-full p-2 text-gray-800 transition duration-200 ease-in-out hover:text-teal-600' />
</a>

<SearchBar />

<div className='nav-links-container flex flex-row items-center space-x-4 text-lg'>
<a
href='#'
Expand Down
88 changes: 88 additions & 0 deletions src/components/Global/SearchBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { useState, useEffect } from 'react'
import { MagnifyingGlassIcon } from '@heroicons/react/24/solid'
import SearchField from '../UI/Forms/SearchField'
import SearchResultCard from '../UI/global/SearchResultCard'

export default function SearchBar() {
const [searchTerm, setSearchTerm] = useState('')
const [searchResult, setSearchResult] = useState([])
const [loading, setLoading] = useState(false)

const handleSearch = async () => {
setLoading(true)

try {
const response = await fetch(`/api/v1/search?query=${searchTerm}`)
const data = await response.json()
setSearchResult(data)
} catch (error) {
console.error('Error fetching search results:', error)
setSearchResult([])
} finally {
setLoading(false)
}
}

useEffect(() => {
if (searchTerm.trim() !== '') {
handleSearch()
} else {
setSearchResult([])
}
}, [searchTerm])

const handleInputChange = event => {
setSearchTerm(event.target.value)
}

const filteredResults = searchResult.filter(
item =>
item.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
(item.manufactured_by &&
item.manufactured_by.owner_name
.toLowerCase()
.includes(searchTerm.toLowerCase())) ||
item.dpp_class.toLowerCase().includes(searchTerm.toLowerCase())
)

return (
<div className='relative w-full md:w-[250px]'>
<div className='relative w-full'>
<div className='flex w-full items-center'>
<SearchField
className='w-full'
placeholder={'Search for a product...'}
id='searchBar'
name='searchBar'
type='text'
defaultValue={''}
onChange={handleInputChange}
/>
</div>
</div>

{filteredResults.length > 0 && (
<ul
className={`absolute left-0 top-16 w-full cursor-pointer rounded-md border border-transparent bg-white text-blue-900 shadow-lg`}
>
{filteredResults.map((item, index) => {
if (!item) {
return null
}

const uniqueKey = item.id || item.name + item.dpp_class + index

return (
<li
key={uniqueKey}
className='flex flex-row items-center space-x-4 p-2 hover:bg-gray-100'
>
<SearchResultCard item={item} />
</li>
)
})}
</ul>
)}
</div>
)
}
7 changes: 1 addition & 6 deletions src/components/Layout/LayoutGlobal.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Head from 'next/head'
import { Header } from '../Global/NavbarGlobal'
import SearchBar from '../utils/SearchBar'

export default function LayoutGlobal({
className,
Expand All @@ -21,11 +20,7 @@ export default function LayoutGlobal({
</Head>
<Header />
<main>
<>
<SearchBar></SearchBar>

{props.children}
</>
<>{props.children}</>
</main>
</>
)
Expand Down
35 changes: 35 additions & 0 deletions src/components/UI/Forms/SearchField.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { MagnifyingGlassIcon } from '@heroicons/react/20/solid'
import { forwardRef } from 'react'

const SearchField = forwardRef((props, ref) => {
return (
<div className={props.className}>
{props.label && (
<label
htmlFor={props.id}
className='mb-2 block text-xs font-semibold text-gray-600'
>
{props.label}
</label>
)}
<MagnifyingGlassIcon className='absolute left-3 top-[11px] h-5 text-gray-500 lg:top-3.5' />

<input
ref={ref}
{...props}
className={`block appearance-none rounded-lg border pl-10 lg:w-full ${
props.error && props.error !== 0
? 'border-red-500'
: 'border-gray-200'
} bg-gray-50 px-[calc(theme(spacing.4)-1px)] py-2 text-gray-900 ring-0 ring-transparent transition duration-200 placeholder:text-gray-400 hover:bg-white hover:ring-4 hover:ring-blue-50 focus:border-blue-500 focus:bg-white focus:outline-none focus:ring-4 focus:ring-blue-500/10 active:border-blue-500 active:bg-white active:ring-0 lg:py-[calc(theme(spacing.3)-1px)]`}
/>
{props.error && props.error !== 0 && (
<p className=' px-4 pt-1.5 text-sm text-red-700'>{props.error}</p>
)}
</div>
)
})

SearchField.displayName = 'SearchField'

export default SearchField
21 changes: 21 additions & 0 deletions src/components/UI/global/SearchResultCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export default function SearchResultCard({ item }) {
console.log(item)
const { name, dpp_class, manufactured_by, created_at } = item

return (
<div className='flex w-full cursor-pointer items-center space-x-3 rounded-md p-3 hover:bg-gray-50'>
<div className='relative'></div>
<div className='flex flex-col'>
<p className='font-semibold'>{name}</p>
<p className='text-xs font-medium text-gray-500'>
{/* {created_at && created_at.creation_time && (
<span> {created_at.creation_time}</span>
)} */}
{manufactured_by && manufactured_by.owner_name && (
<span> {manufactured_by.owner_name}</span>
)}
</p>
</div>
</div>
)
}
86 changes: 0 additions & 86 deletions src/components/utils/SearchBar.jsx

This file was deleted.

33 changes: 16 additions & 17 deletions src/pages/api/v1/search.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import { defaultHandler } from '@/utils/server/api-helpers';
import Product from '@/models/Product';
import { defaultHandler } from '@/utils/server/api-helpers'
import Product from '@/models/Product'

const searchProducts = async (req, res) => {
const { query } = req.query;
const { query } = req.query

try {
const products = await Product.find({
$or: [
{
name: { $regex: query, $options: 'i' }
{
name: { $regex: query, $options: 'i' },
},
{
'manufactured_by.privacy': 'public'
{
'manufactured_by.owner_name': { $regex: query, $options: 'i' },
},
{
'manufactured_by.owner_name': { $regex: query, $options: 'i' }
}
]
}).select('name dpp_class manufactured_by -_id');
],
}).select('name dpp_class manufactured_by _id')

res.status(200).json(products);
res.status(200).json(products)
} catch (error) {
res.status(500).json({ error: 'An error occurred while fetching search results' });
res
.status(500)
.json({ error: 'An error occurred while fetching search results' })
}
};
}

const handler = async (req, res) =>
defaultHandler(
Expand All @@ -36,6 +35,6 @@ const handler = async (req, res) =>
requiresAuth: false,
requiresAdmin: false,
}
);
)

export default handler;
export default handler

0 comments on commit 1faa085

Please sign in to comment.