diff options
-rw-r--r-- | src/actions/counter.js | 24 | ||||
-rw-r--r-- | src/actions/shop.js | 79 | ||||
-rw-r--r-- | src/components/my-view2.js | 72 | ||||
-rw-r--r-- | src/components/my-view3.js | 111 | ||||
-rw-r--r-- | src/reducers/counter.js | 30 | ||||
-rw-r--r-- | src/reducers/shop.js | 199 |
6 files changed, 0 insertions, 515 deletions
diff --git a/src/actions/counter.js b/src/actions/counter.js deleted file mode 100644 index 4ca5254..0000000 --- a/src/actions/counter.js +++ /dev/null @@ -1,24 +0,0 @@ -/** -@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 -*/ - -export const INCREMENT = 'INCREMENT'; -export const DECREMENT = 'DECREMENT'; - -export const increment = () => { - return { - type: INCREMENT - }; -}; - -export const decrement = () => { - return { - type: DECREMENT - }; -}; diff --git a/src/actions/shop.js b/src/actions/shop.js deleted file mode 100644 index 4542186..0000000 --- a/src/actions/shop.js +++ /dev/null @@ -1,79 +0,0 @@ -/** -@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 -*/ - -export const GET_PRODUCTS = 'GET_PRODUCTS'; -export const ADD_TO_CART = 'ADD_TO_CART'; -export const REMOVE_FROM_CART = 'REMOVE_FROM_CART'; -export const CHECKOUT_SUCCESS = 'CHECKOUT_SUCCESS'; -export const CHECKOUT_FAILURE = 'CHECKOUT_FAILURE'; - -const PRODUCT_LIST = [ - {"id": 1, "title": "Cabot Creamery Extra Sharp Cheddar Cheese", "price": 10.99, "inventory": 2}, - {"id": 2, "title": "Cowgirl Creamery Mt. Tam Cheese", "price": 29.99, "inventory": 10}, - {"id": 3, "title": "Tillamook Medium Cheddar Cheese", "price": 8.99, "inventory": 5}, - {"id": 4, "title": "Point Reyes Bay Blue Cheese", "price": 24.99, "inventory": 7}, - {"id": 5, "title": "Shepherd's Halloumi Cheese", "price": 11.99, "inventory": 3} -]; - -export const getAllProducts = () => (dispatch, getState) => { - // Here you would normally get the data from the server. We're simulating - // that by dispatching an async action (that you would dispatch when you - // succesfully got the data back) - - // You could reformat the data in the right format as well: - const products = PRODUCT_LIST.reduce((obj, product) => { - obj[product.id] = product - return obj - }, {}); - - dispatch({ - type: GET_PRODUCTS, - products: products - }); -}; - -export const checkout = (productId) => (dispatch) => { - // Here you could do things like credit card validation, etc. - // If that fails, dispatch CHECKOUT_FAILURE. We're simulating that - // by flipping a coin :) - const flip = Math.floor(Math.random() * 2); - if (flip === 0) { - dispatch({ - type: CHECKOUT_FAILURE - }); - } else { - dispatch({ - type: CHECKOUT_SUCCESS - }); - } -}; - -export const addToCart = (productId) => (dispatch, getState) =>{ - const state = getState(); - // Just because the UI thinks you can add this to the cart - // doesn't mean it's in the inventory (user could've fixed it); - if (state.shop.products[productId].inventory > 0) { - dispatch(addToCartUnsafe(productId)); - } -}; - -export const removeFromCart = (productId) => { - return { - type: REMOVE_FROM_CART, - productId - }; -}; - -export const addToCartUnsafe = (productId) => { - return { - type: ADD_TO_CART, - productId - }; -}; diff --git a/src/components/my-view2.js b/src/components/my-view2.js deleted file mode 100644 index 0dee7ee..0000000 --- a/src/components/my-view2.js +++ /dev/null @@ -1,72 +0,0 @@ -/** -@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 { html } from '@polymer/lit-element'; -import { PageViewElement } from './page-view-element.js'; -import { connect } from 'pwa-helpers/connect-mixin.js'; - -// This element is connected to the Redux store. -import { store } from '../store.js'; - -// These are the actions needed by this element. -import { increment, decrement } from '../actions/counter.js'; - -// We are lazy loading its reducer. -import counter from '../reducers/counter.js'; -store.addReducers({ - counter -}); - -// These are the elements needed by this element. -import './counter-element.js'; - -// These are the shared styles needed by this element. -import { SharedStyles } from './shared-styles.js'; - -class MyView2 extends connect(store)(PageViewElement) { - _render(props) { - return html` - ${SharedStyles} - <section> - <h2>Redux example: simple counter</h2> - <div class="circle">${props._value}</div> - <p>This page contains a reusable <code><counter-element></code>. The - element is not built in a Redux-y way (you can think of it as being a - third-party element you got from someone else), but this page is connected to the - Redux store. When the element updates its counter, this page updates the values - in the Redux store, and you can see the current value of the counter reflected in - the bubble above.</p> - <br><br> - </section> - <section> - <p> - <counter-element value="${props._value}" clicks="${props._clicks}" - on-counter-incremented="${() => store.dispatch(increment())}" - on-counter-decremented="${() => store.dispatch(decrement())}"> - </counter-element> - </p> - </section> - `; - } - - static get properties() { return { - // This is the data from the store. - _clicks: Number, - _value: Number - }} - - // This is called every time something is updated in the store. - _stateChanged(state) { - this._clicks = state.counter.clicks; - this._value = state.counter.value; - } -} - -window.customElements.define('my-view2', MyView2); diff --git a/src/components/my-view3.js b/src/components/my-view3.js deleted file mode 100644 index e226eaa..0000000 --- a/src/components/my-view3.js +++ /dev/null @@ -1,111 +0,0 @@ -/** -@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 { html } from '@polymer/lit-element'; -import { PageViewElement } from './page-view-element.js'; -import { connect } from 'pwa-helpers/connect-mixin.js'; - -// This element is connected to the Redux store. -import { store } from '../store.js'; - -// These are the actions needed by this element. -import { checkout } from '../actions/shop.js'; - -// We are lazy loading its reducer. -import shop, { cartQuantitySelector } from '../reducers/shop.js'; -store.addReducers({ - shop -}); - -// These are the elements needed by this element. -import './shop-products.js'; -import './shop-cart.js'; - -// These are the shared styles needed by this element. -import { SharedStyles } from './shared-styles.js'; -import { ButtonSharedStyles } from './button-shared-styles.js'; -import { addToCartIcon } from './my-icons.js'; - -class MyView3 extends connect(store)(PageViewElement) { - _render({_quantity, _error}) { - return html` - ${SharedStyles} - ${ButtonSharedStyles} - <style> - /* Add more specificity (.checkout) to workaround an issue in lit-element: - https://github.com/PolymerLabs/lit-element/issues/34 */ - button.checkout { - border: 2px solid var(--app-dark-text-color); - border-radius: 3px; - padding: 8px 16px; - } - button.checkout:hover { - border-color: var(--app-primary-color); - color: var(--app-primary-color); - } - .cart, .cart svg { - fill: var(--app-primary-color); - width: 64px; - height: 64px; - } - .circle.small { - margin-top: -72px; - width: 28px; - height: 28px; - font-size: 16px; - font-weight: bold; - line-height: 30px; - } - </style> - - <section> - <h2>Redux example: shopping cart</h2> - <div class="cart">${addToCartIcon}<div class="circle small">${_quantity}</div></div> - <p>This is a slightly more advanced Redux example, that simulates a - shopping cart: getting the products, adding/removing items to the - cart, and a checkout action, that can sometimes randomly fail (to - simulate where you would add failure handling). </p> - <p>This view, as well as its 2 child elements, <code><shop-products></code> and - <code><shop-cart></code> are connected to the Redux store.</p> - </section> - <section> - <h3>Products</h3> - <shop-products></shop-products> - - <br> - <h3>Your Cart</h3> - <shop-cart></shop-cart> - - <div>${_error}</div> - <br> - <p> - <button class="checkout" hidden="${_quantity == 0}" - on-click="${() => store.dispatch(checkout())}"> - Checkout - </button> - </p> - </section> - `; - } - - static get properties() { return { - // This is the data from the store. - _quantity: Number, - _error: String - }} - - // This is called every time something is updated in the store. - _stateChanged(state) { - this._quantity = cartQuantitySelector(state); - this._error = state.shop.error; - } -} - -window.customElements.define('my-view3', MyView3); diff --git a/src/reducers/counter.js b/src/reducers/counter.js deleted file mode 100644 index 523a0f7..0000000 --- a/src/reducers/counter.js +++ /dev/null @@ -1,30 +0,0 @@ -/** -@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 deleted file mode 100644 index 1005ca7..0000000 --- a/src/reducers/shop.js +++ /dev/null @@ -1,199 +0,0 @@ -/** -@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; - } -); |