Passed
Push — master ( 5126cf...651355 )
by Guangyu
23:00 queued 11s
created

web/src/components/e-commerce/Products.js   A

Complexity

Total Complexity 2
Complexity/F 0

Size

Lines of Code 115
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 2
eloc 106
mnd 2
bc 2
fnc 0
dl 0
loc 115
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
rs 10
1
import React, { Fragment, useState, useContext, useEffect } from 'react';
2
import { Button, Card, CardBody, Col, CustomInput, Form, InputGroup, Row } from 'reactstrap';
3
import Loader from '../common/Loader';
4
import useFakeFetch from '../../hooks/useFakeFetch';
5
import { isIterableArray } from '../../helpers/utils';
6
import Product from './product/Product';
7
import Flex from '../common/Flex';
8
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9
import classNames from 'classnames';
10
import InputGroupAddon from 'reactstrap/es/InputGroupAddon';
11
import ProductFooter from './product/ProductFooter';
12
import usePagination from '../../hooks/usePagination';
13
import { ProductContext } from '../../context/Context';
14
15
const Products = ({ match, history }) => {
16
  // Context
17
  const { products, setProductsLayout, handleSort, sortBy, isAsc } = useContext(ProductContext);
18
19
  // State
20
  const [productIds, setProductIds] = useState([]);
21
22
  // Hook
23
  const { loading } = useFakeFetch(products);
24
  const { data: paginationData, meta: paginationMeta, handler: paginationHandler } = usePagination(productIds, 4);
25
  const { total, itemsPerPage, from, to } = paginationMeta;
26
  const { perPage } = paginationHandler;
27
28
  const { productLayout } = match.params;
29
  const isList = productLayout === 'list';
30
  const isGrid = productLayout === 'grid';
31
32
  useEffect(() => {
33
    setProductIds(products.map(product => product.id));
34
  }, [products, setProductIds]);
35
36
  useEffect(() => {
37
    setProductsLayout(productLayout);
38
  }, [setProductsLayout, productLayout]);
39
40
  return (
41
    <Fragment>
42
      <Card className="mb-3">
43
        <CardBody>
44
          <Row className="justify-content-between align-items-center">
45
            <Col sm="auto" className="mb-2 mb-sm-0" tag={Flex} align="center">
46
              <CustomInput
47
                id="itemsPerPage"
48
                type="select"
49
                bsSize="sm"
50
                value={itemsPerPage}
51
                onChange={({ target }) => perPage(Number(target.value))}
52
              >
53
                <option value={2}>2</option>
54
                <option value={4}>4</option>
55
                <option value={6}>6</option>
56
                <option value={total}>All</option>
57
              </CustomInput>
58
              <h6 className="mb-0 text-nowrap ml-2">
59
                Showing {from}-{to} of {total} Products
60
              </h6>
61
            </Col>
62
            <Col sm="auto">
63
              <Form className="d-inline-block mr-3">
64
                <InputGroup size="sm" tag={Flex} align="center">
65
                  <small className="mr-1">Sort by:</small>
66
                  <CustomInput
67
                    type="select"
68
                    defaultValue={sortBy}
69
                    id="ProductSortBy"
70
                    onChange={({ target }) => handleSort(target.value)}
71
                  >
72
                    <option value="price">Price</option>
73
                    <option value="rating">Rating</option>
74
                    <option value="review">Review</option>
75
                    <option value="off">Off</option>
76
                  </CustomInput>
77
                  <InputGroupAddon addonType="append">
78
                    <Button onClick={() => handleSort(sortBy)} className="cursor-pointer">
79
                      <FontAwesomeIcon icon={classNames({ 'sort-amount-up': isAsc, 'sort-amount-down': !isAsc })} />
80
                    </Button>
81
                  </InputGroupAddon>
82
                </InputGroup>
83
              </Form>
84
85
              <FontAwesomeIcon
86
                className="cursor-pointer"
87
                icon={classNames({ 'list-ul': isGrid, th: isList })}
88
                onClick={() => history.push(`/e-commerce/products/${isList ? 'grid' : 'list'}`)}
89
              />
90
            </Col>
91
          </Row>
92
        </CardBody>
93
      </Card>
94
95
      <Card>
96
        <CardBody className={classNames({ 'p-0  overflow-hidden': isList, 'pb-0': isGrid })}>
97
          {loading ? (
98
            <Loader />
99
          ) : (
100
            <Row noGutters={isList}>
101
              {isIterableArray(products) &&
102
                products
103
                  .filter(product => paginationData.includes(product.id))
104
                  .map((product, index) => <Product {...product} key={product.id} index={index} />)}
105
            </Row>
106
          )}
107
        </CardBody>
108
        <ProductFooter meta={paginationMeta} handler={paginationHandler} />
109
      </Card>
110
    </Fragment>
111
  );
112
};
113
114
export default Products;
115