<!DOCTYPE html>
<html ng-app="gemStore">
<head>
<link data-require="bootstrap-css@3.x" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<link rel="stylesheet" href="http://daneden.github.io/animate.css/animate.min.css">
<script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script data-require="ui-bootstrap@*" data-semver="0.10.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
<script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script data-require="bootstrap@*" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular-animate.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-i18n/1.2.15/angular-locale_pt-br.js"></script>
<!-- Style -->
<link rel="stylesheet" href="css/style.css" />
<link rel="stylesheet" href="css/animations.css" />
<!-- Angular Modules -->
<script src="js/app.js"></script>
<script src="js/products.js"></script>
</head>
<body ng-controller="StoreController as store">
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<a class="navbar-brand" href="#">AngularJS Store</a>
<div class="nav-collapse pull-left">
<ul class="nav">
<li>
<product-search></product-search>
</li>
</ul>
</div>
<div class="nav-collapse pull-right">
<ul class="nav">
<li>
<a href="#/cart" data-toggle="modal" data-target="#myModal"><i class="glyphicon glyphicon-shopping-cart"></i> <span class="badge ng-binding">{{ store.cart.length }}</span>
<ng-pluralize count="store.cart.length"
when="{'0': 'Nenhum produto',
'one': 'produto',
'other': 'produtos'}">
</ng-pluralize> carrinho </a>
</li>
</ul>
</div>
</nav>
<product-cart></product-cart>
<div class="container container-fluid view-slide-in">
<div class="list-group row">
<div class="list-group-item col-md-5repeat-animation hide-fade" ng-repeat="product in store.products | filter:searchProduct">
<product-gallery></product-gallery>
<product-title></product-title>
<product-tabs></product-tabs>
</div>
</div>
</div>
</body>
</html>
var app = angular.module('gemStore', ['ngAnimate','product-directives']);
app.controller('StoreController', ['$http',
function($http) {
var store = this;
store.products = [];
store.cart = [];
// GET JSON
$http.get('products.json')
.success(function(data) {
store.products = data;
})
.error(function() {
//
});
}
]);
.navbar {
-webkit-animation: bounceInDown 1s;
/* -webkit-animation-delay: .1s */;
}
.container {
-webkit-animation: fadeIn 1s;
-webkit-animation-delay: .1s;
}
.container {
margin-top: 100px;
}
.ng-invalid.ng-dirty {
border-color: red;
}
.ng-valid.ng-dirty {
border-color: green;
}
.thumbnail {
display: block;
width: 60px;
height: 60px;
overflow: hidden;
}
.thumbnail img {
height: 60px;
}
.img-wrap {
display: block;
width: 450px;
height: 300px;
overflow: hidden;
}
.img-wrap img {
width: 500px;
}
.list-group-item {
margin-right: 10px;
margin-bottom: 10px;
}
[
{
"code": "motog",
"name": "Motorola Moto G",
"description": "O Moto G é o novo smartphone da Motorola. Ele conta com a tecnologia Google e possui um dos melhores custos-benefício do mercado. Sua tela, com",
"shine": 8,
"price": 679.99,
"rarity": 7,
"color": "#CCC",
"faces": 14,
"images": [
"http://fs01.androidpit.info/userfiles/4155894/image/motog-press-1.jpg",
"http://s2.glbimg.com/E0udsksAphunUBCKU_DCBqiDBjA=/125x285:1069x906/494x325/s.glbimg.com/po/tt2/f/original/2013/11/13/moto_g_2.jpg",
"http://www.extra-imagens.com.br/Control/ArquivoExibir.aspx?IdArquivo=23828970"
],
"reviews": [
{
"stars": 5,
"body": "I love this gem!",
"author": "joe@example.org",
"createdOn": 1397490980837
},
{
"stars": 1,
"body": "This gem sucks.",
"author": "tim@example.org",
"createdOn": 1397490980837
}
]
},
{
"code": "samsungs5",
"name": "Samsung Galaxy S5",
"description": "O aparelho tem uma incrível tela Super AMOLED Full HD Gorila Glass de 5.1 polegadas , com resolução de 1920x1080 , com muito mais cores, brilho e ...",
"shine": 9,
"price": 1844.9,
"rarity": 6,
"color": "#EEE",
"faces": 12,
"images": [
"http://media.t3.com/img/resized/sa/xl_samsung%20galaxy%20s5.jpg",
"http://media.t3.com/img/resized/sa/xl_samsung-galaxy-s5-6.jpg"
],
"reviews": [
{
"stars": 3,
"body": "I think this gem was just OK, could honestly use more shine, IMO.",
"author": "JimmyDean@example.org",
"createdOn": 1397490980837
}
]
},
{
"code": "iphone5s",
"name": "Apple iPhone 5S",
"description": "Um smatphone muito além do seu tempo! O i - Phone 5s é um aparelho incrivelmente sofisticado deste sua estrutura de alumínio na elegância do metal ...",
"shine": 70,
"price": 2699.9,
"rarity": 2,
"color": "#000",
"faces": 6,
"images": [
"http://www.imore.com/sites/imore.com/files/styles/large/public/field/image/2013/08/gold_iphone_5s_mockup_imore_fixed.jpg?itok=A2IgjGCL",
"http://cdn2.mos.techradar.futurecdn.net///art/mobile_phones/iPhone/iPhone%205S/Press/iphone%205s%20screens-578-80.jpg",
"http://tecnoblog.net/wp-content/uploads/2012/09/apple-iphone-5-deitado.jpg",
"http://www.capadeiphone.com.br/product_images/uploaded_images/qual-a-melhor-capa-para-iphone-5.jpg"
],
"reviews": [
{
"stars": 1,
"body": "This gem is WAY too expensive for its rarity value.",
"author": "turtleguyy@example.org",
"createdOn": 1397490980837
},
{
"stars": 1,
"body": "BBW: High Shine != High Quality.",
"author": "LouisW407@example.org",
"createdOn": 1397490980837
},
{
"stars": 1,
"body": "Don't waste your rubles!",
"author": "nat@example.org",
"createdOn": 1397490980837
}
]
},
{
"code": "sonyxperiaz2",
"name": "Sony Xperia Z2",
"description": "Band O Sony Xperia Z2 chegou para mudar o conceito de tecnologia em smartphones. Tem display full HD de 5.2’’ e traz memória interna de 16 GB ...",
"shine": 70,
"price": 199.9,
"rarity": 2,
"color": "#000",
"faces": 6,
"images": [
"http://static1.purebreak.com.br/articles/9/36/99/@/21387-sony-xperia-z2-diapo-1.jpg",
"http://s2.glbimg.com/oSIKzKXFRW1JaUFJ7W7z5qIhXkw=/0x0:494x325/494x325/s.glbimg.com/po/tt2/f/original/2014/02/26/xperia_z2.jpg",
"http://phandroid.s3.amazonaws.com/wp-content/uploads/2014/02/sony-xperia-z2-3.jpg",
"http://imagens.canaltech.com.br/46720.64470-Sony-Xperia-Z2.jpg"
],
"reviews": [
{
"stars": 1,
"body": "This gem is WAY too expensive for its rarity value.",
"author": "turtleguyy@example.org",
"createdOn": 1397490980837
},
{
"stars": 1,
"body": "BBW: High Shine != High Quality.",
"author": "LouisW407@example.org",
"createdOn": 1397490980837
},
{
"stars": 1,
"body": "Don't waste your rubles!",
"author": "nat@example.org",
"createdOn": 1397490980837
}
]
},
{
"code": "lgg2",
"name": "LG G2",
"description": "Band O Sony Xperia Z2 chegou para mudar o conceito de tecnologia em smartphones. Tem display full HD de 5.2’’ e traz memória interna de 16 GB ...",
"shine": 70,
"price": 1231.9,
"rarity": 2,
"color": "#000",
"faces": 6,
"images": [
"http://mobilexpert.com.br/public/materias/7744/banner/grd.jpg",
"http://mobilesyrup.com/wp-content/uploads/2013/11/Photo-11-26-2013-4-36-50-PM.jpg"
],
"reviews": [
]
}
]
<!DOCTYPE html>
<h3>{{product.name}}
<em class="pull-right"> {{product.price | currency}} <a href="" ng-click="cart.addCart(product)" class="btn btn-success">
<i class="glyphicon glyphicon-shopping-cart"></i></a></em>
</h3>
<!DOCTYPE html>
<div ng-show="tab.isSet(1)">
<blockquote>{{product.description}}</blockquote>
</div>
<!DOCTYPE html>
<ul class="list-unstyled">
<li><strong>Shine</strong>: {{product.shine}}</li>
<li><strong>Faces</strong>: {{product.faces}}</li>
<li><strong>Rarity</strong>: {{product.rarity}}</li>
<li><strong>Color</strong>: {{product.color}}</li>
</ul>
<!DOCTYPE html>
<section>
<ul class="nav nav-tabs">
<li ng-class="{ active:tab.isSet(1) }">
<a href ng-click="tab.setTab(1)">Descrição</a>
</li>
<li ng-class="{ active:tab.isSet(2) }">
<a href ng-click="tab.setTab(2)">Detalhes</a>
</li>
<li ng-class="{ active:tab.isSet(3) }">
<a href ng-click="tab.setTab(3)">
<ng-pluralize count="product.reviews.length"
when="{'0': 'Nenhum Comentário',
'one': '(1) Comentário',
'other': '({}) Comenários'}">
</ng-pluralize>
</a>
</li>
</ul>
<br>
<!-- Description Tab's Content -->
<product-description ng-show="tab.isSet(1)"></product-description>
<!-- Spec Tab's Content -->
<product-spec ng-show="tab.isSet(2)"></product-spec>
<!-- Review Tab's Content -->
<product-review ng-show="tab.isSet(3)"></product-review>
</section>
<!DOCTYPE html>
<div ng-show="product.images.length">
<div class="img-wrap">
<img ng-src="{{product.images[gallery.current]}}" class="img-thumbnail product-image" />
</div>
<ul class="img-thumbnails clearfix">
<li class="small-image pull-left thumbnail" ng-repeat="image in product.images" >
<a href ng-click="gallery.setCurrent($index)"><img class="" ng-src="{{image}}" /></a>
</li>
</ul>
</div>
<!DOCTYPE html>
<!-- Product Reviews List -->
<ul>
<li ng-repeat="review in product.reviews">
<blockquote>
<strong>{{review.stars}} Estrelas</strong>
{{review.body}}
<cite class="clearfix">{{review.createdOn | date}}—{{review.author}}</cite>
</blockquote>
</li>
</ul>
<form name="reviewForm" ng-submit="reviewForm.$valid && reviewCtrl.addReview(product)" novalidate>
<!-- Live Preview -->
<blockquote ng-show="reviewForm.$valid">
<strong>{{reviewCtrl.review.stars}} Estrelas</strong>
{{reviewCtrl.review.body}}
<cite class="clearfix">{{Date.now()}}—{{reviewCtrl.review.author}}</cite>
</blockquote>
<!-- Review Form -->
<h4>Deixe um Comentário</h4>
<fieldset class="form-group">
<select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Estrela" required>
<option value="">Avalie o Produto</option>
</select>
</fieldset>
<fieldset class="form-group">
<textarea ng-model="reviewCtrl.review.body" class="form-control" placeholder="O que você achou deste produto..." title="Comentário" ng-minlength="10"></textarea>
</fieldset>
<fieldset class="form-group">
<input ng-model="reviewCtrl.review.author" type="email" class="form-control" placeholder="user@example.org" title="Email" required />
</fieldset>
<fieldset class="form-group">
<input type="submit" ng-disabled="reviewForm.$invalid" class="btn btn-success pull-right" value="Comentar" />
</fieldset>
</form>
var app = angular.module('product-directives', []);
// Directives
app.directive("productSearch", function() {
return {
restrict: 'E',
templateUrl: 'templates/product-search.html'
};
});
app.directive("productReview", function() {
return {
restrict: 'E',
templateUrl: 'templates/product-review.html',
controller: function() {
this.review = {};
this.addReview = function(product) {
this.review.createdOn = Date.now();
product.reviews.push(this.review);
this.review = {};
};
},
controllerAs: 'reviewCtrl'
};
});
app.directive("productGallery", function() {
return {
restrict: 'E',
templateUrl: 'templates/product-gallery.html',
controller: function() {
this.current = 0;
this.setCurrent = function(imageNumber) {
this.current = imageNumber || 0;
};
},
controllerAs: 'gallery'
};
});
// #TAB
app.directive('productTabs', function() {
return {
restrict: 'E',
templateUrl: 'templates/products.html',
controller: function() {
this.tab = 1;
this.isSet = function(checkTab) {
return this.tab === checkTab;
};
this.setTab = function(setTab) {
this.tab = setTab;
};
},
controllerAs: 'tab'
}
});
// Title
app.directive("productTitle", function() {
return {
restrict: 'E',
templateUrl: 'templates/product-title.html'
};
});
// Description
app.directive("productDescription", function() {
return {
restrict: 'E',
templateUrl: 'templates/product-description.html'
};
});
app.directive("productSpec", function() {
return {
restrict: 'E',
templateUrl: 'templates/product-spec.html'
};
});
// Specs
app.directive("productSpecs", function() {
return {
restrict: 'A',
templateUrl: 'templates/product-spec.html'
};
});
app.directive('productCart', function() {
return {
restrict: 'E',
templateUrl: 'templates/product-cart.html',
controller: function($scope) {
var cart = $scope.store.cart;
var items = cart.length;
this.addCart = function(item) {
var itemFound = false;
if (items > 0) {
cart.forEach(function(current) {
if (current.code == item.code) {
current.qtd += 1;
itemFound = true;
}
});
}
items += 1;
if (!itemFound) {
item.product = item;
item.qtd = 1;
item.completed = true;
cart.push(item);
}
};
this.removeCart = function(item){
cart.splice(item,1);
};
this.totalCart = function(){
var total = 0;
cart.forEach(function(item){
total += item.qtd * item.price;
});
return total;
}
},
controllerAs: 'cart'
};
});
<!doctype html>
<form name="formSearch" class="navbar-form navbar-left" role="search" novalidate>
<input type="text" class="form-control" placeholder="Pesquisar Produto..." ng-model="searchProduct" ng-minlength="2" required>
</form>
<!doctype html>
<nav class="navbar navbar-default" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
<li class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<div class="col-sm-3 col-md-3">
<form class="navbar-form" role="search">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search" name="q">
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
</div>
</div>
</form>
</div>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<!doctype html>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Carrinho de Compras</h4>
</div>
<div class="modal-body">
<table class="table table-hover">
<thead>
<tr>
<th>Produto</th>
<th>Qtd</th>
<th class="text-center">Preço</th>
<th class="text-center">Total</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in store.cart">
<td class="">
<div class="media">
{{product.name}}
<a class="thumbnail pull-left" href="#">
<img class="img-responsive " ng-src="{{ product.images[0] }}" alt="" />
</a>
</div>
</td>
<td class="">
<input type="number" class="form-control" ng-model="product.qtd" value="">
</td>
<td class="text-center"><strong>{{product.price | currency}}</strong>
</td>
<td class=" text-center"><strong>{{product.qtd * product.price | currency}}</strong>
</td>
<td class="">
<button type="button" class="btn btn-danger" ng-click="cart.removeCart(product)">
<span class="glyphicon glyphicon-trash"></span>
</button>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td>
<h5>Subtotal</h5>
</td>
<td class="text-right">
<h5><strong>{{cart.totalCart() | currency}}</strong></h5>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td>
<h5>Taxa de Entrega</h5>
</td>
<td class="text-right">
<h5><strong>{{ 9.99 | currency}}</strong></h5>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td>
<h3>Total</h3>
</td>
<td class="text-right">
<h3><strong>{{cart.totalCart() + 9.99 | currency}}</strong></h3>
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" data-dismiss="modal">Continuar Comprando</button>
<button type="button" class="btn btn-success">Finalizar Compra</button>
</div>
</div>
</div>
</div>
/* ng-view Animation */
.view-slide-in.ng-enter {
transition: all 1s ease;
-webkit-transition:all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
opacity:0.5;
position:relative;
opacity:0;
top:10px;
left:20px;
}
.view-slide-in.ng-enter {
opacity: 0;
}
.view-slide-in.ng-enter.ng-enter-active {
top:0;
left:0;
opacity: 1;
}
.view-slide-in.ng-leave.ng-leave-active{
top:5px;
left:5px;
opacity:1;
}
.view-slide-in.ng-leave{
top:0;
left:0;
opacity:0;
}
/* ng-repeat Animation */
.repeat-animation.ng-enter,
.repeat-animation.ng-leave,
.repeat-animation.ng-move {
-webkit-transition: all linear 1s;
-moz-transition: all linear 1s;
-o-transition: all linear 1s;
transition: all linear 1s;
position:relative;
left:5px;
}
.repeat-animation.ng-enter {
opacity: 0;
}
.repeat-animation.ng-enter.ng-enter-active {
opacity: 1;
}
.repeat-animation.ng-leave {
opacity: 1;
}
.repeat-animation.ng-leave.ng-leave-active {
opacity: 0;
}
.repeat-animation.ng-move {
left:2px;
opacity: 0.5;
}
.repeat-animation.ng-move.ng-move-active {
left:0;
opacity: 1;
}
/* ng-hide Animation */
.hide-fade.ng-hide-add, .hide-fade.ng-hide-remove {
-webkit-transition:all linear 1s;
-moz-transition:all linear 1s;
-o-transition:all linear 1s;
transition:all linear 1s;
display:block!important;
}
.hide-fade.ng-hide-add.ng-hide-add-active,
.hide-fade.ng-hide-remove {
opacity:0;
}
.hide-fade.ng-hide-add,
.hide-fade.ng-hide-remove.ng-hide-remove-active {
opacity:1;
}