Last active
January 10, 2020 20:01
-
-
Save luizjacomn/9a166e744ec4c318ee79c89b1621abf2 to your computer and use it in GitHub Desktop.
Protótipo de tela de carrinho de compras
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
final pc = Colors.blueGrey.shade900; | |
final sc = Colors.blueGrey.shade800; | |
final bc = Colors.blueGrey; | |
final wc = Colors.white; | |
final ac = Colors.amber; | |
final tc = Colors.transparent; | |
final gc = Colors.green; | |
final rc = Colors.red; | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Carrinho', | |
debugShowCheckedModeBanner: false, | |
home: MyHomePage(title: 'Carrinho'), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
MyHomePage({Key key, this.title}) : super(key: key); | |
final String title; | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
final cart = Cart(); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: pc, | |
appBar: AppBar( | |
backgroundColor: pc, | |
title: Row( | |
crossAxisAlignment: CrossAxisAlignment.end, | |
children: <Widget>[ | |
Icon(Icons.shopping_basket, color: ac), | |
SizedBox(width: 8), | |
Text( | |
widget.title, | |
style: TextStyle(color: ac), | |
), | |
], | |
), | |
actions: <Widget>[ | |
Visibility( | |
visible: cart.isNotEmpty, | |
child: IconButton( | |
icon: Icon( | |
Icons.clear_all, | |
), | |
onPressed: () { | |
setState(() { | |
cart.removeAll(); | |
}); | |
}, | |
), | |
), | |
], | |
), | |
body: cart.isEmpty | |
? Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
Icon( | |
Icons.sentiment_very_dissatisfied, | |
color: bc, | |
size: 72, | |
), | |
SizedBox(height: 16), | |
Text( | |
'Seu carrinho está vazio!'.toUpperCase(), | |
style: TextStyle(color: bc, fontSize: 16), | |
), | |
SizedBox(height: 4), | |
GestureDetector( | |
child: Text( | |
'Adicione itens agora mesmo'.toUpperCase(), | |
style: TextStyle(color: ac, fontSize: 12), | |
), | |
onTap: () { | |
setState(() { | |
cart.addAll(); | |
}); | |
}, | |
), | |
], | |
), | |
) | |
: Column( | |
children: <Widget>[ | |
Center( | |
child: Padding( | |
padding: | |
const EdgeInsets.symmetric(vertical: 16), | |
child: Container( | |
padding: const EdgeInsets.symmetric(vertical: 8), | |
color: gc, | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
Container( | |
padding: const EdgeInsets.symmetric( | |
horizontal: 8, | |
vertical: 4, | |
), | |
decoration: BoxDecoration( | |
color: wc, | |
borderRadius: BorderRadius.all( | |
Radius.circular(4), | |
), | |
), | |
child: Text( | |
'${cart.size}', | |
style: TextStyle(color: gc), | |
), | |
), | |
SizedBox(width: 8), | |
Text( | |
'ITENS NO CARRINHO', | |
style: TextStyle( | |
color: wc, | |
), | |
), | |
], | |
), | |
), | |
), | |
), | |
Expanded( | |
child: ListView.separated( | |
itemCount: cart.size, | |
separatorBuilder: (_, __) => Divider(height: 0), | |
itemBuilder: (context, index) { | |
final item = cart.itens[index]; | |
return Opacity( | |
opacity: item.disponivel ? 1 : 0.5, | |
child: item.disponivel | |
? Dismissible( | |
key: Key(UniqueKey().toString()), | |
onDismissed: (direction) { | |
if (direction == | |
DismissDirection.endToStart) { | |
Scaffold.of(context).showSnackBar( | |
SnackBar( | |
content: Text('${item.nome} removida'), | |
duration: Duration(seconds: 1), | |
), | |
); | |
} else { | |
Scaffold.of(context).showSnackBar( | |
SnackBar( | |
content: | |
Text('${item.nome} para edição'), | |
duration: Duration(seconds: 1), | |
), | |
); | |
} | |
setState(() { | |
cart.remove(item); | |
}); | |
}, | |
background: Container( | |
decoration: BoxDecoration(color: gc), | |
padding: EdgeInsets.all(5.0), | |
child: Row( | |
children: <Widget>[ | |
Padding( | |
padding: | |
const EdgeInsets.only(left: 20.0), | |
child: Text('EDITAR', | |
style: | |
TextStyle(color: Colors.white)), | |
), | |
], | |
), | |
), | |
secondaryBackground: Container( | |
decoration: BoxDecoration(color: rc), | |
padding: EdgeInsets.all(5.0), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.end, | |
children: <Widget>[ | |
Padding( | |
padding: | |
const EdgeInsets.only(right: 20.0), | |
child: Text('REMOVER', | |
style: | |
TextStyle(color: Colors.white)), | |
), | |
], | |
), | |
), | |
child: ItemTile(item: item), | |
) | |
: ItemTile(item: item), | |
); | |
}, | |
), | |
), | |
Padding( | |
padding: | |
const EdgeInsets.symmetric(horizontal: 8, vertical: 4), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
Text( | |
'ENTREGA', | |
style: TextStyle( | |
color: wc, | |
), | |
), | |
Text( | |
'R\$ ${cart.ship.toStringAsFixed(2)}', | |
style: TextStyle( | |
color: rc, | |
), | |
), | |
], | |
), | |
), | |
Padding( | |
padding: | |
const EdgeInsets.symmetric(horizontal: 8, vertical: 4), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
Text( | |
'DESCONTO (${cart.discountPercent})', | |
style: TextStyle( | |
color: wc, | |
), | |
), | |
Text( | |
'- R\$ ${cart.discountValue.toStringAsFixed(2)}', | |
style: TextStyle( | |
color: gc, | |
), | |
), | |
], | |
), | |
), | |
Padding( | |
padding: | |
const EdgeInsets.symmetric(horizontal: 8, vertical: 4), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
Text( | |
'TOTAL', | |
style: TextStyle( | |
color: ac, | |
), | |
), | |
Text( | |
'R\$ ${cart.totalCart.toStringAsFixed(2)}', | |
style: TextStyle( | |
color: ac, | |
), | |
), | |
], | |
), | |
), | |
Padding( | |
padding: | |
const EdgeInsets.symmetric(horizontal: 8, vertical: 16), | |
child: SizedBox( | |
width: double.infinity, | |
child: RaisedButton( | |
color: ac, | |
child: Text( | |
'FECHAR PEDIDO', | |
style: TextStyle( | |
color: pc, | |
), | |
), | |
onPressed: () {}, | |
), | |
), | |
), | |
], | |
), | |
); | |
} | |
} | |
class ItemTile extends StatelessWidget { | |
final Item item; | |
ItemTile({Key key, this.item}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 8), | |
child: Card( | |
color: sc, | |
child: ListTile( | |
leading: CircleAvatar( | |
backgroundColor: tc, | |
child: Image.network(item.img), | |
), | |
title: Padding( | |
padding: const EdgeInsets.only(bottom: 16), | |
child: Text( | |
item.nome, | |
style: TextStyle( | |
color: wc, | |
), | |
), | |
), | |
subtitle: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: <Widget>[ | |
Text( | |
'${item.qtd} x R\$ ${item.preco.toStringAsFixed(2)}', | |
style: TextStyle( | |
color: wc, | |
), | |
), | |
Text( | |
item.disponivel ? 'Disponível' : 'Esgotado', | |
style: TextStyle( | |
color: item.disponivel ? gc : rc, | |
), | |
), | |
], | |
), | |
trailing: Text( | |
'R\$ ${item.total.toStringAsFixed(2)}', | |
style: TextStyle( | |
color: ac, | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
class Cart { | |
List<Item> itens = []; | |
void remove(Item item) => itens.remove(item); | |
void removeAll() => itens.clear(); | |
void addAll() { | |
itens = [ | |
Item( | |
nome: 'Magnífica', | |
qtd: 1, | |
preco: 11, | |
img: | |
'https://www.ambev.com.br/conteudo/uploads/2019/03/magnifica_600ml.png', | |
estoque: 0, | |
), | |
Item( | |
nome: 'Lake Side', | |
qtd: 2, | |
preco: 12, | |
img: | |
'https://superprix.vteximg.com.br/arquivos/ids/177258-600-600/cerveja-lake-side.png?v=636595054012930000', | |
estoque: 3, | |
), | |
Item( | |
nome: 'Petra', | |
qtd: 3, | |
preco: 13, | |
img: | |
'https://superprix.vteximg.com.br/arquivos/ids/179107-600-600/Cerveja-Petra-Origem-Puro-Malte-355ml-Ln-815250.png?v=636969966571500000', | |
estoque: 3, | |
), | |
Item( | |
nome: 'Estrella Galicia', | |
qtd: 4, | |
preco: 14, | |
img: | |
'https://www.emporiofreicaneca.com.br/wp-content/uploads/2019/09/estrella-galicia-600ml-298x600.png', | |
estoque: 10, | |
), | |
]; | |
} | |
int get size => itens.length; | |
double get totalCart => itens | |
.map((item) => item.total) | |
.fold(0, (prev, current) => prev + current); | |
double get ship => 9.99; | |
double get discount => 0.1; | |
String get discountPercent => '${discount * 100}%'; | |
double get discountValue => totalCart * discount; | |
bool get isEmpty => itens.isEmpty; | |
bool get isNotEmpty => !isEmpty; | |
} | |
class Item { | |
String nome; | |
int qtd; | |
double preco; | |
String img; | |
int estoque; | |
Item({this.nome, this.qtd, this.preco, this.img, this.estoque}); | |
double get total => this.qtd * this.preco; | |
bool get disponivel => estoque >= qtd; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment