From 71b5e13a736aba67cbe29fed77ec9703e20211ac Mon Sep 17 00:00:00 2001
From: Zoey Zheng <zoeyyandi@gmail.com>
Date: Sun, 11 Mar 2018 16:56:43 -0400
Subject: [PATCH] added remove product action, created add product form,
 created filter search bar

---
 src/App.js            | 123 +++++++++++++++++++++++++++++++-----------
 src/actions/index.js  |  24 ++++++++-
 src/index.js          |  15 +++---
 src/reducers/index.js |  44 +++++++++------
 4 files changed, 152 insertions(+), 54 deletions(-)

diff --git a/src/App.js b/src/App.js
index f54312b..b88928a 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,63 +1,124 @@
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import './App.css';
-import {connect} from 'react-redux';
-import {addProduct} from './actions/index';
+import { connect } from 'react-redux';
+import { addProduct, deleteProduct, updateSearchString } from './actions/index';
 import Chance from 'chance';
 
 export const chance = Chance();
 
-const Product = (props) => <div>{props.name}</div>;
-
-const DaBest = ({name}) => <h1>The Best: {name}</h1>;
+const Product = ({ product }) => (
+  <div>
+    <p>Name: {product.name}</p>
+    <p>Department: {product.department}</p>
+    <p>Price: {product.price}</p>
+    <p>Stock: {product.stock}</p>
+  </div>
+);
+
+const DaBest = ({ name }) => <h1>The Best: {name}</h1>;
+
+const DeleteButton = ({ deleteProduct, id }) => (
+  <button onClick={() => deleteProduct(id)}>Delete</button>
+);
+
+const Form = ({ handleSubmit }) => {
+  return (
+    <form onSubmit={handleSubmit}>
+      <label>
+        Name:<input name="Name" type="text" autoFocus />
+      </label>
+
+      <label>
+        Department:<input name="Department" type="text" />
+      </label>
+
+      <label>
+        Price:<input name="Price" type="text" />
+      </label>
+
+      <label>
+        Stock:<input name="Stock" type="text" />
+      </label>
+
+      <button>Add Product</button>
+    </form>
+  );
+};
 
-const AdderButton = ({add}) => <button onClick={() => add({name: 'Sofa'})}>Add Sofa</button>
+const SearchInput = ({ handleOnChange }) => (
+  <input
+    onChange={handleOnChange}
+    type="text"
+    autoFocus
+    placeholder="Search for a product"
+  />
+);
 
 class App extends Component {
-
-
-  constructor(props) {
-    super(props);
-  }
-
-  componentDidMount() {
-    this.props.add({
+  handleSubmit = event => {
+    event.preventDefault();
+    let product = {
       id: chance.guid(),
-      name: 'Table',
-      department: 'Furniture',
-      price: '300.00',
-      stock: 5,
-    });
-  }
+      name: event.target[0].value,
+      department: event.target[1].value,
+      price: event.target[2].value,
+      stock: event.target[3].value
+    };
+    this.props.add(product);
+    event.target[0].value = '';
+    event.target[1].value = '';
+    event.target[2].value = '';
+    event.target[3].value = '';
+  };
+
+  handleOnChange = event => {
+    this.props.updateSearchString(event.target.value);
+  };
 
   render() {
-    const {productList, add, whoIsTheBest} = this.props;
-    debugger;
+    const { searchString, productList, whoIsTheBest } = this.props;
     return (
       <div>
-        <DaBest name={whoIsTheBest}/>
-        {productList.map(product => <Product name={product.name} key={product.id}/>)}
-
-        <AdderButton {...this.props} />
+        <DaBest name={whoIsTheBest} />
+        <SearchInput handleOnChange={this.handleOnChange} />
+        {productList
+          .filter(product => {
+            let name = product.name.toLowerCase();
+            return name.includes(searchString.toLowerCase());
+          })
+          .map(product => (
+            <div key={product.id}>
+              <Product product={product} />
+              <DeleteButton
+                deleteProduct={this.props.deleteProduct}
+                id={product.id}
+              />
+            </div>
+          ))}
+        <Form handleSubmit={this.handleSubmit} />
       </div>
     );
   }
 }
 
-
 // React x REDUX STUFF
 
 const mapStateToProps = state => {
   return {
     productList: state.products.productList,
     whoIsTheBest: 'Della',
-
+    searchString: state.products.searchString,
     // an example of how to derive state in the mapStateToProps function - this is a specific 'subset' of the full list
-    lowStockProducts: state.products.productList.filter(prod => prod.stock && prod.stock < 4),
-  }
+    lowStockProducts: state.products.productList.filter(
+      prod => prod.stock && prod.stock < 4
+    )
+  };
 };
 
 const mapDispatchToProps = {
   add: addProduct,
+  deleteProduct: deleteProduct,
+  updateSearchString: updateSearchString
 };
 
 export default connect(mapStateToProps, mapDispatchToProps)(App);
diff --git a/src/actions/index.js b/src/actions/index.js
index 79e204e..bf3c0f7 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -1,5 +1,7 @@
 export const ACTION_TYPES = {
   addProduct: 'ADD_PRODUCTS',
+  deleteProduct: 'DELETE_PRODUCTS',
+  updateSearchString: 'UPDATE_SEARCH_STRING'
 };
 
 export function addProduct(product) {
@@ -7,7 +9,25 @@ export function addProduct(product) {
   return {
     type: ACTION_TYPES.addProduct,
     payload: {
-      product,
+      product
     }
-  }
+  };
+}
+
+export function deleteProduct(id) {
+  return {
+    type: ACTION_TYPES.deleteProduct,
+    payload: {
+      id
+    }
+  };
+}
+
+export function updateSearchString(searchInput) {
+  return {
+    type: ACTION_TYPES.updateSearchString,
+    payload: {
+      searchInput
+    }
+  };
 }
diff --git a/src/index.js b/src/index.js
index dfc54fd..ae6190d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,14 +6,17 @@ import { Provider } from 'react-redux';
 import App from '../src/App';
 import '../src/index.css';
 import reducer from './reducers';
-import registerServiceWorker from "../src/registerServiceWorker";
+import registerServiceWorker from '../src/registerServiceWorker';
 
-const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
+const store = createStore(
+  reducer,
+  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
+);
 
 ReactDOM.render(
-    <Provider store={ store }>
-        <App />
-    </Provider>,
-    document.getElementById('root')
+  <Provider store={store}>
+    <App />
+  </Provider>,
+  document.getElementById('root')
 );
 registerServiceWorker();
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 5cb12f1..3b1945a 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -1,27 +1,41 @@
-import {combineReducers} from 'redux';
-
-import {generateProducts} from '../utils/data';
-import {ACTION_TYPES} from '../actions';
+import { combineReducers } from 'redux';
 
+import { generateProducts } from '../utils/data';
+import { ACTION_TYPES } from '../actions';
 
 // you'll notice I set my initial state below on line 13 to equal this object! This is a common pattern
 const INITIAL_STATE = {
-    productList: generateProducts(10),
-    searchString: '' // hint for optional homework
+  productList: generateProducts(10),
+  searchString: '' // hint for optional homework
 };
 
-export const products = (state = INITIAL_STATE, {type, payload}) => {
-    switch (type) {
-        case ACTION_TYPES.addProduct:
-            // using object spread, I am saying - I want to return the old state, except change the productList property
-            return {...state, productList: state.productList.concat(payload.product)};
-    }
-    return state;
+export const products = (state = INITIAL_STATE, { type, payload }) => {
+  switch (type) {
+    case ACTION_TYPES.addProduct:
+      // using object spread, I am saying - I want to return the old state, except change the productList property
+      return {
+        ...state,
+        productList: [...state.productList, payload.product]
+      };
+    case ACTION_TYPES.deleteProduct:
+      return {
+        ...state,
+        productList: state.productList.filter(
+          product => product.id !== payload.id
+        )
+      };
+    case ACTION_TYPES.updateSearchString:
+      return {
+        ...state,
+        searchString: payload.searchInput
+      };
+    default:
+      return state;
+  }
 };
 
-
 // This is how you can combine many reducers into one large reducer:
 // https://redux.js.org/api-reference/combinereducers
 export default combineReducers({
-    products,
+  products
 });