Skip to content

Commit

Permalink
Merge pull request #32 from skittlesaur/products-frontend
Browse files Browse the repository at this point in the history
Products-frontend
  • Loading branch information
skittlesaur authored Jun 3, 2022
2 parents 5279e63 + d299fd2 commit 95862b5
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 10 deletions.
2 changes: 2 additions & 0 deletions client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import AdminViewOrder from "./pages/admin/orders/id/AdminViewOrder";
import AdminNewProduct from "./pages/admin/products/new/AdminNewProduct";
import AdminShipping from "./pages/admin/shipment/default/AdminShipping";
import AdminUpdateShipping from "./pages/admin/shipment/update/AdminUpdateShipping";
import Products from './pages/products/Products';

import Checkout from "./pages/checkout/checkout";
import Success from "./pages/checkout/success";
Expand Down Expand Up @@ -88,6 +89,7 @@ const App = () => {
<Navigation cartCount={cartCount}/>
<Routes>
<Route path={'/'} element={<Home addProductToCart={addProductToCart}/>}/>
<Route path={'/products'} element={<Products addProductToCart={addProductToCart}/>}/>
<Route path={'/cart'}
element={<CartPage cart={cart} cartCount={cartCount} updateQuantity={updateQuantity}/>}/>
<Route path={'/checkout'} element={<Checkout/>}/>
Expand Down
18 changes: 18 additions & 0 deletions client/src/actions/products.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
import * as api from '../api';
import {FETCH_RECOMMENDATIONS, UPDATE_DATABASE, VALIDATE_CART, VALIDATE_CART_ERR} from "../constants/actions/products";

export const getProductsPerPage = (page, category, onSuccess) => async () => {
try {
const products = await api.getProductsPerPage(page, category).then(res => res.data);
onSuccess(products);
} catch (error) {
console.log(error);
}
}

export const productsSearch = (search, page, onSuccess) => async () => {
try {
const products = await api.productsSearch(search, page).then(res => res.data);
onSuccess(products);
} catch (error) {
console.log(error);
}
}

export const getRecommendations = (onSuccess) => async (dispatch) => {
try {
const data = await api.getRecommendations().then(res => res.data);
Expand Down
2 changes: 2 additions & 0 deletions client/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ API.interceptors.request.use((req) => {
return req;
});

export const getProductsPerPage = (page, category) => API.get(`${PRODUCTS_BASEURL}?page=${page}${category && `&category=${category}`}`);
export const productsSearch = (search, page) => API.get(`${PRODUCTS_BASEURL}/search?search=${search}&page=${page}`);
export const getRecommendations = () => API.get(`${PRODUCTS_BASEURL}/recommendations`);
export const postProduct = (product) => API.post(`${PRODUCTS_BASEURL}`, product);
export const adminUpdateDatabase = (csv, mode) => API.patch(`${PRODUCTS_BASEURL}`, {csv, mode});
Expand Down
16 changes: 10 additions & 6 deletions client/src/components/categories/Categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,35 @@ import {Link} from "react-router-dom";
const Categories = () => {
const categories = [
{
display: "Fruits & Vegetables",
display: "All",
img: FruitsAndVegetables
},
{
display: "Meat, Poultry & Seafood",
display: "Fruits and Vegetables",
img: FruitsAndVegetables
},
{
display: "Meat Poultry and Seafood",
img: MeatPoultrySeafood
},
{
display: "Breakfast",
img: Breakfast
},
{
display: "Chocolate & Candy",
display: "Chocolate and Candy",
img: ChocolateCandy
},
{
display: "Dairy & Eggs",
display: "Dairy and Eggs",
img: DairyEggs
},
{
display: "Beverages",
img: ColdDrinks
},
{
display: "Chips & Crackers",
display: "Chips and Crackers",
img: Snacks
},
{
Expand All @@ -49,7 +53,7 @@ const Categories = () => {
<div className={styles['categories']}>
<div className={`${styles['categories-scroll']}`}>
{categories.map((item, i) =>
<Link key={i} to={`/products/${item.display}`} className={styles['category']}>
<Link key={i} to={`/products?category=${item.display}`} className={styles['category']}>
<div>{item.display}</div>
<img src={item.img} alt={item.display}/>
</Link>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/categories/categories.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
.categories-scroll {
display: grid;
grid-auto-flow: column;
gap: 1em;
gap: .5em;
overflow-x: auto;
overflow-y: hidden;
overscroll-behavior: contain;
Expand All @@ -19,7 +19,7 @@
cursor: pointer;
position: relative;

--CATEGORY_SIZE: 8em;
--CATEGORY_SIZE: 7em;
width: var(--CATEGORY_SIZE);
height: var(--CATEGORY_SIZE);

Expand Down
90 changes: 90 additions & 0 deletions client/src/pages/products/Products.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import styles from './products.module.css';
import {useState, useEffect} from "react";
import {useLocation, useNavigate} from "react-router-dom";
import {useDispatch} from "react-redux";
import {getProductsPerPage, productsSearch} from "../../actions/products";
import ProductCard from "../../components/product-card/ProductCard";
import Pages from "../../components/pages/Pages";
import Categories from "../../components/categories/Categories";
import Loading from "../../components/loading/Loading";

const Products = ({addProductToCart}) => {
const [page, setPage] = useState(1);
const [products, setProducts] = useState([]);
const [totalPages, setTotalPages] = useState(1);
const [loading, setLoading] = useState(false);

const location = useLocation();
const dispatch = useDispatch();
const navigate = useNavigate();

useEffect(() => {
setLoading(true)
const query = new URLSearchParams(location.search);
const page = query.get('page') || 1;
setPage(Number(page));

if (query.get('search')) {
const search = query.get('search');

dispatch(productsSearch(search, page, onSuccess));
} else if (query.get('category')) {
const category = query.get('category');
if (category === 'All') {
setPage(Number(page));

dispatch(getProductsPerPage(page, null, onSuccess));
} else {
dispatch(getProductsPerPage(page, category, onSuccess));
}
} else {
setPage(Number(page));

dispatch(getProductsPerPage(page, null, onSuccess));
}
}, [dispatch, location.search]);

const onSuccess = (res) => {
setTotalPages(res.total_pages);
setProducts(res.products);
setLoading(false);
}

const handleClick = (i) => {
const query = new URLSearchParams(location.search);

if (query.get('search')) {
const search = query.get('search');
navigate(`/products?search=${search}&page=${i}`);
window.scrollTo(0, 0);
} else if (query.get('category')) {
const category = query.get('category');
navigate(`/products?category=${category}&page=${i}`);
window.scrollTo(0, 0);
} else {
navigate(`/products?page=${i}`);
window.scrollTo(0, 0);
}
}

return (
<div className={styles['wrapper']}>
<div className={'heading'}>
<h1>Products</h1>
</div>
<Categories/>
{loading ? <Loading/> :
<>
<div className={styles['products-wrapper']}>
{products.map(((product, i) => <ProductCard addProductToCart={addProductToCart} key={i}
product={product}/>))}
</div>
<Pages max={totalPages} current={page} onPageClick={handleClick}/>
</>
}
</div>
)
;
}

export default Products;
31 changes: 31 additions & 0 deletions client/src/pages/products/products.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.wrapper {
display: flex;
flex-direction: column;
padding: 2em 1em;
gap: 2em;
}

.products-wrapper {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1em;
}

@media screen and (min-width: 768px) {
.products-wrapper {
grid-template-columns: repeat(3, 1fr);
}
}

@media screen and (min-width: 1024px){
.products-wrapper {
grid-template-columns: repeat(4, 1fr);
}
}

@media screen and (min-width: 1440px) {
.wrapper {
max-width: 1200px;
margin: auto;
}
}
6 changes: 4 additions & 2 deletions server/controller/products/Products.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import CSVtoJSON from "../../utils/CSVtoJSON.js";

export const productsSearch = async (req, res) => {
try {

const products = await Products.find({"name": {$regex: req.query.search, $options: "i"}});

const productsPaged = Pagination(req.query.page, products);

res.status(200).json(productsPaged);
const numberOfPages = Math.ceil(products.length / 2);
res.status(200).json({total_pages: numberOfPages, products:productsPaged});

} catch (error) {
res.status(404).json({message: error.message});
Expand Down Expand Up @@ -43,7 +45,7 @@ export const ShowProductsPerPage = async (req, res) => {
const ShowProductsPerCategory = async (category, products) => {
try {

products = await Products.find({"category": {$eq: category}});
products = await Products.find({"category": {$regex: category, $options: "i"}});
return products;

} catch (error) {
Expand Down

0 comments on commit 95862b5

Please sign in to comment.