<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>