diff --git a/package-lock.json b/package-lock.json index 14198e1323..ea4f8413e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6049,6 +6049,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -11116,6 +11124,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz", "integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==" }, + "react-redux": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", + "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + } + }, "react-scripts": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.0.tgz", @@ -11238,6 +11258,15 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -12929,6 +12958,11 @@ "util.promisify": "~1.0.0" } }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index 310bc22aff..b0e61a0927 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "node-sass": "^4.13.1", "react": "^16.13.0", "react-dom": "^16.13.0", - "react-scripts": "3.4.0" + "react-redux": "^7.2.0", + "react-scripts": "3.4.0", + "redux": "^4.0.5" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.js b/src/App.js index a6fc09d22b..679527417e 100755 --- a/src/App.js +++ b/src/App.js @@ -1,48 +1,57 @@ -import React from 'react'; - -import Header from './components/Header'; -import AddedFeatures from './components/AddedFeatures'; -import AdditionalFeatures from './components/AdditionalFeatures'; -import Total from './components/Total'; - -const App = () => { - const state = { - additionalPrice: 0, - car: { - price: 26395, - name: '2019 Ford Mustang', - image: - 'https://cdn.motor1.com/images/mgl/0AN2V/s1/2019-ford-mustang-bullitt.jpg', - features: [] - }, - additionalFeatures: [ - { id: 1, name: 'V-6 engine', price: 1500 }, - { id: 2, name: 'Racing detail package', price: 1500 }, - { id: 3, name: 'Premium sound system', price: 500 }, - { id: 4, name: 'Rear spoiler', price: 250 } - ] - }; +import React from "react"; + +import { connect } from "react-redux"; + +import { removeItem, addItem } from "./actions"; +import Header from "./components/Header"; +import AddedFeatures from "./components/AddedFeatures"; +import AdditionalFeatures from "./components/AdditionalFeatures"; +import Total from "./components/Total"; + +const App = props => { const removeFeature = item => { // dispatch an action here to remove an item + + + props.removeItem(item); }; const buyItem = item => { // dipsatch an action here to add an item + + props.addItem(item); }; + // const { state, removeFeature, buyItem } = props; + return (
-
- +
+
- - + +
); }; -export default App; + +const mapStateToProps = state => { + console.log("maps props", state); + return { + features: state.car.features, + car: state.car, + additionalFeatures: state.additionalFeatures, + additionalPrice: state.additionalPrice + }; +}; + +export default connect(mapStateToProps, { removeItem, addItem })(App); \ No newline at end of file diff --git a/src/actions/index.js b/src/actions/index.js new file mode 100644 index 0000000000..2e27c61847 --- /dev/null +++ b/src/actions/index.js @@ -0,0 +1,10 @@ +export const removeItem = item => { + return { type: "REMOVE_ITEM", payload: { id: item.id, price: item.price } }; +}; + +export const addItem = item => { + return { + type: "BUY_ITEM", + payload: { id: item.id, name: item.name, price: item.price } + }; +}; \ No newline at end of file diff --git a/src/components/AddedFeature.js b/src/components/AddedFeature.js index 92aff93bfc..eff8c95a59 100755 --- a/src/components/AddedFeature.js +++ b/src/components/AddedFeature.js @@ -4,8 +4,8 @@ const AddedFeature = props => { return (
  • {/* Add an onClick to run a function to remove a feature */} - - {props.feature.name} + + {props.feature.name} (-{props.feature.price})
  • ); }; diff --git a/src/components/AddedFeatures.js b/src/components/AddedFeatures.js index 620feb377b..03067d832f 100755 --- a/src/components/AddedFeatures.js +++ b/src/components/AddedFeatures.js @@ -9,7 +9,11 @@ const AddedFeatures = props => { {props.car.features.length ? (
      {props.car.features.map(item => ( - + ))}
    ) : ( diff --git a/src/components/AdditionalFeature.js b/src/components/AdditionalFeature.js index 5741b88d5b..7489ab51d4 100755 --- a/src/components/AdditionalFeature.js +++ b/src/components/AdditionalFeature.js @@ -4,7 +4,7 @@ const AdditionalFeature = props => { return (
  • {/* Add an onClick that will let you add a feature to your car */} - + {props.feature.name} (+{props.feature.price})
  • ); diff --git a/src/components/AdditionalFeatures.js b/src/components/AdditionalFeatures.js index 5e3cc2e150..a3eaffa08a 100755 --- a/src/components/AdditionalFeatures.js +++ b/src/components/AdditionalFeatures.js @@ -8,7 +8,10 @@ const AdditionalFeatures = props => { {props.additionalFeatures.length ? (
      {props.additionalFeatures.map(item => ( - + ))}
    ) : ( diff --git a/src/index.js b/src/index.js index a24f2c35f0..91c7c48361 100755 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,21 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; +import React from "react"; +import ReactDOM from "react-dom"; +import { createStore } from "redux"; +import { Provider } from "react-redux"; -import 'bulma/css/bulma.css'; -import './styles.scss'; +import mainReducer from "./reducers/mainReducer"; -const rootElement = document.getElementById('root'); -ReactDOM.render(, rootElement); +import App from "./App"; + +import "bulma/css/bulma.css"; +import "./styles.scss"; + +const store = createStore(mainReducer); + +const rootElement = document.getElementById("root"); +ReactDOM.render( + + + , + rootElement +); \ No newline at end of file diff --git a/src/reducers/mainReducer.js b/src/reducers/mainReducer.js new file mode 100644 index 0000000000..7c092a319d --- /dev/null +++ b/src/reducers/mainReducer.js @@ -0,0 +1,45 @@ +const initialState = { + additionalPrice: 0, + car: { + price: 26395, + name: "2019 Ford Mustang", + image: + "https://cdn.motor1.com/images/mgl/0AN2V/s1/2019-ford-mustang-bullitt.jpg", + features: [] + }, + additionalFeatures: [ + { id: 1, name: "V-6 engine", price: 1500 }, + { id: 2, name: "Racing detail package", price: 1500 }, + { id: 3, name: "Premium sound system", price: 500 }, + { id: 4, name: "Rear spoiler", price: 250 } + ] + }; + + const mainReducer = (state = initialState, action) => { + switch (action.type) { + case "BUY_ITEM": + return { + ...state, + car: { + ...state.car, + price: state.car.price + action.payload.price, + features: [...state.car.features, action.payload] + } + }; + case "REMOVE_ITEM": + return { + ...state, + car: { + ...state.car, + price: state.car.price - action.payload.price, + features: [...state.car.features.filter( + item => item.id !== action.payload.id + )] + } + }; + default: + return state; + } + }; + + export default mainReducer; \ No newline at end of file