Skip to content

Commit

Permalink
Merge pull request #12 from Nandita10062001/feature/search-filter
Browse files Browse the repository at this point in the history
Added Search Filter
  • Loading branch information
Nandita10062001 authored Oct 24, 2024
2 parents 01396ea + 8438db3 commit 9f1b229
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 4 deletions.
2 changes: 1 addition & 1 deletion client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="client\public\favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
Expand Down
2 changes: 2 additions & 0 deletions client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import Profile from './pages/user/Profile.js';
import Orders from './pages/user/Orders.js';
import Products from './pages/Admin/Products.js';
import UpdateProduct from './pages/Admin/UpdateProduct.js';
import SearchPage from './pages/SearchPage.js';

function App() {
return (
<>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/search" element={<SearchPage />} />
<Route path="/dashboard" element={<PrivateRoute />}>
<Route path="user" element={<Dashboard />} />
<Route path="user/profile" element={<Profile />} />
Expand Down
42 changes: 42 additions & 0 deletions client/src/components/Form/SearchInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { useSearch } from '../../context/Search';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';

const SearchInput = () => {
const [values, setValues] = useSearch();
const navigate = useNavigate();

const handleSubmit = async (e) => {
e.preventDefault();
try {
const { data } = await axios.get(
`${process.env.REACT_APP_API}/api/v1/product/search/${values.keyword}`
);
setValues({ ...values, result: data });
navigate('/search');
} catch (error) {
console.log(error);
}
};

return (
<div>
<form className="d-flex me-3" role="search" onSubmit={handleSubmit}>
<input
className="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
value={values.keyword}
onChange={(e) => setValues({ ...values, keyword: e.target.value })}
/>
<button className="btn btn-outline-success" type="submit">
Search
</button>
</form>
</div>
);
};

export default SearchInput;
2 changes: 2 additions & 0 deletions client/src/components/Layout/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { NavLink, Link, useNavigate } from 'react-router-dom';
import { useAuth } from '../../context/Auth';
import { toast } from 'react-toastify';
import SearchInput from '../Form/SearchInput';

const Header = () => {
const [auth, setAuth] = useAuth();
Expand Down Expand Up @@ -39,6 +40,7 @@ const Header = () => {
🛒 E-Commerce App
</Link>
<ul className="navbar-nav ms-auto mb-2 mb-lg-0">
<SearchInput/>
<li className="nav-item">
<NavLink className="nav-link" aria-current="page" to="/">
Home
Expand Down
20 changes: 20 additions & 0 deletions client/src/context/Search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useState, useContext, createContext } from 'react';
const SearchContext = createContext();

const SearchProvider = ({ children }) => {
const [search, setSearch] = useState({
keyword: '',
results: [],
});

return (
<SearchContext.Provider value={[search, setSearch]}>
{children}
</SearchContext.Provider>
);
};

//custom hook
const useSearch = () => useContext(SearchContext);

export { useSearch, SearchProvider };
9 changes: 6 additions & 3 deletions client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
import { AuthProvider } from './context/Auth';
import { SearchProvider } from './context/Search';
import 'antd/dist/reset.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<AuthProvider>
<BrowserRouter>
<App />
</BrowserRouter>
<SearchProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</SearchProvider>
</AuthProvider>
);

Expand Down
48 changes: 48 additions & 0 deletions client/src/pages/SearchPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import { useSearch } from '../context/Search';
import Layout from '../components/Layout/Layout';

const SearchPage = () => {
const [values, setValues] = useSearch();
return (
<Layout title={'Search Results'}>
<div className="container">
<div className="text-center">
<h1>Search Results</h1>
<h6>
{values?.result.length < 1
? 'No Products Found'
: `Found ${values?.result.length}`}
</h6>
<div className="d-flex flex-wrap mt-4">
{values?.result.map((p) => (
<div key={p._id} className="col-lg-3 col-md-4 col-sm-6 mb-4">
{' '}
<div className="card m-2">
<img
src={`${process.env.REACT_APP_API}/api/v1/product/product-photo/${p._id}`}
className="card-img-top"
alt={p.name}
/>
<div className="card-body">
<div className="d-flex justify-content-between">
<h5 className="card-title">{p.name}</h5>
<h5>{p.price}$</h5>
</div>
<p className="card-text">
{p.description.substring(0, 25)}...
</p>
<button class="btn btn-info ms-1">More Details</button>
<button class="btn btn-secondary ms-1">Add to Cart</button>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</Layout>
);
};

export default SearchPage;
23 changes: 23 additions & 0 deletions controllers/productController.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,26 @@ export const productListController = async (req, res) => {
});
}
};

//search-product
export const searchProductController = async (req, res) => {
try {
const { keyword } = req.params;
const result = await productModel
.find({
$or: [
{ name: { $regex: keyword, $options: 'i' } },
{ description: { $regex: keyword, $options: 'i' } },
],
})
.select('-photo');
res.json(result);
} catch (error) {
console.log(error);
res.status(400).send({
success: false,
message: 'Error in Search Product API',
error,
});
}
};
4 changes: 4 additions & 0 deletions routes/productRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
productFilterController,
productListController,
productPhotoController,
searchProductController,
updateProductController,
} from '../controllers/productController.js';
import formidable from 'express-formidable';
Expand Down Expand Up @@ -54,4 +55,7 @@ router.get('/product-count', productCountController);
//product-per-page
router.get('/product-list/:page', productListController);

//search-product
router.get('/search/:keyword', searchProductController)

export default router;

0 comments on commit 9f1b229

Please sign in to comment.