"react shopping card"
Bootstrap 3.0.0 Snippet by evarevirus

<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <!------ Include the above in your HEAD tag ----------> <!DOCTYPE html><html class=''> <head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/paulkim/pen/oZLavq?depth=everything&order=popularity&page=70&q=react&show_forks=false" /> <style class="cp-pen-styles">ul { padding: 0; margin: 0; list-style: none; } img, media { max-width: 100%; } * { box-sizing: border-box; } body { margin: 0; } html { font-size: 16px; } body { font-family: Helvetica, Arial, sans-serif; color: #333; } a { text-decoration: none; -webkit-transition: 0.2s; transition: 0.2s; color: #555; } a:hover, a:active, a:focus { color: #27a; } h1, h2 { margin: 0; } .item-add-button, .cart-pay-button { font-size: 1.25rem; font-weight: bold; color: #fff; background-color: #2d2; display: block; width: 100%; max-width: 20rem; padding: 0.25rem 0.5rem; margin: 1.5rem auto 0; border: none; border-radius: 0.375rem; box-shadow: 0 0.375rem #2b2; -webkit-transition: 0.2s; transition: 0.2s; } .item-add-button:active, .cart-pay-button:active { -webkit-transform: translateY(0.375rem); transform: translateY(0.375rem); box-shadow: 0 0 #2b2; } .empty-cart, .cart-items { margin: 2rem 0; } .empty-cart { text-align: center; } .cart-item { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; margin: 1rem 0; } .cart-item-image-link, .cart-item-delete { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; } .cart-item-info { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; -ms-flex-item-align: stretch; align-self: stretch; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: distribute; justify-content: space-around; } .cart-item-delete { font-size: 1.5rem; margin: 0.5rem; } .cart-item-image { vertical-align: bottom; height: 5rem; padding: 0 0.8333rem 0 0.8333rem; } .cart-item-name-link, .cart-item-value { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; margin: 0.25rem 0.5rem; } .cart-item-name { font-size: 1.25rem; } .cart-item-value { font-size: 1rem; } .cart-item-price { margin-right: 1rem; } .cart-item-qty-select { margin-left: 0.5rem; } .cart-total { font-size: 1.25rem; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; } .cart-total-label { font-weight: bold; } .header { width: 100%; height: 4.375rem; position: fixed; top: 0; left: 0; background-color: #fff; background-color: rgba(255, 255, 255, 0.85); border-bottom: 0.0625rem solid #999; } .header-contents { max-width: 75rem; margin: 0 auto; display: -webkit-box; display: -ms-flexbox; display: flex; } .header-contents > a { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; } .back-button { margin: 1rem auto 1rem 1rem; padding: 0.625rem 0; } .cart-button { margin: 1rem 1rem 1rem auto; padding: 0.5rem; border: 0.125rem solid #46f; border-radius: 0.375rem; background-color: #68f; background-color: rgba(102, 136, 255, 0.85); color: #fff; font-weight: bold; } .cart-button:hover, .cart-button:active, .cart-button:focus { color: #fff; } .cart-button:hover, .cart-button:focus { border: 0.125rem solid #35f; background-color: #57f; background-color: rgba(85, 119, 255, 0.85); } .cart-button:active { border: 0.125rem solid #24f; background-color: #35f; background-color: rgba(51, 85, 255, 0.85); } .item { max-width: 25rem; margin: 0 auto; } .item-name, .item-price { padding: 0.25rem 0; } .item-name { font-size: 1.5rem; } .item-price { font-size: 1.25rem; font-weight: normal; } .item-add-form, .item-sold-out { margin: 2.5rem 0 0; } .item-add-form { text-align: center; } .item-qty-label { margin-right: 0.5rem; } .item-sold-out { color: #f00; } @media (min-width: 48rem) { .item { display: -webkit-box; display: -ms-flexbox; display: flex; max-width: 60rem; padding: 2rem 0 0; } .item-image { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; } .item-details { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 2rem 0 1rem 2rem; } } .no-match { text-align: center; margin: 2rem 0; } .item-qty, .cart-item-qty-select { font-size: 1rem; color: #333; width: 2.75rem; background-color: #fff; border: 0.0625rem solid #666; border-radius: 0.25rem; } .shop-item { margin: 2rem auto; max-width: 21.625rem; border: 0.0625rem solid #555; box-shadow: 0 0 0.625rem 0.25rem #555; } .shop-item-image, .shop-item-name, .shop-item-price { padding: 0.5rem 0.75rem; } .shop-item-image { margin: 0; } .shop-item-name { font-size: 1.5rem; } .shop-item-price { font-size: 1rem; font-weight: normal; padding-bottom: 1rem; } @media (min-width: 40rem) { .shop-item-list { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .shop-item { -webkit-box-flex: 0; -ms-flex: 0 0 43%; flex: 0 0 43%; margin: 2rem 3.5%; } } @media (min-width: 54rem) { .shop-item { -webkit-box-flex: 0; -ms-flex: 0 0 29%; flex: 0 0 29%; margin: 2rem 2.166%; } } .shopping-cart-app { max-width: 75rem; margin: 0 auto; } .main-header { font-size: 1.75rem; margin: 1rem 0; } .main { padding: 4.375rem 1rem 2.5rem; } </style></head><body> <div id='app'></div> <script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.2/react-redux.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/react-router/2.8.1/ReactRouter.min.js'></script> <script >'use strict'; // INITIAL STATE // -------------------- // --> initialState // // FUNCTIONS // -------------------- // --> getOptionsArray // // ACTIONS // -------------------- // --> addToCart // --> removeFromCart // --> updateCartItem // --> removeStockItem // // REDUCERS // -------------------- // ------> cartItem // ----> cart // ------> stockItem // ----> stock // --> reducers // // COMPONENTS // -------------------- // ------> Header // ----> HeaderContainer // ----------> ShopItem // --------> ShopItems // ------> ShopItemsContainer // ----> Shop // ----------> AddItem // --------> AddItemContainer // ------> Item // ----> ItemContainer // ----------> CartItem // --------> CartItems // --------> Total // --------> PayButton // ------> Cart // ----> CartContainer // ----> NoMatch // --> App var _React = React; var PropTypes = _React.PropTypes; var _ReactRedux = ReactRedux; var connect = _ReactRedux.connect; var Provider = _ReactRedux.Provider; var _ReactRouter = ReactRouter; var Router = _ReactRouter.Router; var Route = _ReactRouter.Route; var Link = _ReactRouter.Link; var IndexRoute = _ReactRouter.IndexRoute; var hashHistory = _ReactRouter.hashHistory; // INITIAL STATE var initialState = { cart: [], stock: [{ id: 0, name: 'TC 2017 LS', description: 'VC FlexLight Jersey with spot sublimated Team Canada 2017 logo, from our Team Canada Collection.', price: 34.95, count: 12, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/TC2017_LS_Mens_grande.jpg?v=1485541617' }, { id: 1, name: 'TC 2017 Shorts', description: 'VC FlexLight Shorts with spot sublimated Team Canada 2017 logo, from our Team Canada Collection.', price: 25.00, count: 7, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/TC2017_Shorts_White_grande.jpg?v=1485541580' }, { id: 2, name: 'TC 2016 Red SS', description: 'VC Ultimate\'s fully sublimated performance jersey, a replica of one of the two official dark jerseys of 2016 Team Canada teams! Sublimated jerseys are made with VC\'s FlexLight performance material – soft, lightweight and moisture wicking.', price: 74.00, count: 11, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/TC2016_red_SS_front_grande.jpg?v=1468602448' }, { id: 3, name: 'TC 2016 Dark SS', description: 'VC Ultimate\'s fully sublimated performance jersey, a replica of one of the two official dark jerseys of 2016 Team Canada teams! Sublimated jerseys are made with VC\'s FlexLight performance material – soft, lightweight and moisture wicking.', price: 35.99, count: 13, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/TC2016_SS_front_grande.jpg?v=1460557226' }, { id: 4, name: 'TC 2016 Light SS', description: 'Official replica of the 2016 Team Canada light playing jersey. VC spot sublimated jerseys are made with VC\'s FlexLight performance material – soft, lightweight and moisture wicking.', price: 35.99, count: 16, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/TCsample2_white_front_grande.jpg?v=1480111096' }, { id: 5, name: 'Goat Shorts', description: 'This just in... VC\'s NEW signature \'GOAT\' style athletic shorts now with pockets! Made with our FlexLight material.', price: 29.00, count: 4, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/MedGreyPockets_front_grande400x600_grande_888f95c1-0f4d-483f-938e-c686892a855a_grande.jpg?v=1454966549' }, { id: 6, name: 'Friction Gloves', description: 'This is the glove that started it all! Friction Gloves work great in every condition: dry, hot, rain, snow, you name it. They will help you maintain a firm grip on the disc whether you\'re catching or throwing. They eliminate slippage when the disc is wet, keep your hands warm in cold weather, and ease the sting of zippy throws. Whether your goal is to throw with more accuracy, catch tough discs, or just look fly, Frictions will help. Frictions are not bulky or stiff like other gloves. They are tight fitting and, after a while, you\'ll forget they\'re even on!', price: 33.95, count: 18, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/Gloves_grande.jpg?v=1446586810' }, { id: 7, name: 'TC 2017 Trucker', description: 'Premium meshback cotton front trucker hat. Made by FlexFit, with the official embroidered patch of Team Canada 2017! 47% Cotton / 25% Polyester / 28% Nylon, contrast trucker mesh back, matching plastic snap, hard buckram, matching undervisor. One size fits all', price: 15.00, count: 15, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/TC2017_Hat_Snapback_BlackWhite_grande.jpg?v=1485538793' }, { id: 8, name: 'VC Discraft Disc', description: 'Discraft 175 gram Ultrastar disc, hot stamped with the original VC logo.', price: 14.00, count: 19, img: 'https://cdn.shopify.com/s/files/1/0340/2849/products/Disc_VC_OG_grande_grande_cc0c1695-4247-426a-bd6c-5821da4e42da_grande.png?v=1485469652' }] }; // FUNCTIONS // getOptionsArray var getOptionsArray = function getOptionsArray(count) { var array = []; for (var i = 0; i < count; i++) {if (window.CP.shouldStopExecution(1)){break;} array.push(i + 1); } window.CP.exitedLoop(1); return array; }; // ACTIONS // addToCart var addToCart = function addToCart(id, count) { return { type: 'ADD_TO_CART', id: id, count: count }; }; // removeFromCart var removeFromCart = function removeFromCart(id) { return { type: 'REMOVE_FROM_CART', id: id }; }; // updateCartItem var updateCartItem = function updateCartItem(id, count) { return { type: 'UPDATE_CART_ITEM', id: id, count: count }; }; // removeStockItem var removeStockItem = function removeStockItem(id, count) { return { type: 'REMOVE_STOCK_ITEM', id: id, count: count }; }; // REDUCERS // cartItem var cartItem = function cartItem(state, action) { switch (action.type) { case 'ADD_TO_CART': return { id: action.id, count: action.count }; case 'REMOVE_FROM_CART': return state.id !== action.id; case 'UPDATE_CART_ITEM': if (state.id !== action.id) { return state; } return Object.assign({}, state, { count: action.count }); default: return state; } }; // cart var cart = function cart() { var state = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; var action = arguments[1]; switch (action.type) { case 'ADD_TO_CART': return [].concat(state, [cartItem(undefined, action)]); case 'REMOVE_FROM_CART': return state.filter(function (item) { return cartItem(item, action); }); case 'UPDATE_CART_ITEM': return state.map(function (item) { return cartItem(item, action); }); default: return state; } }; // stockItem var stockItem = function stockItem(state, action) { switch (action.type) { case 'REMOVE_STOCK_ITEM': if (state.id !== action.id) { return state; } return Object.assign({}, state, { count: state.count - action.count }); default: return state; } }; // stock var stock = function stock() { var state = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; var action = arguments[1]; switch (action.type) { case 'REMOVE_STOCK_ITEM': return state.map(function (item) { return stockItem(item, action); }); default: return state; } }; // reducers var reducers = Redux.combineReducers({ cart: cart, stock: stock }); // COMPONENTS // Header var Header = function Header(_ref) { var children = _ref.children; var cartItems = _ref.cartItems; var backButton = _ref.backButton; var cartButton = _ref.cartButton; var getBackButton = function getBackButton() { return React.createElement( Link, { to: '/', className: 'back-button' }, '< Back to shop' ); }; var getCartButton = function getCartButton() { return React.createElement( Link, { to: '/cart', className: 'cart-button' }, 'Cart (', cartItems, ')' ); }; return React.createElement( 'div', { className: 'shopping-cart-app' }, React.createElement( 'header', { className: 'header' }, React.createElement( 'div', { className: 'header-contents' }, backButton ? getBackButton() : '', cartButton ? getCartButton() : '' ) ), React.createElement( 'main', { className: 'main' }, children ) ); }; Header.PropTypes = { cartItems: PropTypes.number.isRequired, backButton: PropTypes.bool.isRequired, cartButton: PropTypes.bool.isRequired }; // HeaderContainer var showBackButton = function showBackButton(pathname) { return pathname !== '/' ? true : false; }; var showCartButton = function showCartButton(pathname) { return !pathname.includes('cart') ? true : false; }; var HeaderContainer = connect(function (state, ownProps) { return { children: ownProps.children, cartItems: state.cart.length, backButton: showBackButton(ownProps.location.pathname), cartButton: showCartButton(ownProps.location.pathname) }; })(Header); // ShopItem var ShopItem = function ShopItem(_ref2) { var id = _ref2.id; var name = _ref2.name; var price = _ref2.price; var img = _ref2.img; return React.createElement( 'li', { className: 'shop-item shop-item-' + id }, React.createElement( Link, { to: '/item/' + id }, React.createElement( 'div', { className: 'shop-item-container' }, React.createElement('img', { className: 'shop-item-image', src: img }), React.createElement( 'h1', { className: 'shop-item-name' }, name ), React.createElement( 'h2', { className: 'shop-item-price' }, '$', price.toFixed(2) ) ) ) ); }; ShopItem.PropTypes = { id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, price: PropTypes.number.isRequired, img: PropTypes.string.isRequired }; // ShopItems var ShopItems = function ShopItems(_ref3) { var items = _ref3.items; if (!items.length) { return React.createElement( 'p', { className: 'no-shop-items' }, 'No items' ); } return React.createElement( 'ul', { className: 'shop-item-list' }, items.map(function (item) { return React.createElement(ShopItem, { key: item.id, id: item.id, name: item.name, price: item.price, img: item.img }); }) ); }; ShopItems.PropTypes = { items: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, description: PropTypes.string.isRequired, price: PropTypes.number.isRequired, count: PropTypes.number.isRequired }).isRequired).isRequired }; // ShopItemsContainer var ShopItemsContainer = connect(function (state) { return { items: state.stock }; })(ShopItems); // Shop var Shop = function Shop() { return React.createElement( 'div', { className: 'shop' }, React.createElement( 'h1', { className: 'main-header shop-header' }, 'Shop' ), React.createElement(ShopItemsContainer, null) ); }; // AddItem var AddItem = function AddItem(_ref4) { var id = _ref4.id; var count = _ref4.count; var _onSubmit = _ref4.onSubmit; if (!count) { return React.createElement( 'p', { className: 'item-sold-out' }, 'Sold out!' ); } return React.createElement( 'form', { className: 'item-add-form', onSubmit: function onSubmit(e) { e.preventDefault(); _onSubmit(e, id); } }, React.createElement( 'span', { className: 'item-qty-label' }, 'Qty:' ), React.createElement( 'select', { className: 'item-qty' }, getOptionsArray(count).map(function (num) { return React.createElement( 'option', { key: num, value: num }, num ); }) ), React.createElement( 'button', { className: 'item-add-button', type: 'submit' }, 'Add to cart' ) ); }; AddItem.PropTypes = { count: PropTypes.number.isRequired, onClick: PropTypes.func.isRequired }; // AddItemContainer var addItemGetSelectedValue = function addItemGetSelectedValue(e) { return e.target.getElementsByClassName('item-qty')[0].value; }; var AddItemContainer = connect(function (state, ownProps) { return { id: ownProps.id, count: state.stock.find(function (item) { return item.id === ownProps.id; }).count, inCart: state.cart.some(function (item) { return item.id === ownProps.id; }) }; }, null, function (stateProps, dispatchProps, ownProps) { var _onSubmit2 = stateProps.inCart ? updateCartItem : addToCart; return Object.assign({}, ownProps, stateProps, dispatchProps, { onSubmit: function onSubmit(e, id) { dispatchProps.dispatch(_onSubmit2(id, addItemGetSelectedValue(e))); } }); })(AddItem); // Item var Item = function Item(_ref5) { var id = _ref5.id; var name = _ref5.name; var description = _ref5.description; var price = _ref5.price; var img = _ref5.img; return React.createElement( 'div', { className: 'item item-' + id }, React.createElement('img', { className: 'item-image', src: img }), React.createElement( 'div', { className: 'item-details' }, React.createElement( 'h1', { className: 'item-name' }, name ), React.createElement( 'h2', { className: 'item-price' }, '$', price.toFixed(2) ), React.createElement( 'p', { className: 'item-desc' }, description ), React.createElement(AddItemContainer, { id: id }) ) ); }; Item.PropTypes = { id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, description: PropTypes.string.isRequired, price: PropTypes.number.isRequired, img: PropTypes.string.isRequired }; // ItemContainer var ItemContainer = connect(function (state, ownProps) { return state.stock.find(function (item) { return String(item.id) === ownProps.params.id; }); })(Item); // CartItem var CartItem = function CartItem(_ref6) { var id = _ref6.id; var name = _ref6.name; var price = _ref6.price; var img = _ref6.img; var count = _ref6.count; var stockCount = _ref6.stockCount; var onQtyChange = _ref6.onQtyChange; var onRemoveClick = _ref6.onRemoveClick; return React.createElement( 'li', { className: 'cart-item cart-item-' + id }, React.createElement( Link, { to: '/item/' + id, className: 'cart-item-image-link' }, React.createElement('img', { className: 'cart-item-image', src: img }) ), React.createElement( 'div', { className: 'cart-item-info' }, React.createElement( Link, { to: '/item/' + id, className: 'cart-item-name-link' }, React.createElement( 'h1', { className: 'cart-item-name' }, name ) ), React.createElement( 'div', { className: 'cart-item-value' }, React.createElement( 'span', { className: 'cart-item-price' }, '$', price.toFixed(2) ), React.createElement( 'span', { className: 'cart-item-qty' }, 'Qty:', React.createElement( 'select', { className: 'cart-item-qty-select', value: count, onChange: function onChange(e) { return onQtyChange(e, id); } }, getOptionsArray(stockCount).map(function (num) { return React.createElement( 'option', { key: num, value: num }, num ); }) ) ) ) ), React.createElement( 'a', { href: '#', className: 'cart-item-delete', onClick: function onClick(e) { onRemoveClick(e, id); } }, '×' ) ); }; CartItem.PropTypes = { id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, price: PropTypes.number.isRequired, img: PropTypes.string.isRequired, count: PropTypes.number.isRequired, stockCount: PropTypes.number.isRequired, onQtyChange: PropTypes.func.isRequired, onRemoveClick: PropTypes.func.isRequired }; // CartItems var CartItems = function CartItems(_ref7) { var cart = _ref7.cart; var _onQtyChange = _ref7.onQtyChange; var _onRemoveClick = _ref7.onRemoveClick; if (!cart.length) { return React.createElement( 'p', { className: 'empty-cart' }, 'Cart is empty' ); } return React.createElement( 'ul', { className: 'cart-items' }, cart.map(function (item) { return React.createElement(CartItem, { key: item.id, id: item.id, name: item.name, price: item.price, img: item.img, count: item.count, stockCount: item.stockCount, onQtyChange: function onQtyChange(e, id) { return _onQtyChange(e, id); }, onRemoveClick: function onRemoveClick(e, id) { return _onRemoveClick(e, id); } }); }) ); }; CartItems.PropTypes = { cart: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, price: PropTypes.number.isRequired, img: PropTypes.string.isRequired, count: PropTypes.number.isRequired, stockCount: PropTypes.number.isRequired }).isRequired).isRequired, onQtyChange: PropTypes.func.isRequired, onRemoveClick: PropTypes.func.isRequired }; // Total var Total = function Total(_ref8) { var cart = _ref8.cart; return React.createElement( 'div', { className: 'cart-total' }, React.createElement( 'span', { className: 'cart-total-label' }, 'Total:' ), React.createElement( 'span', { className: 'cart-total-value' }, '$', cart.length ? cart.reduce(function (acc, item) { return acc + item.price * item.count; }, 0).toFixed(2) : Number(0).toFixed(2) ) ); }; Total.PropTypes = { cart: PropTypes.arrayOf(PropTypes.shape({ price: PropTypes.number.isRequired, count: PropTypes.number.isRequired }).isRequired).isRequired }; // PayButton var PayButton = function PayButton(_ref9) { var onPayClick = _ref9.onPayClick; return React.createElement( 'button', { type: 'button', className: 'cart-pay-button', onClick: function onClick() { return onPayClick(); } }, 'Pay now' ); }; PayButton.PropTypes = { onPayClick: PropTypes.func.isRequired }; // Cart var Cart = function Cart(_ref10) { var cart = _ref10.cart; var onQtyChange = _ref10.onQtyChange; var onRemoveClick = _ref10.onRemoveClick; var onPayClick = _ref10.onPayClick; return React.createElement( 'div', { className: 'cart' }, React.createElement( 'h1', { className: 'main-header cart-header' }, 'My Cart' ), React.createElement(CartItems, { cart: cart, onQtyChange: onQtyChange, onRemoveClick: onRemoveClick }), React.createElement(Total, { cart: cart }), React.createElement(PayButton, { onPayClick: onPayClick }) ); }; Cart.PropTypes = { cart: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, price: PropTypes.number.isRequired, img: PropTypes.string.isRequired, count: PropTypes.number.isRequired, stockCount: PropTypes.number.isRequired }).isRequired).isRequired, onQtyChange: PropTypes.func.isRequired, onRemoveClick: PropTypes.func.isRequired, onPayClick: PropTypes.func.isRequired }; // CartContainer var cartGetSelectedValue = function cartGetSelectedValue(e) { return e.target.value; }; var CartContainer = connect(function (state) { return { cart: state.cart.map(function (cartItem) { var item = state.stock.find(function (stockItem) { return cartItem.id === stockItem.id; }); return { id: cartItem.id, name: item.name, price: item.price, img: item.img, count: cartItem.count, stockCount: item.count }; }) }; }, function (_dispatch) { return { onQtyChange: function onQtyChange(e, id) { _dispatch(updateCartItem(id, cartGetSelectedValue(e))); }, onRemoveClick: function onRemoveClick(e, id) { e.preventDefault(); _dispatch(removeFromCart(id)); }, dispatch: function dispatch(reducer) { return _dispatch(reducer); } }; }, function (stateProps, dispatchProps, ownProps) { return Object.assign({}, ownProps, stateProps, dispatchProps, { onPayClick: function onPayClick() { return stateProps.cart.map(function (item) { dispatchProps.dispatch(removeStockItem(item.id, item.count)); dispatchProps.dispatch(removeFromCart(item.id)); }); } }); })(Cart); // NoMatch var NoMatch = function NoMatch() { return React.createElement( 'p', { className: 'no-match' }, 'Sorry, the page you are looking for does not exist. Click above to go back to the shop.' ); }; // App var App = function App() { return React.createElement( Router, { history: hashHistory }, React.createElement( Route, { path: '/', component: HeaderContainer }, React.createElement(IndexRoute, { component: Shop }), React.createElement(Route, { path: 'item/:id', component: ItemContainer }), React.createElement(Route, { path: 'cart', component: CartContainer }), React.createElement(Route, { path: '*', component: NoMatch }) ) ); }; var store = Redux.createStore(reducers, initialState); ReactDOM.render(React.createElement( Provider, { store: store }, React.createElement(App, null) ), document.getElementById('app')); //# sourceURL=pen.js </script> </body></html>

Related: See More


Questions / Comments: