Skip to content

Instantly share code, notes, and snippets.

@shankarsridhar
Last active October 18, 2018 00:16
Show Gist options
  • Save shankarsridhar/91a9cae213a045a689c3e21bc67be5b7 to your computer and use it in GitHub Desktop.
Save shankarsridhar/91a9cae213a045a689c3e21bc67be5b7 to your computer and use it in GitHub Desktop.
bug-3
import Component from '@ember/component';
import { computed } from '@ember/object';
export default Component.extend({
tagName: 'li',
classNames: ['candy-item'],
isDiscountAllowed: computed.and('discount.{couponNotUsed,percent}', 'isOnSale'),
discountedPrice: computed('discount.percent', function() {
const price = this.get('price');
const discountPercent = this.get('discount.percent');
return price * (1 - discountPercent);
}),
init() {
this._super(...arguments);
this.set('discount', {
couponNotUsed: true,
percent: 0.1
});
},
actions: {
applyCoupon() {
const discountedPrice = this.get('discountedPrice');
this.set('isCouponApplied', true);
this.set('discount.couponNotUsed', false);
this.set('price', discountedPrice);
}
}
});
import Controller from '@ember/controller';
import { get, set, computed, observer } from '@ember/object';
export default Controller.extend({
totalSavings: computed('model.cartItems.@each.{originalPrice,price,qty}', function() {
console.log('totalSavings - Computed Property');
let _totalAmountSaved = 0;
const cartItems = get(this, 'model.cartItems');
cartItems.forEach(item => {
_totalAmountSaved += (item.originalPrice - item.price) * item.qty;
});
_totalAmountSaved = _totalAmountSaved.toFixed(2);
return _totalAmountSaved;
}),
totalAmount: computed('model.cartItems.@each.{qty,price}', function() {
const cartItems = get(this, 'model.cartItems');
let _totalAmount = 0;
cartItems.forEach(item => (_totalAmount += item.qty * item.price));
return _totalAmount;
}),
// DEMO[3]: BAD - listening to `model.cartItems.[]` vs `model.cartItems`
uniqueChocolatesCount: computed('model.cartItems', function() {
return this.get('model.cartItems.length');
}),
actions: {
addToCart(candyId) {
const cartItems = get(this, 'model.cartItems');
const targetCandy = cartItems.findBy('id', candyId);
if (targetCandy) {
const qty = get(targetCandy, 'qty');
set(targetCandy, 'qty', qty + 1);
} else {
const catalogue = get(this, 'model.candies');
const newCandyLineItem = catalogue.findBy('id', candyId);
set(newCandyLineItem, 'qty', 1);
cartItems.pushObject(newCandyLineItem);
}
},
resetCart() {
this.set('model.cartItems', []);
}
}
});
import Route from '@ember/routing/route';
export default Route.extend({
model() {
this._super(...arguments);
return {
candies: [
{
id: '1',
name: 'Ferrero',
url: 'http://i64.tinypic.com/mjn2h5.jpg',
price: 10,
originalPrice: 10,
isOnSale: true
},
{
id: '2',
name: 'Lindt',
url: 'http://i65.tinypic.com/14btfrr.png',
price: 8,
originalPrice: 8,
isOnSale: false
},
{
id: '3',
name: 'Hersheys',
url: 'http://i68.tinypic.com/2vtbi3m.jpg',
price: 8,
originalPrice: 8,
isOnSale: true
},
{
id: '4',
name: 'Kisses',
url: 'http://i64.tinypic.com/2vnm7bm.png',
price: 10,
originalPrice: 10,
isOnSale: false
}
],
cartItems: []
};
}
});
body {
font-family: Arial, Helvetica, sans-serif;
background-color: #f5f5f5; }
.app-name {
font-family: -apple-system, system-ui, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Fira Sans, Ubuntu, Oxygen, Oxygen Sans, Cantarell, Droid Sans, Apple Color Emoji, Segoe UI Emoji, Segoe UI Emoji, Segoe UI Symbol, Lucida Grande, Helvetica, Arial, sans-serif;
font-size: 20px;
line-height: 28px;
font-weight: 400;
color: #000000e6; }
.ember-application {
padding: 20px; }
.catalogue {
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px; }
.rounded-border {
border-radius: 100%; }
.candy-list {
padding: 0;
list-style: none;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px; }
.candy-list .candy-item {
background-color: #fff;
border: 1px solid #efefef;
padding: 10px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15), 0 4px 6px rgba(0, 0, 0, 0.2);
transition: box-shadow 83ms; }
.candy-list .candy-item:hover {
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15), 0 8px 12px rgba(0, 0, 0, 0.2); }
.candy-list .btn-coupon {
padding: 4px 12px;
cursor: pointer;
background-color: #ef7e37;
color: #fff;
text-transform: capitalize;
border-radius: 5px; }
.candy-list .btn-cart {
padding: 4px 12px;
cursor: pointer;
background-color: #0073b1;
font-weight: 800;
color: #fff;
text-transform: capitalize; }
.candy-list .candy-image {
width: 150px;
height: 150px;
border: 2px solid rgba(255, 255, 255, 0.4); }
.candy-list .candy-footer {
display: flex;
justify-content: space-between; }
.cart {
background-color: #fff;
min-height: 200px;
padding: 12px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15), 0 4px 6px rgba(0, 0, 0, 0.2); }
.cart tbody tr:last-child td {
padding-bottom: 40px; }
.cart td {
min-width: 100px; }
.cart .cart-title {
font-family: -apple-system, system-ui, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Fira Sans, Ubuntu, Oxygen, Oxygen Sans, Cantarell, Droid Sans, Apple Color Emoji, Segoe UI Emoji, Segoe UI Emoji, Segoe UI Symbol, Lucida Grande, Helvetica, Arial, sans-serif;
font-size: 18px;
line-height: 28px;
color: #000000e6;
margin-bottom: 20px;
text-align: left; }
th,
td {
text-align: left; }
.btn-reset-cart {
padding: 4px 12px;
cursor: pointer;
background-color: #900021;
color: #fff;
text-transform: capitalize; }
.flex {
display: flex; }
.text-center {
text-align: center; }
.text-left {
text-align: left; }
/*# sourceMappingURL=candyshop.css.map */
<section class="catalogue text-center">
<h1 class="app-name">Welcome to the Candy Shop</h1>
<ul class="candy-list">
{{#each model.candies as |candy|}}
{{candy-item
id=candy.id
name=candy.name
price=candy.price
url=candy.url
isOnSale=candy.isOnSale
addToCart=(action "addToCart") }}
{{/each}}
</ul>
</section>
<section class="cart">
<table>
<caption class="cart-title">Shopping Cart</caption>
<tbody>
<tr>
<th>Name</th>
<th>Price</th>
<th>Qty</th>
</tr>
{{#if model.cartItems.length }}
{{#each model.cartItems as |item|}}
<tr>
<td class="name">{{item.name}}</td>
<td class="price">{{item.price}}</td>
<td class="qty">{{item.qty}}</td>
</tr>
{{/each}}
{{else}}
<tr>
<td>cart is empty</td>
</tr>
{{/if}}
</tbody>
<tfoot>
<tr>
<td>Total Amount:</td>
<td>{{totalAmount}}</td>
</tr>
<tr>
<td>Total Savings:</td>
<td>{{totalSavings}}</td>
</tr>
<tr>
<td>Unique Chocolates Count:</td>
<td>{{uniqueChocolatesCount}}</td>
</tr>
</tfoot>
</table>
{{#if model.cartItems.length }}
<button {{action "resetCart"}} class="btn-reset-cart">Empty Cart</button>
{{/if}}
</section>
{{outlet}}
<section>
<header class="candy-name text-left">
{{name}}
{{#if isDiscountAllowed}}
<button class="btn-coupon" {{action "applyCoupon"}}>use coupon</button>
{{/if}}
</header>
<img src= {{url}} alt="candy image" class="rounded-border candy-image" />
<footer class="candy-footer">
{{#if isCouponApplied}}
<span class="price">${{discountedPrice}}</span>
{{else}}
<span class="price">${{price}}</span>
{{/if}}
<button {{action addToCart id}} class="btn-cart">add to cart</button>
</footer>
</section>
{
"version": "0.15.0",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js",
"ember": "3.2.2",
"ember-template-compiler": "3.2.2",
"ember-testing": "3.2.2"
},
"addons": {
"ember-data": "3.2.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment