aboutsummaryrefslogtreecommitdiff
path: root/src/reducers
diff options
context:
space:
mode:
authorMichael Foiani <mfoiani2019@communityschoolnaples.org>2018-07-25 19:38:43 -0400
committerMichael Foiani <mfoiani2019@communityschoolnaples.org>2018-07-25 19:38:43 -0400
commit3c09a0a91488e182f521b0cd39017cb5bc781a83 (patch)
treebc26d401b97f13169f3becdfe03bba6fd0f34353 /src/reducers
Initial commit. Added pwa starter kit to project for the application.
Diffstat (limited to 'src/reducers')
-rw-r--r--src/reducers/app.js51
-rw-r--r--src/reducers/counter.js30
-rw-r--r--src/reducers/shop.js199
3 files changed, 280 insertions, 0 deletions
diff --git a/src/reducers/app.js b/src/reducers/app.js
new file mode 100644
index 0000000..375e214
--- /dev/null
+++ b/src/reducers/app.js
@@ -0,0 +1,51 @@
+/**
+@license
+Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+*/
+
+import {
+ UPDATE_PAGE,
+ UPDATE_OFFLINE,
+ OPEN_SNACKBAR,
+ CLOSE_SNACKBAR,
+ UPDATE_DRAWER_STATE
+} from '../actions/app.js';
+
+const app = (state = {drawerOpened: false}, action) => {
+ switch (action.type) {
+ case UPDATE_PAGE:
+ return {
+ ...state,
+ page: action.page
+ };
+ case UPDATE_OFFLINE:
+ return {
+ ...state,
+ offline: action.offline
+ };
+ case UPDATE_DRAWER_STATE:
+ return {
+ ...state,
+ drawerOpened: action.opened
+ };
+ case OPEN_SNACKBAR:
+ return {
+ ...state,
+ snackbarOpened: true
+ };
+ case CLOSE_SNACKBAR:
+ return {
+ ...state,
+ snackbarOpened: false
+ };
+ default:
+ return state;
+ }
+};
+
+export default app;
diff --git a/src/reducers/counter.js b/src/reducers/counter.js
new file mode 100644
index 0000000..523a0f7
--- /dev/null
+++ b/src/reducers/counter.js
@@ -0,0 +1,30 @@
+/**
+@license
+Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+*/
+
+import { INCREMENT, DECREMENT } from '../actions/counter.js';
+
+const counter = (state = {clicks: 0, value: 0}, action) => {
+ switch (action.type) {
+ case INCREMENT:
+ return {
+ 'clicks': state.clicks + 1,
+ 'value': state.value + 1
+ };
+ case DECREMENT:
+ return {
+ 'clicks': state.clicks + 1,
+ 'value': state.value - 1
+ };
+ default:
+ return state;
+ }
+};
+
+export default counter;
diff --git a/src/reducers/shop.js b/src/reducers/shop.js
new file mode 100644
index 0000000..1005ca7
--- /dev/null
+++ b/src/reducers/shop.js
@@ -0,0 +1,199 @@
+/**
+@license
+Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+*/
+
+import {
+ GET_PRODUCTS,
+ ADD_TO_CART,
+ REMOVE_FROM_CART,
+ CHECKOUT_SUCCESS,
+ CHECKOUT_FAILURE
+} from '../actions/shop.js';
+import { createSelector } from 'reselect';
+
+const INITIAL_CART = {
+ addedIds: [],
+ quantityById: {}
+};
+
+const UPDATED_CART = {
+ addedIds: ['1'],
+ quantityById: {'1': 1}
+};
+
+const shop = (state = {products: {}, cart: INITIAL_CART}, action) => {
+ switch (action.type) {
+ case GET_PRODUCTS:
+ return {
+ ...state,
+ products: action.products
+ };
+ case ADD_TO_CART:
+ case REMOVE_FROM_CART:
+ case CHECKOUT_SUCCESS:
+ return {
+ ...state,
+ products: products(state.products, action),
+ cart: cart(state.cart, action),
+ error: ''
+ };
+ case CHECKOUT_FAILURE:
+ return {
+ ...state,
+ error: 'Checkout failed. Please try again'
+ };
+ default:
+ return state;
+ }
+};
+
+// Slice reducer: it only reduces the bit of the state it's concerned about.
+const products = (state, action) => {
+ switch (action.type) {
+ case ADD_TO_CART:
+ case REMOVE_FROM_CART:
+ const productId = action.productId;
+ return {
+ ...state,
+ [productId]: product(state[productId], action)
+ };
+ default:
+ return state;
+ }
+};
+
+const product = (state, action) => {
+ switch (action.type) {
+ case ADD_TO_CART:
+ return {
+ ...state,
+ inventory: state.inventory - 1
+ };
+ case REMOVE_FROM_CART:
+ return {
+ ...state,
+ inventory: state.inventory + 1
+ };
+ default:
+ return state;
+ }
+};
+
+const cart = (state = INITIAL_CART, action) => {
+ switch (action.type) {
+ case ADD_TO_CART:
+ case REMOVE_FROM_CART:
+ return {
+ addedIds: addedIds(state.addedIds, state.quantityById, action),
+ quantityById: quantityById(state.quantityById, action)
+ };
+ case CHECKOUT_SUCCESS:
+ return INITIAL_CART;
+ default:
+ return state;
+ }
+};
+
+const addedIds = (state = INITIAL_CART.addedIds, quantityById, action) => {
+ const productId = action.productId;
+ switch (action.type) {
+ case ADD_TO_CART:
+ if (state.indexOf(productId) !== -1) {
+ return state;
+ }
+ return [
+ ...state,
+ action.productId
+ ];
+ case REMOVE_FROM_CART:
+ // This is called before the state is updated, so if you have 1 item in the
+ // cart during the remove action, you'll have 0.
+ if (quantityById[productId] <= 1) {
+ // This removes all items in this array equal to productId.
+ return state.filter(e => e !== productId);
+ }
+ return state;
+ default:
+ return state;
+ }
+};
+
+const quantityById = (state = INITIAL_CART.quantityById, action) => {
+ const productId = action.productId;
+ switch (action.type) {
+ case ADD_TO_CART:
+ return {
+ ...state,
+ [productId]: (state[productId] || 0) + 1
+ };
+ case REMOVE_FROM_CART:
+ return {
+ ...state,
+ [productId]: (state[productId] || 0) - 1
+ };
+ default:
+ return state;
+ }
+};
+
+export default shop;
+
+// Per Redux best practices, the shop data in our store is structured
+// for efficiency (small size and fast updates).
+//
+// The _selectors_ below transform store data into specific forms that
+// are tailored for presentation. Putting this logic here keeps the
+// layers of our app loosely coupled and easier to maintain, since
+// views don't need to know about the store's internal data structures.
+//
+// We use a tiny library called `reselect` to create efficient
+// selectors. More info: https://github.com/reduxjs/reselect.
+
+const cartSelector = state => state.shop.cart;
+const productsSelector = state => state.shop.products;
+
+// Return a flattened array representation of the items in the cart
+export const cartItemsSelector = createSelector(
+ cartSelector,
+ productsSelector,
+ (cart, products) => {
+ const items = [];
+ for (let id of cart.addedIds) {
+ const item = products[id];
+ items.push({id: item.id, title: item.title, amount: cart.quantityById[id], price: item.price});
+ }
+ return items;
+ }
+);
+
+// Return the total cost of the items in the cart
+export const cartTotalSelector = createSelector(
+ cartSelector,
+ productsSelector,
+ (cart, products) => {
+ let total = 0;
+ for (let id of cart.addedIds) {
+ const item = products[id];
+ total += item.price * cart.quantityById[id];
+ }
+ return parseFloat(Math.round(total * 100) / 100).toFixed(2);
+ }
+);
+
+// Return the number of items in the cart
+export const cartQuantitySelector = createSelector(
+ cartSelector,
+ cart => {
+ let num = 0;
+ for (let id of cart.addedIds) {
+ num += cart.quantityById[id];
+ }
+ return num;
+ }
+);