- {title} - ${price}{inventory ? ` x ${inventory}` : null}
+const Product = ({ price, quantity, title, image }) => (
+
)
Product.propTypes = {
price: PropTypes.number,
- inventory: PropTypes.number,
- title: PropTypes.string
+ quantity: PropTypes.number,
+ title: PropTypes.string,
+ image: PropTypes.string
}
export default Product
diff --git a/src/components/ProductItem.css b/src/components/ProductItem.css
new file mode 100644
index 0000000..bd9de7f
--- /dev/null
+++ b/src/components/ProductItem.css
@@ -0,0 +1,91 @@
+:local(.productitem){
+ display: flex;
+ align-items: center;
+}
+
+@media only screen and (min-width: 1401px) {
+ .btn {
+ position: relative;
+ bottom: 3rem;
+ right: 6rem;
+ }
+}
+
+@media only screen and (max-width: 1400px) {
+ .btn {
+ position: relative;
+ bottom: 3rem;
+ right: 5.5rem;
+ }
+}
+
+@media only screen and (max-width: 1280px) {
+ .btn {
+ position: relative;
+ bottom: 3rem;
+ right: 4.5rem;
+ }
+}
+
+@media only screen and (max-width: 1180px) {
+ .btn {
+ position: relative;
+ bottom: 3rem;
+ right: 4rem;
+ }
+}
+
+@media only screen and (max-width: 1024px) {
+ .btn {
+ position: relative;
+ bottom: 3rem;
+ right: 2.5rem;
+ }
+}
+
+@media only screen and (max-width: 768px) {
+ .btn {
+ position: relative;
+ bottom: 3rem;
+ left: 2rem;
+ }
+}
+
+@media only screen and (max-width: 544px) {
+ .btn {
+ position: relative;
+ bottom: 3rem;
+ left: 2rem;
+ }
+}
+
+@media only screen and (max-width: 320px) {
+ .btn {
+ position: relative;
+ bottom: 0;
+ left: 0rem;
+ }
+}
+
+.add {
+ border: none;
+ color: white;
+ background-color: #3eab93;
+ border-radius: .20rem;
+ padding: .5rem 1rem;
+ margin: 1rem;
+}
+
+.add:hover {
+ background-color: #27987f;
+}
+
+.add:disabled {
+ background-color: #dfdfdf;
+ cursor: pointer;
+}
+
+hr {
+ border-top: silver solid 1px;
+}
+
diff --git a/src/components/ProductItem.js b/src/components/ProductItem.js
index f8f8131..2824b01 100644
--- a/src/components/ProductItem.js
+++ b/src/components/ProductItem.js
@@ -1,18 +1,26 @@
import React from 'react'
import PropTypes from 'prop-types'
import Product from './Product'
+import styles from './ProductItem.css'
const ProductItem = ({ product, onAddToCartClicked }) => (
-
-
-
0 ? '' : 'disabled'}>
- {product.inventory > 0 ? 'Add to cart' : 'Sold Out'}
-
+
+
+
+
+
+ 0 ? '' : 'disabled'}>
+ {product.inventory > 0 ? 'ADD TO CART' : 'SOLD OUT'}
+
+
+
)
@@ -20,9 +28,10 @@ ProductItem.propTypes = {
product: PropTypes.shape({
title: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
+ image: PropTypes.string.isRequired,
inventory: PropTypes.number.isRequired
}).isRequired,
- onAddToCartClicked: PropTypes.func.isRequired
+ onAddToCartClicked: PropTypes.func.isRequired,
}
export default ProductItem
diff --git a/src/components/ProductList.css b/src/components/ProductList.css
new file mode 100644
index 0000000..6209718
--- /dev/null
+++ b/src/components/ProductList.css
@@ -0,0 +1,23 @@
+:local(.productlist){
+ display: flex;
+ float: right;
+ width: 65%;
+ margin: 1rem;
+ justify-content: center;
+}
+
+@media only screen and (max-width: 544px) {
+ :local(.productlist){
+ display: block;
+ margin: 0;
+ width: 100%;
+ }
+}
+
+@media only screen and (max-width: 320px) {
+ :local(.productlist){
+ display: block;
+ margin: 0;
+ width: 100%;
+ }
+}
diff --git a/src/components/ProductsList.js b/src/components/ProductsList.js
index f0265fc..3a3a7d3 100644
--- a/src/components/ProductsList.js
+++ b/src/components/ProductsList.js
@@ -1,16 +1,15 @@
import React from 'react'
import PropTypes from 'prop-types'
+import styles from './ProductList.css'
-const ProductsList = ({ title, children }) => (
-
-
{title}
+const ProductsList = ({ children }) => (
+
)
ProductsList.propTypes = {
children: PropTypes.node,
- title: PropTypes.string.isRequired
}
export default ProductsList
diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js
index 6cbabea..3e357f8 100644
--- a/src/constants/ActionTypes.js
+++ b/src/constants/ActionTypes.js
@@ -1,4 +1,7 @@
export const ADD_TO_CART = 'ADD_TO_CART'
+export const DELETE_FROM_CART = 'DELETE_FROM_CART'
+export const INCREASE_QUANTITY = 'INCREASE_QUANTITY'
+export const DECREASE_QUANTITY = 'DECREASE_QUANTITY'
export const CHECKOUT_REQUEST = 'CHECKOUT_REQUEST'
export const CHECKOUT_SUCCESS = 'CHECKOUT_SUCCESS'
export const CHECKOUT_FAILURE = 'CHECKOUT_FAILURE'
diff --git a/src/containers/App.js b/src/containers/App.js
index 7625918..5903ed3 100644
--- a/src/containers/App.js
+++ b/src/containers/App.js
@@ -4,11 +4,8 @@ import CartContainer from './CartContainer'
const App = () => (
-
Shopping Cart Example
-
-
-
+
)
diff --git a/src/containers/CartContainer.js b/src/containers/CartContainer.js
index ac36ff7..3d45285 100644
--- a/src/containers/CartContainer.js
+++ b/src/containers/CartContainer.js
@@ -1,15 +1,18 @@
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
-import { checkout } from '../actions'
+import { checkout, increaseQuantity, decreaseQuantity, deleteFromCart } from '../actions'
import { getTotal, getCartProducts } from '../reducers'
import Cart from '../components/Cart'
-const CartContainer = ({ products, total, checkout }) => (
+const CartContainer = ({ products, total, checkout, increaseQuantity, decreaseQuantity, deleteFromCart }) => (
checkout(products)} />
+ onCheckoutClicked={() => checkout(products)}
+ onIncreaseQuantityClicked={increaseQuantity}
+ onDecreaseQuantityClicked={decreaseQuantity}
+ onDeleteFromCartClicked={deleteFromCart}/>
)
CartContainer.propTypes = {
@@ -20,7 +23,7 @@ CartContainer.propTypes = {
quantity: PropTypes.number.isRequired
})).isRequired,
total: PropTypes.string,
- checkout: PropTypes.func.isRequired
+ checkout: PropTypes.func.isRequired,
}
const mapStateToProps = (state) => ({
@@ -30,5 +33,5 @@ const mapStateToProps = (state) => ({
export default connect(
mapStateToProps,
- { checkout }
-)(CartContainer)
+ { checkout, increaseQuantity, decreaseQuantity, deleteFromCart }
+)(CartContainer)
\ No newline at end of file
diff --git a/src/containers/ProductsContainer.js b/src/containers/ProductsContainer.js
index 9108a97..e6518f2 100644
--- a/src/containers/ProductsContainer.js
+++ b/src/containers/ProductsContainer.js
@@ -12,7 +12,8 @@ const ProductsContainer = ({ products, addToCart }) => (
addToCart(product.id)} />
+ onAddToCartClicked={() => addToCart(product.id)}
+ />
)}
)
@@ -24,7 +25,7 @@ ProductsContainer.propTypes = {
price: PropTypes.number.isRequired,
inventory: PropTypes.number.isRequired
})).isRequired,
- addToCart: PropTypes.func.isRequired
+ addToCart: PropTypes.func.isRequired,
}
const mapStateToProps = state => ({
@@ -34,4 +35,4 @@ const mapStateToProps = state => ({
export default connect(
mapStateToProps,
{ addToCart }
-)(ProductsContainer)
+)(ProductsContainer)
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index d166264..91564c7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,21 +1,26 @@
import React from 'react'
import { render } from 'react-dom'
-import { createStore, applyMiddleware } from 'redux'
+import { createStore, applyMiddleware, compose } from 'redux'
import { Provider } from 'react-redux'
import { createLogger } from 'redux-logger'
import thunk from 'redux-thunk'
import reducer from './reducers'
import { getAllProducts } from './actions'
import App from './containers/App'
+import './styles/main.css';
const middleware = [ thunk ];
if (process.env.NODE_ENV !== 'production') {
middleware.push(createLogger());
}
+const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
+
const store = createStore(
reducer,
+ composeEnhancers(
applyMiddleware(...middleware)
+ )
)
store.dispatch(getAllProducts())
@@ -25,4 +30,4 @@ render(
,
document.getElementById('root')
-)
+)
\ No newline at end of file
diff --git a/src/reducers/cart.js b/src/reducers/cart.js
index 7d87e42..65fcec2 100644
--- a/src/reducers/cart.js
+++ b/src/reducers/cart.js
@@ -1,5 +1,8 @@
import {
ADD_TO_CART,
+ DELETE_FROM_CART,
+ INCREASE_QUANTITY,
+ DECREASE_QUANTITY,
CHECKOUT_REQUEST,
CHECKOUT_FAILURE
} from '../constants/ActionTypes'
@@ -16,6 +19,8 @@ const addedIds = (state = initialState.addedIds, action) => {
return state
}
return [ ...state, action.productId ]
+ case DELETE_FROM_CART:
+ return state.filter(id => id !== action.productId);
default:
return state
}
@@ -28,6 +33,18 @@ const quantityById = (state = initialState.quantityById, action) => {
return { ...state,
[productId]: (state[productId] || 0) + 1
}
+ case DELETE_FROM_CART:
+ return { ...state,
+ [action.productId]: state[action.productId] - 1
+ }
+ case INCREASE_QUANTITY:
+ return { ...state,
+ [action.productId]: state[action.productId] + 1
+ }
+ case DECREASE_QUANTITY:
+ return { ...state,
+ [action.productId]: state[action.productId] - 1
+ }
default:
return state
}
@@ -52,4 +69,4 @@ const cart = (state = initialState, action) => {
}
}
-export default cart
+export default cart
\ No newline at end of file
diff --git a/src/reducers/products.js b/src/reducers/products.js
index 01dba2c..09b55b0 100644
--- a/src/reducers/products.js
+++ b/src/reducers/products.js
@@ -1,5 +1,5 @@
import { combineReducers } from 'redux'
-import { RECEIVE_PRODUCTS, ADD_TO_CART } from '../constants/ActionTypes'
+import { RECEIVE_PRODUCTS, ADD_TO_CART, DELETE_FROM_CART, INCREASE_QUANTITY, DECREASE_QUANTITY } from '../constants/ActionTypes'
const products = (state, action) => {
switch (action.type) {
@@ -8,6 +8,21 @@ const products = (state, action) => {
...state,
inventory: state.inventory - 1
}
+ case DELETE_FROM_CART:
+ return {
+ ...state,
+ inventory: state.inventory + 1
+ };
+ case INCREASE_QUANTITY:
+ return {
+ ...state,
+ inventory: state.inventory - 1
+ }
+ case DECREASE_QUANTITY:
+ return {
+ ...state,
+ inventory: state.inventory + 1
+ };
default:
return state
}
@@ -53,4 +68,4 @@ export const getProduct = (state, id) =>
state.byId[id]
export const getVisibleProducts = state =>
- state.visibleIds.map(id => getProduct(state, id))
+ state.visibleIds.map(id => getProduct(state, id))
\ No newline at end of file
diff --git a/src/styles/main.css b/src/styles/main.css
new file mode 100644
index 0000000..9d61320
--- /dev/null
+++ b/src/styles/main.css
@@ -0,0 +1,28 @@
+@import url('https://fonts.googleapis.com/css?family=Lora');
+
+button:hover {
+ cursor: pointer;
+}
+
+button:disabled {
+ background-color: #dfdfdf;
+ cursor: pointer;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ display: flex;
+ text-align: center;
+ margin: 3rem;
+ font-family: 'Lora', serif;
+}
+
+.acme {
+ display: flex;
+ width: 25%;
+ margin: 1rem;
+ justify-content: center;
+}
\ No newline at end of file