<!DOCTYPE html>
<html>
<head>
<script data-require="angularjs@1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
</head>
<body ng-app="app">
<catalog></catalog>
<script src="script.js"></script>
</body>
</html>
function ApiService ($timeout) {
this.getProducts = () => {
// simulate async http request
// and server response latency
return $timeout(() => {
return [{
id: 1,
title: 'Fourrure d\'épiderme',
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit`,
img: 'http://lorempixel.com/200/200/sports/'
}, {
id: 2,
title: 'Steak pré-maché',
description: `Sed ut perspiciatis unde omnis iste natus error
sit voluptatem accusantium`,
img: 'http://lorempixel.com/200/200/people/'
}, {
id: 3,
title: 'Crème de jouvence',
description: 'At vero eos et accusamus et iusto odio dignissimos ducimus',
img: 'http://lorempixel.com/200/200/nature/'
}, {
id: 4,
title: 'Vase antique',
description: `On the other hand, we denounce with righteous indignation and`,
img: 'http://lorempixel.com/200/200/food/'
}];
}, 200);
};
this.addToCart = product => {
return $timeout(() => {
return {
status: 201,
statusText: 'Created',
data: null
};
}, 200);
};
this.removeFromCart = product => {
return $timeout(() => {
return {
status: 204,
statusText: 'No Content',
data: null
};
}, 200);
};
}
const CatalogComponent = {
template: `
<h1>Amazonie</h1>
<div>
<h2>Nos produits exclusivements uniques</h2>
<section style="display: flex; justify-content: space-between; padding: 0 20px;">
<product style="padding: 1%;"
ng-repeat="product in $catalog.products track by product.id"
data="product"
add-to-cart="$catalog.addToCart(product)">
</product>
</section>
<div ng-if="$catalog.fetching">Chargement ...</div>
<cart
data="$catalog.cart"
loading="$catalog.loading"
remove-from-cart="$catalog.removeFromCart(product)">
</cart>
</div>
`,
require: '^product',
controller: class CatalogCtrl {
constructor (ApiService, $log) { // ne pas oublier $inject sur un build minifié
this.ApiService = ApiService;
this.$log = $log;
this.products = [];
this.cart = [];
}
$onInit () {
this.fetching = true;
this.ApiService.getProducts()
.then((products) => {
this.products = this.products.concat(products);
})
.finally(() => this.fetching = false)
.catch((error) => this.$log.error(error));
}
addToCart (product) {
if (angular.isDefined(product.quantity) &&
angular.isNumber(product.quantity) &&
product.quantity > 0
) {
this.loading = true;
this.ApiService.addToCart(product)
.then(() => this.cart = this.cart.concat(
angular.copy(product)
))
.finally(() => {
product.quantity = undefined; // reset input quantity
this.loading = false;
})
.catch((error) => this.$log.error(error));
}
}
removeFromCart (product) {
if (this.cart.indexOf(product) > -1) {
this.loading = true;
this.ApiService.removeFromCart()
.then(() => {
let remaining = angular
.copy(this.cart)
.filter((remainingProduct) => {
return product.id !== remainingProduct.id;
});
this.cart = remaining;
})
.finally(() => this.loading = false)
.catch((error) => this.$log.error(error));
}
}
},
controllerAs: '$catalog',
transclude: false
};
const ProductComponent = {
bindings: {
data: '<',
addToCart: '&'
},
require: '^catalog',
template: `
<article style="height: 100%; display:flex; flex-direction: column; justify-content: space-around;">
<header style="display: block">
<img ng-src="{{ $product.data.img }}"
alt="{{ $prodct.data.id + '-product-image' }}"
style="display: block; max-width: 100%">
<h3>{{ $product.data.title }}</h3>
<p>{{ $product.data.description }}</p>
</header>
<section style="padding: 10px 0;">
<label for="{{ $product.data.id }}">Qté</label>
<input id="{{ $product.data.id }}"
type="number"
ng-model="$product.data.quantity"/>
</section>
<footer>
<button type="button"
ng-click="$product.addToCart({ product: $product.data})"
ng-disabled="!$product.data.quantity || $product.data.quantity == 0">
Ajouter au panier
</button>
</footer>
</article>
`,
transclude: false,
controllerAs: '$product'
};
const CartComponent = {
bindings: {
data: '<',
loading: '<',
removeFromCart: '&'
},
require: '^catalog',
template: `
<section>
<h4>Mon panier</h4>
<div style="color: #87a800" ng-repeat="product in $cart.data">
<strong>{{ product.title }}</strong> x {{ product.quantity }}
<button type="button"
ng-click="$cart.removeFromCart({ product })">
Supprimer
</button>
</div>
<div ng-if="$cart.data.length == 0 && !$cart.loading">Vide</div>
<div ng-if="$cart.loading">Chargement en cours...</div>
</section>
`,
transclude: false,
controllerAs: '$cart'
};
angular
.module('app', [])
.service('ApiService', ApiService)
.component('cart', CartComponent)
.component('product', ProductComponent)
.component('catalog', CatalogComponent);