From 7c441e0eda0c6f0e6874e04831cb959e6ce136ab Mon Sep 17 00:00:00 2001 From: kiran Date: Tue, 1 May 2018 22:47:23 +0530 Subject: [PATCH 1/7] basic redux setup --- package.json | 3 ++ src/client/actions/index.js | 25 ++++++++++++++ src/client/components/AddToCart.js | 12 +++++++ src/client/components/App.js | 26 ++++++++++++++ src/client/components/Cart.js | 35 +++++++++++++++++++ src/client/components/CartBadge.js | 23 +++++++++++++ src/client/components/DeleteCartItem.js | 7 ++++ src/client/components/Header.js | 40 +++++++++++++++++++++ src/client/components/Home.js | 7 ++++ src/client/components/Price.js | 5 +++ src/client/components/Product.js | 37 ++++++++++++++++++++ src/client/components/ProductSelect.js | 7 ++++ src/client/components/Products.js | 46 +++++++++++++++++++++++++ src/client/reducers/cartItems.js | 8 +++++ src/client/reducers/index.js | 8 +++++ src/client/reducers/products.js | 8 +++++ src/client/store.js | 13 +++++++ src/index.js | 16 +++++++++ src/server/connectors/index.js | 5 ++- src/server/index.js | 6 ++-- yarn.lock | 34 ++++++++++++++++-- 21 files changed, 365 insertions(+), 6 deletions(-) create mode 100644 src/client/actions/index.js create mode 100644 src/client/components/AddToCart.js create mode 100644 src/client/components/App.js create mode 100644 src/client/components/Cart.js create mode 100644 src/client/components/CartBadge.js create mode 100644 src/client/components/DeleteCartItem.js create mode 100644 src/client/components/Header.js create mode 100644 src/client/components/Home.js create mode 100644 src/client/components/Price.js create mode 100644 src/client/components/Product.js create mode 100644 src/client/components/ProductSelect.js create mode 100644 src/client/components/Products.js create mode 100644 src/client/reducers/cartItems.js create mode 100644 src/client/reducers/index.js create mode 100644 src/client/reducers/products.js create mode 100644 src/client/store.js create mode 100644 src/index.js diff --git a/package.json b/package.json index 3c33187..1f211b3 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,12 @@ "mongoose": "^4.13.6", "react": "^16.0.0", "react-dom": "^16.0.0", + "react-redux": "^5.0.7", "react-router-dom": "^4.2.2", "react-scripts": "1.0.17", "reactstrap": "^5.0.0-beta.3", + "redux": "^4.0.0", + "redux-thunk": "^2.2.0", "uuid": "^3.1.0" }, "devDependencies": { diff --git a/src/client/actions/index.js b/src/client/actions/index.js new file mode 100644 index 0000000..f17c4fd --- /dev/null +++ b/src/client/actions/index.js @@ -0,0 +1,25 @@ +export function fetchProducts() { + return function(dispatch) { + return fetch("/api/products").then(res => + res.json().then(products => { + dispatch({ + type: "SET_PRODUCTS", + payload: products + }); + }) + ); + }; +} + +export function fetchCartItems() { + return function(dispatch) { + return fetch("/api/cart-items").then(res => + res.json().then(cartItems => { + dispatch({ + type: "SET_CART_ITEMS", + payload: cartItems + }); + }) + ); + }; +} diff --git a/src/client/components/AddToCart.js b/src/client/components/AddToCart.js new file mode 100644 index 0000000..1684f9d --- /dev/null +++ b/src/client/components/AddToCart.js @@ -0,0 +1,12 @@ +import React from "react"; +import { Button, UncontrolledAlert } from "reactstrap"; + +export default class AddToCart extends React.Component { + render() { + return ( + + ); + } +} diff --git a/src/client/components/App.js b/src/client/components/App.js new file mode 100644 index 0000000..92fedc1 --- /dev/null +++ b/src/client/components/App.js @@ -0,0 +1,26 @@ +import React from "react"; +import { Route, Switch } from "react-router-dom"; +import Home from "./Home"; +import Products from "./Products"; +import Product from "./Product"; +import Cart from "./Cart"; +import Header from "./Header"; +import { Container } from "reactstrap"; + +export default class App extends React.Component { + render() { + return ( +
+
+ + + + + + + + +
+ ); + } +} diff --git a/src/client/components/Cart.js b/src/client/components/Cart.js new file mode 100644 index 0000000..cee176a --- /dev/null +++ b/src/client/components/Cart.js @@ -0,0 +1,35 @@ +import React from "react"; +import { ListGroup, ListGroupItem, Alert } from "reactstrap"; +import DeleteCartItem from "./DeleteCartItem"; +import { connect } from "react-redux"; + +function CartItem({ cartItem }) { + return ( + +
+
{cartItem.product.name}
+
+ +
+
+
+ ); +} + +export class Cart extends React.Component { + render() { + const { cartItems } = this.props; + if (!cartItems.length) { + return Cart is empty; + } + return ( + + {cartItems.map(cartItem => ( + + ))} + + ); + } +} + +export default connect(state => ({ cartItems: state.cartItems }))(Cart); diff --git a/src/client/components/CartBadge.js b/src/client/components/CartBadge.js new file mode 100644 index 0000000..6287794 --- /dev/null +++ b/src/client/components/CartBadge.js @@ -0,0 +1,23 @@ +import React from "react"; +import { Badge } from "reactstrap"; +import { connect } from "react-redux"; +import { fetchCartItems } from "../actions"; + +class CartBadge extends React.Component { + componentDidMount() { + this.props.fetchCartItems(); + } + render() { + const { cartItems } = this.props; + if (!cartItems) { + return null; + } + return cartItems.length ? ( + {cartItems.length} + ) : null; + } +} + +export default connect(state => ({ cartItems: state.cartItems }), { + fetchCartItems +})(CartBadge); diff --git a/src/client/components/DeleteCartItem.js b/src/client/components/DeleteCartItem.js new file mode 100644 index 0000000..eaf110a --- /dev/null +++ b/src/client/components/DeleteCartItem.js @@ -0,0 +1,7 @@ +import React from "react"; + +export default class DeleteCartItem extends React.Component { + render() { + return delete; + } +} diff --git a/src/client/components/Header.js b/src/client/components/Header.js new file mode 100644 index 0000000..f76544e --- /dev/null +++ b/src/client/components/Header.js @@ -0,0 +1,40 @@ +import React from "react"; +import { Navbar, NavbarBrand, Nav, NavItem } from "reactstrap"; +import { Link } from "react-router-dom"; +import classnames from "classnames"; +import CartBadge from "./CartBadge"; + +export default class Header extends React.Component { + render() { + const { location: { pathname } } = this.props; + return ( +
+ + Apollo Store + + +
+ ); + } +} diff --git a/src/client/components/Home.js b/src/client/components/Home.js new file mode 100644 index 0000000..b4af15f --- /dev/null +++ b/src/client/components/Home.js @@ -0,0 +1,7 @@ +import React from "react"; + +export default class Home extends React.Component { + render() { + return
Welcome to apollo store
; + } +} diff --git a/src/client/components/Price.js b/src/client/components/Price.js new file mode 100644 index 0000000..51afe37 --- /dev/null +++ b/src/client/components/Price.js @@ -0,0 +1,5 @@ +import React from "react"; + +export default function Price({ value }) { + return ₹ {value}; +} diff --git a/src/client/components/Product.js b/src/client/components/Product.js new file mode 100644 index 0000000..59cd9dd --- /dev/null +++ b/src/client/components/Product.js @@ -0,0 +1,37 @@ +import React from "react"; +import { Media } from "reactstrap"; +import AddToCart from "./AddToCart"; +import Price from "./Price"; +import { connect } from "react-redux"; + +export class Product extends React.Component { + render() { + const { product } = this.props; + if (!product) { + return null; + } + return ( + + + product + + + {product.name} +
{product.description}
+
+ Price: +
+ +
+
+ ); + } +} + +export default connect((state, props) => { + return { + product: state.products.find( + p => p.id === parseInt(props.match.params.id, 10) + ) + }; +})(Product); diff --git a/src/client/components/ProductSelect.js b/src/client/components/ProductSelect.js new file mode 100644 index 0000000..dbf9b72 --- /dev/null +++ b/src/client/components/ProductSelect.js @@ -0,0 +1,7 @@ +import React from "react"; + +export default class ProductSelect extends React.Component { + render() { + return ; + } +} diff --git a/src/client/components/Products.js b/src/client/components/Products.js new file mode 100644 index 0000000..1d1476b --- /dev/null +++ b/src/client/components/Products.js @@ -0,0 +1,46 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { ListGroup, ListGroupItem } from "reactstrap"; +import ProductSelect from "./ProductSelect"; +import Price from "./Price"; +import { connect } from "react-redux"; +import { fetchProducts } from "../actions"; + +function Product({ product }) { + return ( + +
+
+ + {product.name} +
+
+ +
+
+
+ ); +} + +export class Products extends React.Component { + componentDidMount() { + this.props.fetchProducts(); + } + render() { + const { products } = this.props; + return ( +
+ Products + + {products.map(product => ( + + ))} + +
+ ); + } +} + +export default connect(state => ({ products: state.products }), { + fetchProducts +})(Products); diff --git a/src/client/reducers/cartItems.js b/src/client/reducers/cartItems.js new file mode 100644 index 0000000..1c35f57 --- /dev/null +++ b/src/client/reducers/cartItems.js @@ -0,0 +1,8 @@ +export default function cartItemsReducer(state = [], action) { + switch (action.type) { + case "SET_CART_ITEMS": + return action.payload; + default: + return state; + } +} diff --git a/src/client/reducers/index.js b/src/client/reducers/index.js new file mode 100644 index 0000000..2b6075b --- /dev/null +++ b/src/client/reducers/index.js @@ -0,0 +1,8 @@ +import { combineReducers } from "redux"; +import products from "./products"; +import cartItems from "./cartItems"; + +export default combineReducers({ + products, + cartItems +}); diff --git a/src/client/reducers/products.js b/src/client/reducers/products.js new file mode 100644 index 0000000..d757014 --- /dev/null +++ b/src/client/reducers/products.js @@ -0,0 +1,8 @@ +export default function productsReducer(state = [], action) { + switch (action.type) { + case "SET_PRODUCTS": + return action.payload; + default: + return state; + } +} diff --git a/src/client/store.js b/src/client/store.js new file mode 100644 index 0000000..48aa55d --- /dev/null +++ b/src/client/store.js @@ -0,0 +1,13 @@ +import { createStore, applyMiddleware, compose } from "redux"; +import rootReducer from "./reducers"; +import thunk from "redux-thunk"; + +export default function configureStore() { + const composeEnhancers = + window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; + const store = createStore( + rootReducer, + composeEnhancers(applyMiddleware(thunk)) + ); + return store; +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..ec1f0e8 --- /dev/null +++ b/src/index.js @@ -0,0 +1,16 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import App from "./client/components/App"; +import "bootstrap/dist/css/bootstrap.min.css"; +import { BrowserRouter, Route } from "react-router-dom"; +import { Provider } from "react-redux"; +import configureStore from "./client/store"; + +ReactDOM.render( + + + + + , + document.getElementById("root") +); diff --git a/src/server/connectors/index.js b/src/server/connectors/index.js index c9a4fce..69d3572 100644 --- a/src/server/connectors/index.js +++ b/src/server/connectors/index.js @@ -38,7 +38,10 @@ export function getCartItem(id) { } export function getCartItems() { - return cartItems; + return cartItems.map(c => ({ + ...c, + product: getProduct(c.productId) + })); } export function addToCart(args) { diff --git a/src/server/index.js b/src/server/index.js index 65ac35b..031bf40 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -31,9 +31,9 @@ app.use( }) ); -app.use(function(req, res, next) { - setTimeout(next, 500); -}); +// app.use(function(req, res, next) { +// setTimeout(next, 500); +// }); app.get("/api/user", function(req, res) { res.json(getUser()); diff --git a/yarn.lock b/yarn.lock index 824a933..78c06ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3543,7 +3543,7 @@ hoek@4.x.x: version "4.2.1" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" -hoist-non-react-statics@^2.3.0: +hoist-non-react-statics@^2.3.0, hoist-non-react-statics@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" @@ -3800,7 +3800,7 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" -invariant@^2.2.1, invariant@^2.2.2: +invariant@^2.0.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: @@ -4908,6 +4908,10 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +lodash-es@^4.17.5: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.10.tgz#62cd7104cdf5dd87f235a837f0ede0e8e5117e05" + lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -6480,6 +6484,17 @@ react-portal@^4.1.2: dependencies: prop-types "^15.5.8" +react-redux@^5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" + dependencies: + hoist-non-react-statics "^2.5.0" + invariant "^2.0.0" + lodash "^4.17.5" + lodash-es "^4.17.5" + loose-envify "^1.1.0" + prop-types "^15.6.0" + react-router-dom@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.2.2.tgz#c8a81df3adc58bba8a76782e946cbd4eae649b8d" @@ -6685,6 +6700,17 @@ reduce-function-call@^1.0.1: dependencies: balanced-match "^0.4.2" +redux-thunk@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" + +redux@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03" + dependencies: + loose-envify "^1.1.0" + symbol-observable "^1.2.0" + regenerate@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" @@ -7604,6 +7630,10 @@ symbol-observable@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + symbol-tree@^3.2.1, symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" From 79ec89f371515d14c897b392b8171c4e9c90fcdc Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Wed, 2 May 2018 19:19:14 +0530 Subject: [PATCH 2/7] create base for react-workshop added three phases of api requests added redux folder added mapDispatchToProps and mapStateToProps to all the components --- src/client/actions/index.js | 25 ------- src/client/components/AddToCart.js | 20 +++++- src/client/components/Cart.js | 6 +- src/client/components/CartBadge.js | 21 ++++-- src/client/components/Product.js | 34 +++++++--- src/client/components/Products.js | 24 ++++--- src/client/reducers/cartItems.js | 8 --- src/client/redux/actionTypes/index.js | 9 +++ src/client/redux/actions/index.js | 72 +++++++++++++++++++++ src/client/redux/reducers/cartItems.js | 14 ++++ src/client/{ => redux}/reducers/index.js | 0 src/client/{ => redux}/reducers/products.js | 4 +- src/client/store.js | 2 +- src/server/connectors/index.js | 14 ++-- src/server/index.js | 3 +- 15 files changed, 184 insertions(+), 72 deletions(-) delete mode 100644 src/client/actions/index.js delete mode 100644 src/client/reducers/cartItems.js create mode 100644 src/client/redux/actionTypes/index.js create mode 100644 src/client/redux/actions/index.js create mode 100644 src/client/redux/reducers/cartItems.js rename src/client/{ => redux}/reducers/index.js (100%) rename src/client/{ => redux}/reducers/products.js (63%) diff --git a/src/client/actions/index.js b/src/client/actions/index.js deleted file mode 100644 index f17c4fd..0000000 --- a/src/client/actions/index.js +++ /dev/null @@ -1,25 +0,0 @@ -export function fetchProducts() { - return function(dispatch) { - return fetch("/api/products").then(res => - res.json().then(products => { - dispatch({ - type: "SET_PRODUCTS", - payload: products - }); - }) - ); - }; -} - -export function fetchCartItems() { - return function(dispatch) { - return fetch("/api/cart-items").then(res => - res.json().then(cartItems => { - dispatch({ - type: "SET_CART_ITEMS", - payload: cartItems - }); - }) - ); - }; -} diff --git a/src/client/components/AddToCart.js b/src/client/components/AddToCart.js index 1684f9d..c26d365 100644 --- a/src/client/components/AddToCart.js +++ b/src/client/components/AddToCart.js @@ -1,12 +1,26 @@ import React from "react"; -import { Button, UncontrolledAlert } from "reactstrap"; +import { bindActionCreators } from "redux"; +import { connect } from "react-redux"; +import { Button } from "reactstrap"; +import * as actionCreators from "../redux/actions"; -export default class AddToCart extends React.Component { +class AddToCart extends React.Component { render() { + const { actions: { addItemsToCart }, product } = this.props; return ( - ); } } + +const mapDispatchToProps = dispatch => ({ + actions: bindActionCreators(actionCreators, dispatch) +}); + +export default connect(null, mapDispatchToProps)(AddToCart); diff --git a/src/client/components/Cart.js b/src/client/components/Cart.js index cee176a..f0e8923 100644 --- a/src/client/components/Cart.js +++ b/src/client/components/Cart.js @@ -32,4 +32,8 @@ export class Cart extends React.Component { } } -export default connect(state => ({ cartItems: state.cartItems }))(Cart); +const mapStateToProps = state => ({ + cartItems: state.cartItems +}); + +export default connect(mapStateToProps)(Cart); diff --git a/src/client/components/CartBadge.js b/src/client/components/CartBadge.js index 6287794..479f999 100644 --- a/src/client/components/CartBadge.js +++ b/src/client/components/CartBadge.js @@ -1,12 +1,15 @@ import React from "react"; -import { Badge } from "reactstrap"; +import { bindActionCreators } from "redux"; import { connect } from "react-redux"; -import { fetchCartItems } from "../actions"; +import * as actions from "../redux/actions"; +import { Badge } from "reactstrap"; class CartBadge extends React.Component { componentDidMount() { - this.props.fetchCartItems(); + const { actions } = this.props; + actions.getCartItems(); } + render() { const { cartItems } = this.props; if (!cartItems) { @@ -18,6 +21,12 @@ class CartBadge extends React.Component { } } -export default connect(state => ({ cartItems: state.cartItems }), { - fetchCartItems -})(CartBadge); +const mapStateToProps = state => ({ + cartItems: state.cartItems +}); + +const mapDispatchToProps = dispatch => ({ + actions: bindActionCreators(actions, dispatch) +}); + +export default connect(mapStateToProps, mapDispatchToProps)(CartBadge); diff --git a/src/client/components/Product.js b/src/client/components/Product.js index 59cd9dd..ad8b1fc 100644 --- a/src/client/components/Product.js +++ b/src/client/components/Product.js @@ -1,12 +1,24 @@ import React from "react"; +import { bindActionCreators } from "redux"; +import { connect } from "react-redux"; import { Media } from "reactstrap"; +import * as actionCreators from "../redux/actions"; import AddToCart from "./AddToCart"; import Price from "./Price"; -import { connect } from "react-redux"; -export class Product extends React.Component { +class Product extends React.Component { + componentDidMount() { + const { product, actions, match } = this.props; + if (!product) { + const productId = parseInt(match.params.id, 10); + actions.getProducts(productId); + } + } + render() { - const { product } = this.props; + const { products, match } = this.props; + const productId = parseInt(match.params.id, 10); + const product = products.length && products.find(p => p.id === productId); if (!product) { return null; } @@ -28,10 +40,12 @@ export class Product extends React.Component { } } -export default connect((state, props) => { - return { - product: state.products.find( - p => p.id === parseInt(props.match.params.id, 10) - ) - }; -})(Product); +const mapStateToProps = (state, props) => ({ + products: state.products +}); + +const mapDisptachToProps = dispatch => ({ + actions: bindActionCreators(actionCreators, dispatch) +}); + +export default connect(mapStateToProps, mapDisptachToProps)(Product); diff --git a/src/client/components/Products.js b/src/client/components/Products.js index 1d1476b..6c2d5cc 100644 --- a/src/client/components/Products.js +++ b/src/client/components/Products.js @@ -1,10 +1,11 @@ import React from "react"; +import { bindActionCreators } from "redux"; +import { connect } from "react-redux"; import { Link } from "react-router-dom"; import { ListGroup, ListGroupItem } from "reactstrap"; -import ProductSelect from "./ProductSelect"; +import * as productActionCreators from "../redux/actions"; import Price from "./Price"; -import { connect } from "react-redux"; -import { fetchProducts } from "../actions"; +import ProductSelect from "./ProductSelect"; function Product({ product }) { return ( @@ -22,9 +23,10 @@ function Product({ product }) { ); } -export class Products extends React.Component { +class Products extends React.Component { componentDidMount() { - this.props.fetchProducts(); + const { productActions } = this.props; + productActions.getProducts(); } render() { const { products } = this.props; @@ -41,6 +43,12 @@ export class Products extends React.Component { } } -export default connect(state => ({ products: state.products }), { - fetchProducts -})(Products); +const mapStateToProps = state => ({ + products: state.products +}); + +const mapDispatchToProps = dispatch => ({ + productActions: bindActionCreators(productActionCreators, dispatch) +}); + +export default connect(mapStateToProps, mapDispatchToProps)(Products); diff --git a/src/client/reducers/cartItems.js b/src/client/reducers/cartItems.js deleted file mode 100644 index 1c35f57..0000000 --- a/src/client/reducers/cartItems.js +++ /dev/null @@ -1,8 +0,0 @@ -export default function cartItemsReducer(state = [], action) { - switch (action.type) { - case "SET_CART_ITEMS": - return action.payload; - default: - return state; - } -} diff --git a/src/client/redux/actionTypes/index.js b/src/client/redux/actionTypes/index.js new file mode 100644 index 0000000..b4ea067 --- /dev/null +++ b/src/client/redux/actionTypes/index.js @@ -0,0 +1,9 @@ +export const GET_PRODUCTS_REQUEST = "GET_PRODUCTS_REQUEST"; +export const GET_PRODUCTS_SUCCESS = "GET_PRODUCTS_SUCCESS"; +export const GET_PRODUCTS_FAILURE = "GET_PRODUCTS_SUCCESS"; +export const GET_CART_ITEMS_REQUEST = "GET_CART_ITEMS_REQUEST"; +export const GET_CART_ITEMS_SUCCESS = "GET_CART_ITEMS_SUCCESS"; +export const GET_CART_ITEMS_FAILURE = "GET_CART_ITEMS_FAILURE"; +export const ADD_ITEMS_TO_CART_REQUEST = "ADD_ITEMS_TO_CART_REQUEST"; +export const ADD_ITEMS_TO_CART_SUCCESS = "ADD_ITEMS_TO_CART_SUCCESS"; +export const ADD_ITEMS_TO_CART_FAILURE = "ADD_ITEMS_TO_CART_FAILURE"; diff --git a/src/client/redux/actions/index.js b/src/client/redux/actions/index.js new file mode 100644 index 0000000..771fd14 --- /dev/null +++ b/src/client/redux/actions/index.js @@ -0,0 +1,72 @@ +import * as actionTypes from "../actionTypes"; + +export const getProducts = productId => { + return dispatch => { + dispatch({ type: actionTypes.GET_PRODUCTS_REQUEST }); + const apiUrl = productId ? `/api/products/${productId}` : "/api/products"; + console.log(apiUrl); + return fetch(apiUrl).then(async response => { + const responseData = await response.json(); + if (response.ok) { + dispatch({ + type: actionTypes.GET_PRODUCTS_SUCCESS, + payload: responseData + }); + } else { + dispatch({ + type: actionTypes.GET_PRODUCTS_FAILURE, + payload: "Cannot Fetch Products" + }); + } + }); + }; +}; + +export const getCartItems = () => { + return dispatch => { + dispatch({ type: actionTypes.GET_CART_ITEMS_REQUEST }); + return fetch("/api/cart-items").then(async response => { + const responseData = await response.json(); + if (response.ok) { + dispatch({ + type: actionTypes.GET_CART_ITEMS_SUCCESS, + payload: responseData + }); + } else { + dispatch({ + type: actionTypes.GET_CART_ITEMS_FAILURE, + payload: "Cannot Fetch Products" + }); + } + }); + }; +}; + +export const addItemsToCart = product => { + const data = { + productId: product.id + }; + return dispatch => { + dispatch({ type: actionTypes.ADD_ITEMS_TO_CART_REQUEST }); + return fetch("/api/cart-items", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json" + } + }).then(async response => { + const responseData = await response.json(); + if (response.ok) { + dispatch({ + type: actionTypes.ADD_ITEMS_TO_CART_SUCCESS, + payload: responseData + }); + } else { + dispatch({ + type: actionTypes.ADD_ITEMS_TO_CART_FAILURE, + payload: "Cannot add Products" + }); + } + }); + }; +}; diff --git a/src/client/redux/reducers/cartItems.js b/src/client/redux/reducers/cartItems.js new file mode 100644 index 0000000..40cbb43 --- /dev/null +++ b/src/client/redux/reducers/cartItems.js @@ -0,0 +1,14 @@ +import * as actionTypes from "../actionTypes"; + +export default function cartItemsReducer(state = [], action) { + switch (action.type) { + case actionTypes.GET_CART_ITEMS_SUCCESS: + return [...state, ...action.payload]; + + case actionTypes.ADD_ITEMS_TO_CART_SUCCESS: + return [...state, action.payload]; + + default: + return state; + } +} diff --git a/src/client/reducers/index.js b/src/client/redux/reducers/index.js similarity index 100% rename from src/client/reducers/index.js rename to src/client/redux/reducers/index.js diff --git a/src/client/reducers/products.js b/src/client/redux/reducers/products.js similarity index 63% rename from src/client/reducers/products.js rename to src/client/redux/reducers/products.js index d757014..61ce489 100644 --- a/src/client/reducers/products.js +++ b/src/client/redux/reducers/products.js @@ -1,6 +1,8 @@ +import * as actionTypes from "../actionTypes"; + export default function productsReducer(state = [], action) { switch (action.type) { - case "SET_PRODUCTS": + case actionTypes.GET_PRODUCTS_SUCCESS: return action.payload; default: return state; diff --git a/src/client/store.js b/src/client/store.js index 48aa55d..581d1da 100644 --- a/src/client/store.js +++ b/src/client/store.js @@ -1,5 +1,5 @@ import { createStore, applyMiddleware, compose } from "redux"; -import rootReducer from "./reducers"; +import rootReducer from "./redux/reducers"; import thunk from "redux-thunk"; export default function configureStore() { diff --git a/src/server/connectors/index.js b/src/server/connectors/index.js index 69d3572..580c78a 100644 --- a/src/server/connectors/index.js +++ b/src/server/connectors/index.js @@ -30,7 +30,8 @@ export function getProducts() { } export function getProduct(id) { - return products.find(product => product.id === id); + console.log("productId", id); + return [products.find(product => product.id === id)]; } export function getCartItem(id) { @@ -38,19 +39,16 @@ export function getCartItem(id) { } export function getCartItems() { - return cartItems.map(c => ({ - ...c, - product: getProduct(c.productId) - })); + return cartItems; } -export function addToCart(args) { - if (cartItems.find(c => c.productId === parseInt(args.productId, 10))) { +export function addToCart({ productId }) { + if (cartItems.find(c => c.productId === parseInt(productId, 10))) { throw new Error("Product already in cart"); } const newCartItem = { id: cartItems.length + 1, - productId: parseInt(args.productId, 10) + product: products.find(p => p.id === productId) }; cartItems.push(newCartItem); return newCartItem; diff --git a/src/server/index.js b/src/server/index.js index 031bf40..1b44b11 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -13,7 +13,7 @@ import { const PORT = 8000; const app = express(); -app.use(bodyParser.urlencoded({ extended: false })); +app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use( @@ -45,6 +45,7 @@ app.get("/api/products", function(req, res) { app.get("/api/products/:id", function(req, res) { const id = parseInt(req.params.id, 10); + console.log("product id", id); res.json(getProduct(id)); }); From 5742e422f68ee757b68295ff408ce9a6e869c2bd Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 3 May 2018 14:56:02 +0530 Subject: [PATCH 3/7] created first checkpoint for redux workshop implemented concept of transformers listening to all request start actions simulated a real time api call by adding set timeout to add item to cart api --- src/client/components/AddToCart.js | 14 ++++++-- src/client/components/Cart.js | 4 +-- src/client/components/CartBadge.js | 6 ++-- src/client/components/Product.js | 2 +- src/client/components/Products.js | 2 +- src/client/redux/actions/index.js | 9 +++-- src/client/redux/reducers/cartItems.js | 33 +++++++++++++++++-- src/client/redux/reducers/products.js | 31 +++++++++++++++-- .../transformers/transformGetCartItemsApi.js | 10 ++++++ .../transformers/transformProductsApi.js | 10 ++++++ src/server/connectors/index.js | 7 ++-- src/server/index.js | 3 +- 12 files changed, 109 insertions(+), 22 deletions(-) create mode 100644 src/client/redux/transformers/transformGetCartItemsApi.js create mode 100644 src/client/redux/transformers/transformProductsApi.js diff --git a/src/client/components/AddToCart.js b/src/client/components/AddToCart.js index c26d365..f26366c 100644 --- a/src/client/components/AddToCart.js +++ b/src/client/components/AddToCart.js @@ -6,21 +6,29 @@ import * as actionCreators from "../redux/actions"; class AddToCart extends React.Component { render() { - const { actions: { addItemsToCart }, product } = this.props; + const { + actions: { addItemsToCart }, + cartItems: { isLoading }, + product + } = this.props; return ( ); } } +const mapStateToProps = state => ({ + cartItems: state.cartItems +}); + const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(actionCreators, dispatch) }); -export default connect(null, mapDispatchToProps)(AddToCart); +export default connect(mapStateToProps, mapDispatchToProps)(AddToCart); diff --git a/src/client/components/Cart.js b/src/client/components/Cart.js index f0e8923..82fe003 100644 --- a/src/client/components/Cart.js +++ b/src/client/components/Cart.js @@ -19,12 +19,12 @@ function CartItem({ cartItem }) { export class Cart extends React.Component { render() { const { cartItems } = this.props; - if (!cartItems.length) { + if (!cartItems.ids.length) { return Cart is empty; } return ( - {cartItems.map(cartItem => ( + {Object.values(cartItems.byId).map(cartItem => ( ))} diff --git a/src/client/components/CartBadge.js b/src/client/components/CartBadge.js index 479f999..3784d1e 100644 --- a/src/client/components/CartBadge.js +++ b/src/client/components/CartBadge.js @@ -12,11 +12,11 @@ class CartBadge extends React.Component { render() { const { cartItems } = this.props; - if (!cartItems) { + if (!cartItems.ids.length) { return null; } - return cartItems.length ? ( - {cartItems.length} + return cartItems.ids.length ? ( + {cartItems.ids.length} ) : null; } } diff --git a/src/client/components/Product.js b/src/client/components/Product.js index ad8b1fc..4166004 100644 --- a/src/client/components/Product.js +++ b/src/client/components/Product.js @@ -18,7 +18,7 @@ class Product extends React.Component { render() { const { products, match } = this.props; const productId = parseInt(match.params.id, 10); - const product = products.length && products.find(p => p.id === productId); + const product = products.ids.length && products.byId[productId]; if (!product) { return null; } diff --git a/src/client/components/Products.js b/src/client/components/Products.js index 6c2d5cc..33d5e46 100644 --- a/src/client/components/Products.js +++ b/src/client/components/Products.js @@ -34,7 +34,7 @@ class Products extends React.Component {
Products - {products.map(product => ( + {Object.values(products.byId).map(product => ( ))} diff --git a/src/client/redux/actions/index.js b/src/client/redux/actions/index.js index 771fd14..89bb2ad 100644 --- a/src/client/redux/actions/index.js +++ b/src/client/redux/actions/index.js @@ -1,16 +1,18 @@ import * as actionTypes from "../actionTypes"; +import { transformProductsApi } from "../transformers/transformProductsApi"; +import { transformGetCartItemsApi } from "../transformers/transformGetCartItemsApi"; export const getProducts = productId => { return dispatch => { dispatch({ type: actionTypes.GET_PRODUCTS_REQUEST }); const apiUrl = productId ? `/api/products/${productId}` : "/api/products"; - console.log(apiUrl); return fetch(apiUrl).then(async response => { const responseData = await response.json(); if (response.ok) { + const data = transformProductsApi(responseData); dispatch({ type: actionTypes.GET_PRODUCTS_SUCCESS, - payload: responseData + payload: data }); } else { dispatch({ @@ -28,9 +30,10 @@ export const getCartItems = () => { return fetch("/api/cart-items").then(async response => { const responseData = await response.json(); if (response.ok) { + const data = transformGetCartItemsApi(responseData); dispatch({ type: actionTypes.GET_CART_ITEMS_SUCCESS, - payload: responseData + payload: data }); } else { dispatch({ diff --git a/src/client/redux/reducers/cartItems.js b/src/client/redux/reducers/cartItems.js index 40cbb43..4f9dcf8 100644 --- a/src/client/redux/reducers/cartItems.js +++ b/src/client/redux/reducers/cartItems.js @@ -1,12 +1,39 @@ import * as actionTypes from "../actionTypes"; -export default function cartItemsReducer(state = [], action) { +const initialState = { + byId: {}, + ids: [], + isLoading: false, + isError: false, + errorMsg: "" +}; + +export default function cartItemsReducer(state = initialState, action) { switch (action.type) { + case actionTypes.ADD_ITEMS_TO_CART_REQUEST: + case actionTypes.GET_CART_ITEMS_REQUEST: + return { + ...state, + isLoading: true + }; + case actionTypes.GET_CART_ITEMS_SUCCESS: - return [...state, ...action.payload]; + return { + ...state, + ...action.payload, + isLoading: false + }; case actionTypes.ADD_ITEMS_TO_CART_SUCCESS: - return [...state, action.payload]; + return { + ...state, + byId: { + ...state.byId, + [action.payload.id]: action.payload + }, + ids: [...state.ids, action.payload.id], + isLoading: false + }; default: return state; diff --git a/src/client/redux/reducers/products.js b/src/client/redux/reducers/products.js index 61ce489..a6ada10 100644 --- a/src/client/redux/reducers/products.js +++ b/src/client/redux/reducers/products.js @@ -1,9 +1,36 @@ import * as actionTypes from "../actionTypes"; -export default function productsReducer(state = [], action) { +const initialState = { + byId: {}, + ids: [], + isLoading: false, + isError: false, + errorMsg: "" +}; + +export default function productsReducer(state = initialState, action) { switch (action.type) { + case actionTypes.GET_CART_ITEMS_REQUEST: + return { + ...state, + isLoading: true + }; + case actionTypes.GET_PRODUCTS_SUCCESS: - return action.payload; + return { + ...state, + ...action.payload, + isLoading: false + }; + + case actionTypes.GET_PRODUCTS_FAILURE: + return { + ...state, + isLoading: false, + isError: true, + errorMsg: action.payload + }; + default: return state; } diff --git a/src/client/redux/transformers/transformGetCartItemsApi.js b/src/client/redux/transformers/transformGetCartItemsApi.js new file mode 100644 index 0000000..03647f6 --- /dev/null +++ b/src/client/redux/transformers/transformGetCartItemsApi.js @@ -0,0 +1,10 @@ +export const transformGetCartItemsApi = data => ({ + byId: data.reduce( + (obj, cartItem) => ({ + ...obj, + [cartItem.id]: cartItem + }), + {} + ), + ids: data.map(cartItem => cartItem.id) +}); diff --git a/src/client/redux/transformers/transformProductsApi.js b/src/client/redux/transformers/transformProductsApi.js new file mode 100644 index 0000000..0e3980e --- /dev/null +++ b/src/client/redux/transformers/transformProductsApi.js @@ -0,0 +1,10 @@ +export const transformProductsApi = data => ({ + byId: data.reduce( + (obj, product) => ({ + ...obj, + [product.id]: product + }), + {} + ), + ids: data.map(product => product.id) +}); diff --git a/src/server/connectors/index.js b/src/server/connectors/index.js index 580c78a..79f3a0a 100644 --- a/src/server/connectors/index.js +++ b/src/server/connectors/index.js @@ -30,7 +30,6 @@ export function getProducts() { } export function getProduct(id) { - console.log("productId", id); return [products.find(product => product.id === id)]; } @@ -51,7 +50,11 @@ export function addToCart({ productId }) { product: products.find(p => p.id === productId) }; cartItems.push(newCartItem); - return newCartItem; + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(newCartItem); + }, 5000); + }); } export function deleteCartItem(args) { diff --git a/src/server/index.js b/src/server/index.js index 1b44b11..8db428c 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -45,7 +45,6 @@ app.get("/api/products", function(req, res) { app.get("/api/products/:id", function(req, res) { const id = parseInt(req.params.id, 10); - console.log("product id", id); res.json(getProduct(id)); }); @@ -59,7 +58,7 @@ app.get("/api/cart-items/:id", function(req, res) { }); app.post("/api/cart-items", function(req, res) { - res.json(addToCart(req.body)); + addToCart(req.body).then(res.json); }); app.post("/api/cart-items/:id", function(req, res) { From 7edf569128d76e35bc75d732bd0957423d0d7a29 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 3 May 2018 20:49:48 +0530 Subject: [PATCH 4/7] bug fix --- src/server/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/index.js b/src/server/index.js index 8db428c..b043fe5 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -58,7 +58,7 @@ app.get("/api/cart-items/:id", function(req, res) { }); app.post("/api/cart-items", function(req, res) { - addToCart(req.body).then(res.json); + addToCart(req.body).then(response => res.json(response)); }); app.post("/api/cart-items/:id", function(req, res) { From c40ff7607e3c2e5ead028b82c17a5f541988799a Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 3 May 2018 23:16:18 +0530 Subject: [PATCH 5/7] add redux-pack and refactor code --- package.json | 1 + src/client/redux/actionTypes/index.js | 3 + src/client/redux/actions/index.js | 86 +++++++++++--------------- src/client/redux/reducers/cartItems.js | 58 ++++++++++------- src/client/redux/reducers/products.js | 39 ++++++------ src/client/store.js | 5 +- yarn.lock | 14 ++++- 7 files changed, 110 insertions(+), 96 deletions(-) diff --git a/package.json b/package.json index 1f211b3..3f457d4 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react-scripts": "1.0.17", "reactstrap": "^5.0.0-beta.3", "redux": "^4.0.0", + "redux-pack": "0.1.5", "redux-thunk": "^2.2.0", "uuid": "^3.1.0" }, diff --git a/src/client/redux/actionTypes/index.js b/src/client/redux/actionTypes/index.js index b4ea067..ce5bcf9 100644 --- a/src/client/redux/actionTypes/index.js +++ b/src/client/redux/actionTypes/index.js @@ -1,3 +1,6 @@ +export const GET_PRODUCTS = "GET_PRODUCTS"; +export const GET_CART_ITEMS = "GET_CART_ITEMS"; +export const ADD_ITEMS_TO_CART = "ADD_ITEMS_TO_CART"; export const GET_PRODUCTS_REQUEST = "GET_PRODUCTS_REQUEST"; export const GET_PRODUCTS_SUCCESS = "GET_PRODUCTS_SUCCESS"; export const GET_PRODUCTS_FAILURE = "GET_PRODUCTS_SUCCESS"; diff --git a/src/client/redux/actions/index.js b/src/client/redux/actions/index.js index 89bb2ad..e6e82b8 100644 --- a/src/client/redux/actions/index.js +++ b/src/client/redux/actions/index.js @@ -4,43 +4,33 @@ import { transformGetCartItemsApi } from "../transformers/transformGetCartItemsA export const getProducts = productId => { return dispatch => { - dispatch({ type: actionTypes.GET_PRODUCTS_REQUEST }); const apiUrl = productId ? `/api/products/${productId}` : "/api/products"; - return fetch(apiUrl).then(async response => { - const responseData = await response.json(); - if (response.ok) { - const data = transformProductsApi(responseData); - dispatch({ - type: actionTypes.GET_PRODUCTS_SUCCESS, - payload: data - }); - } else { - dispatch({ - type: actionTypes.GET_PRODUCTS_FAILURE, - payload: "Cannot Fetch Products" - }); - } + return dispatch({ + type: actionTypes.GET_PRODUCTS, + promise: fetch(apiUrl).then(async response => { + const responseData = await response.json(); + if (response.ok) { + return transformProductsApi(responseData); + } else { + Promise.reject("Something went wrong"); + } + }) }); }; }; export const getCartItems = () => { return dispatch => { - dispatch({ type: actionTypes.GET_CART_ITEMS_REQUEST }); - return fetch("/api/cart-items").then(async response => { - const responseData = await response.json(); - if (response.ok) { - const data = transformGetCartItemsApi(responseData); - dispatch({ - type: actionTypes.GET_CART_ITEMS_SUCCESS, - payload: data - }); - } else { - dispatch({ - type: actionTypes.GET_CART_ITEMS_FAILURE, - payload: "Cannot Fetch Products" - }); - } + return dispatch({ + type: actionTypes.GET_CART_ITEMS, + promise: fetch("/api/cart-items").then(async response => { + const responseData = await response.json(); + if (response.ok) { + return transformGetCartItemsApi(responseData); + } else { + Promise.reject("Something went wrong"); + } + }) }); }; }; @@ -50,26 +40,22 @@ export const addItemsToCart = product => { productId: product.id }; return dispatch => { - dispatch({ type: actionTypes.ADD_ITEMS_TO_CART_REQUEST }); - return fetch("/api/cart-items", { - method: "POST", - body: JSON.stringify(data), - headers: { - "Content-Type": "application/json" - } - }).then(async response => { - const responseData = await response.json(); - if (response.ok) { - dispatch({ - type: actionTypes.ADD_ITEMS_TO_CART_SUCCESS, - payload: responseData - }); - } else { - dispatch({ - type: actionTypes.ADD_ITEMS_TO_CART_FAILURE, - payload: "Cannot add Products" - }); - } + return dispatch({ + type: actionTypes.ADD_ITEMS_TO_CART, + promise: fetch("/api/cart-items", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json" + } + }).then(async response => { + const responseData = await response.json(); + if (response.ok) { + return responseData; + } else { + return Promise.reject("Something went wrong"); + } + }) }); }; }; diff --git a/src/client/redux/reducers/cartItems.js b/src/client/redux/reducers/cartItems.js index 4f9dcf8..0d111ab 100644 --- a/src/client/redux/reducers/cartItems.js +++ b/src/client/redux/reducers/cartItems.js @@ -1,4 +1,5 @@ import * as actionTypes from "../actionTypes"; +import { handle } from "redux-pack"; const initialState = { byId: {}, @@ -10,30 +11,41 @@ const initialState = { export default function cartItemsReducer(state = initialState, action) { switch (action.type) { - case actionTypes.ADD_ITEMS_TO_CART_REQUEST: - case actionTypes.GET_CART_ITEMS_REQUEST: - return { - ...state, - isLoading: true - }; + case actionTypes.GET_CART_ITEMS: + return handle(state, action, { + start: s => ({ ...s, isLoading: true }), + success: s => ({ + ...s, + ...action.payload, + isLoading: false + }), + failure: s => ({ + ...s, + isLoading: false, + isError: true, + errorMsg: action.payload + }) + }); - case actionTypes.GET_CART_ITEMS_SUCCESS: - return { - ...state, - ...action.payload, - isLoading: false - }; - - case actionTypes.ADD_ITEMS_TO_CART_SUCCESS: - return { - ...state, - byId: { - ...state.byId, - [action.payload.id]: action.payload - }, - ids: [...state.ids, action.payload.id], - isLoading: false - }; + case actionTypes.ADD_ITEMS_TO_CART: + return handle(state, action, { + start: s => ({ ...s, isLoading: true }), + success: s => ({ + ...s, + byId: { + ...state.byId, + [action.payload.id]: action.payload + }, + ids: [...state.ids, action.payload.id], + isLoading: false + }), + failure: s => ({ + ...s, + isLoading: false, + isError: true, + errorMsg: action.payload + }) + }); default: return state; diff --git a/src/client/redux/reducers/products.js b/src/client/redux/reducers/products.js index a6ada10..95231d5 100644 --- a/src/client/redux/reducers/products.js +++ b/src/client/redux/reducers/products.js @@ -1,4 +1,5 @@ import * as actionTypes from "../actionTypes"; +import { handle } from "redux-pack"; const initialState = { byId: {}, @@ -10,26 +11,24 @@ const initialState = { export default function productsReducer(state = initialState, action) { switch (action.type) { - case actionTypes.GET_CART_ITEMS_REQUEST: - return { - ...state, - isLoading: true - }; - - case actionTypes.GET_PRODUCTS_SUCCESS: - return { - ...state, - ...action.payload, - isLoading: false - }; - - case actionTypes.GET_PRODUCTS_FAILURE: - return { - ...state, - isLoading: false, - isError: true, - errorMsg: action.payload - }; + case actionTypes.GET_PRODUCTS: + return handle(state, action, { + start: s => ({ + ...s, + isLoading: true + }), + success: s => ({ + ...s, + ...action.payload, + isLoading: false + }), + failure: s => ({ + ...s, + isLoading: false, + isError: true, + errorMsg: action.payload + }) + }); default: return state; diff --git a/src/client/store.js b/src/client/store.js index 581d1da..08e9bfd 100644 --- a/src/client/store.js +++ b/src/client/store.js @@ -1,13 +1,14 @@ import { createStore, applyMiddleware, compose } from "redux"; -import rootReducer from "./redux/reducers"; import thunk from "redux-thunk"; +import { middleware as reduxPack } from "redux-pack"; +import rootReducer from "./redux/reducers"; export default function configureStore() { const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( rootReducer, - composeEnhancers(applyMiddleware(thunk)) + composeEnhancers(applyMiddleware(thunk, reduxPack)) ); return store; } diff --git a/yarn.lock b/yarn.lock index 78c06ea..f8164eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2238,6 +2238,10 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" +deline@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/deline/-/deline-1.0.4.tgz#6c05c87836926e1a1c63e47882f3d2eb2c6f14c9" + depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" @@ -6700,6 +6704,14 @@ reduce-function-call@^1.0.1: dependencies: balanced-match "^0.4.2" +redux-pack@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/redux-pack/-/redux-pack-0.1.5.tgz#1973b26ef749dfc020e8a61d54cf3e55ec8ae4cd" + dependencies: + deline "^1.0.4" + invariant "^2.2.2" + uuid "^3.0.1" + redux-thunk@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" @@ -8019,7 +8031,7 @@ uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" -uuid@^3.0.0, uuid@^3.1.0: +uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" From 6db71cc62ade6a19759274c1717915cd85b92554 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Fri, 4 May 2018 10:59:57 +0530 Subject: [PATCH 6/7] common problems with large scale applications added common problems implemented solution of common problems --- package.json | 1 + src/client/components/AddToCart.js | 1 + src/client/components/App.js | 3 ++- src/client/components/Header.js | 20 ++++++++++++++++++++ src/client/components/Products.js | 24 ++++++++++++++++++++---- src/client/redux/reducers/products.js | 6 +++++- src/server/connectors/index.js | 24 +++++++++++++++++++++++- src/server/index.js | 11 ++++++++--- yarn.lock | 4 ++++ 9 files changed, 84 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3f457d4..fc61684 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "bootstrap": "^4.0.0", "classnames": "^2.2.5", "express": "^4.16.2", + "lodash": "4.17.10", "mongoose": "^4.13.6", "react": "^16.0.0", "react-dom": "^16.0.0", diff --git a/src/client/components/AddToCart.js b/src/client/components/AddToCart.js index f26366c..6fb2d61 100644 --- a/src/client/components/AddToCart.js +++ b/src/client/components/AddToCart.js @@ -13,6 +13,7 @@ class AddToCart extends React.Component { } = this.props; return (