Skip to content

Commit

Permalink
Implemented Search Product by categories and name
Browse files Browse the repository at this point in the history
  • Loading branch information
EunsooJung committed Feb 18, 2020
1 parent cdfc0e5 commit 63b90a0
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 4 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@testing-library/user-event": "^7.1.2",
"antd": "^3.26.9",
"dotenv": "^8.2.0",
"query-string": "^6.11.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
Expand Down
4 changes: 3 additions & 1 deletion src/components/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import Layout from './Layout';
import { getProducts } from './salesApi';
import CardForProduct from './CardForProduct';
import Search from './Search';

const Home = () => {
// react useState hooks
Expand Down Expand Up @@ -41,9 +42,10 @@ const Home = () => {
return (
<Layout
title='Welcome to Online Marketplace!'
description='Online Marketplace v1.x'
description='Node React MongoDB - Online Marketplace App v1.x'
className='container-fluid'
>
<Search />
<h4 className='mb-4'> Best Sellers</h4>
<div className='row'>
{productsBySell.map((product, i) => (
Expand Down
124 changes: 124 additions & 0 deletions src/components/Search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React, { useState, useEffect } from 'react';
import { getCategories, list } from './salesApi';
import CardForProduct from './CardForProduct';

/**
* @function Search
* @param
* @argument
* @description
* @usedBy ./Home.js
*/
const Search = () => {
const [data, setData] = useState({
categories: [],
category: '',
search: '',
results: [],
searched: false
});

const { categories, category, search, results, searched } = data;

const loadCategories = () => {
getCategories().then(data => {
if (data.error) {
console.log(data.error);
} else {
setData({ ...data, categories: data });
}
});
};

useEffect(() => {
loadCategories();
}, []);

const searchData = () => {
// console.log(search, category);
if (search) {
list({ search: search || undefined, category: category }).then(
response => {
if (response.error) {
console.log(response.error);
} else {
setData({ ...data, results: response, searched: true });
}
}
);
}
};

const searchSubmit = e => {
e.preventDefault();
searchData();
};

const handleChange = name => event => {
setData({ ...data, [name]: event.target.value, searched: false });
};

const searchMessage = (searched, results) => {
if (searched && results.length > 0) {
return `Found ${results.length} products`;
}
if (searched && results.length < 1) {
return `No products found`;
}
};

const searchedProducts = (results = []) => {
return (
<div>
<h2 className='mt-4 mb-4'>{searchMessage(searched, results)}</h2>

<div className='row'>
{results.map((product, i) => (
// <div className='col-4 mb-3'>
<CardForProduct key={i} product={product} />
// </div>
))}
</div>
</div>
);
};

const searchForm = () => (
<form onSubmit={searchSubmit}>
<span className='input-group-text'>
<div className='input-group input-group-lg'>
<div className='input-group-prepend'>
<select className='btn mr-2' onChange={handleChange('category')}>
<option value='All'>All</option>
{categories.map((c, i) => (
<option key={i} value={c._id}>
{c.name}
</option>
))}
</select>
</div>

<input
type='search'
className='form-control'
onChange={handleChange('search')}
placeholder='Search by name'
/>
</div>
<div className='btn input-group-append' style={{ border: 'none' }}>
<button className='input-group-text'>Search</button>
</div>
</span>
</form>
);

return (
<div className='row'>
<div className='container mb-3'>{searchForm()}</div>
<div className='container-fluid mb-3'>{searchedProducts(results)}</div>
{/* {JSON.stringify(results)} */}
</div>
);
};

export default Search;
33 changes: 31 additions & 2 deletions src/components/salesApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
*/

import { API } from '../config';
import queryString from 'query-string';

/**
* Get all products
* @RequestedBy @method loadProductBySell, @method loadProductByArrival in Home.js
* @RequestTo router.get('/products, list) in routes/productsRoutes.js back-end
* @usedBy ./Home.js
*/
export const getProducts = sortBy => {
return fetch(`${API}/products?sortBy=${sortBy}&order=desc&limit=6`, {
Expand All @@ -21,7 +23,7 @@ export const getProducts = sortBy => {

/**
* @description get all categories call to backend
* @usedBy components/shop.js
* @usedBy components/shop.js, Search.js
*/
export const getCategories = () => {
return fetch(`${API}/categories`, {
Expand All @@ -45,7 +47,6 @@ export const getFilteredProducts = (skip, limit, filters = {}) => {
skip,
filters
};

return fetch(`${API}/products/by/search`, {
method: 'POST',
headers: {
Expand All @@ -61,3 +62,31 @@ export const getFilteredProducts = (skip, limit, filters = {}) => {
console.log(err);
});
};

/**
* @description
* @usedBy ./Search.js
* @requestType POST
* @requestTo router.post('/products/by/search', searchProductsList); back-end
*/
export const list = params => {
const query = queryString.stringify(params);
console.log('query', query);
return fetch(`${API}/products/search?${query}`, {
method: 'GET'
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};

export const read = productId => {
return fetch(`${API}/product/${productId}`, {
method: 'GET'
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};
2 changes: 1 addition & 1 deletion src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,5 @@
}

.jumbotron-font-color {
color: #09f127;
color: #fff;
}
19 changes: 19 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8498,6 +8498,15 @@ query-string@^4.1.0:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"

query-string@^6.11.0:
version "6.11.0"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.11.0.tgz#dc27a05733d1be66f16d0f83dfa957270f45f66d"
integrity sha512-jS+me8X3OEGFTsF6kF+vUUMFG/d3WUCvD7bHhfZP5784nOq1pjj8yau/u86nfOncmcN6ZkSWKWkKAvv/MGxzLA==
dependencies:
decode-uri-component "^0.2.0"
split-on-first "^1.0.0"
strict-uri-encode "^2.0.0"

querystring-es3@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
Expand Down Expand Up @@ -10044,6 +10053,11 @@ spdy@^4.0.1:
select-hose "^2.0.0"
spdy-transport "^3.0.0"

split-on-first@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==

split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
Expand Down Expand Up @@ -10151,6 +10165,11 @@ strict-uri-encode@^1.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=

strict-uri-encode@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=

string-convert@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
Expand Down

0 comments on commit 63b90a0

Please sign in to comment.