Skip to content

Instantly share code, notes, and snippets.

@edward1986
Created April 27, 2021 07:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edward1986/404118cdccd8a19d2da2f475a888ed29 to your computer and use it in GitHub Desktop.
Save edward1986/404118cdccd8a19d2da2f475a888ed29 to your computer and use it in GitHub Desktop.
import 'package:ecom_app/screens/home_screen.dart';
import 'package:flutter/material.dart';
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/screens/checkout_screen.dart';
import 'package:ecom_app/screens/login_screen.dart';
import 'package:ecom_app/services/cart_service.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class CartScreen extends StatefulWidget {
final List<Product> cartItems;
CartScreen(this.cartItems);
@override
_CartScreenState createState() => _CartScreenState();
}
class _CartScreenState extends State<CartScreen> {
double _total;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
CartService _cartService = CartService();
@override
void initState() {
super.initState();
_getTotal();
}
_getTotal() {
_total = 0.0;
this.widget.cartItems.forEach((item) {
setState(() {
_total += (item.price - item.discount) * item.quantity;
});
});
}
void _checkOut(List<Product> cartItems) async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
int _userId = _prefs.getInt('userId');
if (_userId != null && _userId > 0) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CheckoutScreen(cartItems: cartItems)));
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoginScreen(cartItems: cartItems)));
}
}
_showSnackMessage(message) {
var snackBar = SnackBar(
content: message,
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: Text(''),
title: Text('Items in Cart'),
backgroundColor: Colors.redAccent,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
},
)
],
),
body: ListView.builder(
itemCount: this.widget.cartItems.length,
itemBuilder: (context, index) {
return Dismissible(
key: Key(this.widget.cartItems[index].id.toString()),
onDismissed: (param) {
_deleteCartItem(index, this.widget.cartItems[index].id);
},
background: Container(
color: Colors.redAccent,
),
child: Card(
child: ListTile(
leading: Image.network(this.widget.cartItems[index].photo),
title: Text(this.widget.cartItems[index].name,
style:
TextStyle(fontSize: 17, fontWeight: FontWeight.bold)),
subtitle: Row(
children: <Widget>[
Text(
'\$${this.widget.cartItems[index].price -
this.widget.cartItems[index].discount}',
style:
TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
),
Text(
' x ',
style:
TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
),
Text(
'${this.widget.cartItems[index].quantity}',
style:
TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
),
Text(
' = ',
style:
TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
),
Text(
'\$${(this.widget.cartItems[index].price - this.widget
.cartItems[index].discount) *
this.widget.cartItems[index].quantity}',
style:
TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
)
],
),
trailing: Column(
children: <Widget>[
InkWell(
onTap: () {
setState(() {
_total += this.widget.cartItems[index].price -
this.widget.cartItems[index].discount;
this.widget.cartItems[index].quantity++;
});
},
child: Icon(
Icons.arrow_drop_up,
size: 21,
),
),
Text('${this.widget.cartItems[index].quantity}',
style: TextStyle(
fontSize: 11, fontWeight: FontWeight.bold)),
InkWell(
onTap: () {
setState(() {
if (this.widget.cartItems[index].quantity > 1) {
_total -= this.widget.cartItems[index].price -
this.widget.cartItems[index].discount;
this.widget.cartItems[index].quantity--;
}
});
},
child: Icon(
Icons.arrow_drop_down,
size: 21,
),
)
],
),
),
),
);
},
),
bottomNavigationBar: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
'Total : \$$_total',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.redAccent),
),
),
Expanded(
child: RaisedButton(
color: Colors.redAccent,
onPressed: () {
_checkOut(this.widget.cartItems);
},
child: Text(
'Checkout',
style: TextStyle(color: Colors.white),
),
),
)
],
),
),
),
);
}
void _deleteCartItem(int index, int id) async {
setState(() {
this.widget.cartItems.removeAt(index);
});
var result = await _cartService.deleteCartItemById(id);
if (result > 0) {
_showSnackMessage(Text(
'One item deleted from cart',
style: TextStyle(color: Colors.red),
));
} else {
_showSnackMessage(Text(
'Cart items can not be deleted!',
style: TextStyle(color: Colors.yellow),
));
}
}
}
import 'package:ecom_app/models/product.dart';import 'package:ecom_app/repository/repository.dart';
class CartService {
Repository _repository;
CartService() {
_repository = Repository();
}
addToCart(Product product) async {
List<Map> items = await _repository.getLocalByCondition(
'carts', 'productId', product.id);
if (items.length > 0) {
product.quantity = items.first['productQuantity'] + 1;
return await _repository.updateLocal(
'carts', 'productId', product.toMap());
}
product.quantity = 1;
return await _repository.saveLocal('carts', product.toMap());
}
getCartItems() async {
return await _repository.getAllLocal('carts');
}
deleteCartItemById(int id) async {
return await _repository.deleteLocalById('carts', id);
}
makeTheCartEmpty() async {
return await _repository.deleteLocal('carts');
}
}
class Category {
int id;
String name;
String icon;
}
import 'package:ecom_app/repository/repository.dart';
class CategoryService {
Repository _repository;
CategoryService(){
_repository = Repository();
}
getCategories() async {
return await _repository.httpGet('categories');
}
}
import 'dart:convert';
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/models/shipping.dart';
import 'package:ecom_app/screens/payment_screen.dart';
import 'package:ecom_app/services/shipping_service.dart';
import 'package:flutter/material.dart';
class CheckoutScreen extends StatefulWidget {
final List<Product> cartItems;
CheckoutScreen({this.cartItems});
@override
_CheckoutScreenState createState() => _CheckoutScreenState();
}
class _CheckoutScreenState extends State<CheckoutScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final name = TextEditingController();
final email = TextEditingController();
final address = TextEditingController();
_showSnackMessage(message) {
var snackBar = SnackBar(
content: message,
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Checkout'),
backgroundColor: Colors.redAccent,
leading: Text(''),
elevation: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
body: Padding(
padding: const EdgeInsets.only(top: 0.0),
child: ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 28.0, right: 28.0, bottom: 14.0),
child: Text('Shipping Address',
style:
TextStyle(fontSize: 28.0, fontWeight: FontWeight.bold)),
),
Divider(
height: 5.0,
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: name,
decoration: InputDecoration(
hintText: 'Enter your name', labelText: 'Enter your name'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
keyboardType: TextInputType.emailAddress,
controller: email,
decoration: InputDecoration(
hintText: 'Enter your email address',
labelText: 'Enter your email address'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: address,
maxLines: 3,
decoration:
InputDecoration(hintText: 'Address', labelText: 'Address'),
),
),
Column(
children: <Widget>[
ButtonTheme(
minWidth: 320.0,
height: 45.0,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7.0)),
color: Colors.redAccent,
onPressed: () {
var shipping = Shipping();
shipping.name = name.text;
shipping.email = email.text;
shipping.address = address.text;
_shipping(context, shipping);
},
child: Text('Continue to Payment',
style: TextStyle(color: Colors.white)),
),
),
],
),
],
),
),
);
}
void _shipping(BuildContext context, Shipping shipping) async {
var _shippingService = ShippingService();
var shippingData = await _shippingService.addShipping(shipping);
print("resuly"+shippingData.body);
var result = jsonDecode(shippingData.body);
if (result['result'] == true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PaymentScreen(
cartItems: this.widget.cartItems,
)));
} else {
_showSnackMessage(
Text('Failed to add shipping', style: TextStyle(color: Colors.red),));
}
}
}
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseConnection {
initDatabase() async {
var directory = await getApplicationDocumentsDirectory();
var path = join(directory.path, 'db_ecom_1');
var database =
await openDatabase(path, version: 1, onCreate: _onCreatingDatabase);
return database;
}
_onCreatingDatabase(Database db, int version) async {
await db.execute(
"CREATE TABLE carts(id INTEGER PRIMARY KEY, productId INTEGER, productName TEXT, productPhoto TEXT,detail TEXT, productPrice INTEGER, productDiscount INTEGER, productQuantity INTEGER)");
}
}
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/screens/product_detail.dart';
import 'package:flutter/material.dart';
class HomeHotProduct extends StatefulWidget {
final Product product;
HomeHotProduct(this.product);
@override
_HomeHotProductState createState() => _HomeHotProductState();
}
class _HomeHotProductState extends State<HomeHotProduct> {
@override
Widget build(BuildContext context) {
return Container(
width: 190.0,
height: 260.0,
child: InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => ProductDetail(this.widget.product)));
},
child: Card(
child: Column(
children: <Widget>[
Text(this.widget.product.name),
Image.network(widget.product.photo, width: 190.0, height: 160.0,),
Row(children: <Widget>[
Text('Price: ${this.widget.product.price}'),
Text('Discount: ${this.widget.product.discount}'),
],)
],
),
),
),
);
}
}
import 'package:ecom_app/models/product.dart';
import 'package:flutter/material.dart';
import 'home_hot_product.dart';
class HomeHotProducts extends StatefulWidget {
final List<Product> productList;
HomeHotProducts({this.productList});
@override
_HomeHotProductsState createState() => _HomeHotProductsState();
}
class _HomeHotProductsState extends State<HomeHotProducts> {
@override
Widget build(BuildContext context) {
return Container(
height: 205,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: this.widget.productList.length,
itemBuilder: (context, index) {
return
HomeHotProduct(this.widget.productList[index]);
},
),
);
}
}
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/screens/product_detail.dart';
import 'package:flutter/material.dart';
class HomeNewArrivalProduct extends StatefulWidget {
final Product product;
HomeNewArrivalProduct(this.product);
@override
_HomeNewArrivalProductState createState() => _HomeNewArrivalProductState();
}
class _HomeNewArrivalProductState extends State<HomeNewArrivalProduct> {
@override
Widget build(BuildContext context) {
return Container(
width: 190.0,
height: 260.0,
child: InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => ProductDetail(this.widget.product)));
},
child: Card(
child: Column(
children: <Widget>[
Text(this.widget.product.name),
Image.network(widget.product.photo, width: 190.0, height: 160.0,),
Row(children: <Widget>[
Text('Price: ${this.widget.product.price}'),
Text('Discount: ${this.widget.product.discount}'),
],)
],
),
),
),
);
}
}
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/widgets/home_new_arrival_product.dart';
import 'package:flutter/material.dart';
class HomeNewArrivalProducts extends StatefulWidget {
final List<Product> productList;
HomeNewArrivalProducts({this.productList});
@override
_HomeNewArrivalProductsState createState() => _HomeNewArrivalProductsState();
}
class _HomeNewArrivalProductsState extends State<HomeNewArrivalProducts> {
@override
Widget build(BuildContext context) {
return Container(
height: 205,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: this.widget.productList.length,
itemBuilder: (context, index) {
return
HomeNewArrivalProduct(this.widget.productList[index]);
},
),
);
}
}
import 'package:ecom_app/models/category.dart';
import 'package:flutter/material.dart';
import 'home_product_category.dart';
class HomeProductCategories extends StatefulWidget {
final List<Category> categoryList;
HomeProductCategories({this.categoryList});
@override
_HomeProductCategoriesState createState() => _HomeProductCategoriesState();
}
class _HomeProductCategoriesState extends State<HomeProductCategories> {
@override
Widget build(BuildContext context) {
return Container(
height: 205,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: this.widget.categoryList.length,
itemBuilder: (context, index) {
return HomeProductCategory(this.widget.categoryList[index].icon,
this.widget.categoryList[index].name,
this.widget.categoryList[index].id);
},
),
);
}
}
import 'package:ecom_app/screens/products_by_category_screen.dart';import 'package:flutter/material.dart';
class HomeProductCategory extends StatefulWidget {
final int categoryId;
final String categoryIcon;
final String categoryName;
HomeProductCategory(this.categoryIcon, this.categoryName, this.categoryId);
@override
_HomeProductCategoryState createState() => _HomeProductCategoryState();
}
class _HomeProductCategoryState extends State<HomeProductCategory> {
@override
Widget build(BuildContext context) {
return Container(
width: 140.0,
height: 190.0,
child: InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) =>
ProductsByCategoryScreen(categoryName: widget.categoryName,
categoryId: widget.categoryId)));
},
child: Card(
child: Column(
children: <Widget>[
Image.network(widget.categoryIcon, width: 190.0, height: 160.0,),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(widget.categoryName),
),
],
),
),
),
);
}
}
import 'dart:convert';
import 'package:ecom_app/models/category.dart';
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/screens/cart_screen.dart';
import 'package:ecom_app/services/cart_service.dart';
import 'package:ecom_app/services/category_service.dart';
import 'package:ecom_app/services/product_service.dart';
import 'package:ecom_app/services/slider_service.dart';
import 'package:ecom_app/widgets/carousel_slider.dart';
import 'package:ecom_app/widgets/home_hot_products.dart';
import 'package:ecom_app/widgets/home_new_arrival_products.dart';
import 'package:ecom_app/widgets/home_product_categories.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
SliderService _sliderService = SliderService();
CategoryService _categoryService = CategoryService();
ProductService _productService = ProductService();
List<Category> _categoryList = List<Category>();
List<Product> _productList = List<Product>();
List<Product> _newArrivalproductList = List<Product>();
CartService _cartService = CartService();
List<Product> _cartItems;
var items = [];
@override
void initState() {
super.initState();
_getAllSliders();
_getAllCategories();
_getAllHotProducts();
_getAllNewArrivalProducts();
_getCartItems();
_setSharedPrefs();
}
_setSharedPrefs() async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.setInt('userId', 0);
_prefs.setString('userName', '');
_prefs.setString('userEmail', '');
}
_getCartItems() async {
_cartItems = List<Product>();
var cartItems = await _cartService.getCartItems();
cartItems.forEach((data) {
var product = Product();
product.id = data['productId'];
product.name = data['productName'];
product.photo = data['productPhoto'];
product.price = data['productPrice'];
product.discount = data['productDiscount'];
product.detail = data['detail'] ?? 'No detail';
product.quantity = data['productQuantity'];
setState(() {
_cartItems.add(product);
});
});
}
_getAllSliders() async {
var sliders = await _sliderService.getSliders();
var result = json.decode(sliders.body);
result['data'].forEach((data) {
setState(() {
items.add(NetworkImage(data['image_url']));
});
});
}
_getAllCategories() async {
var categories = await _categoryService.getCategories();
var result = json.decode(categories.body);
result['data'].forEach((data) {
var model = Category();
model.id = data['id'];
model.name = data['categoryName'];
model.icon = data['categoryIcon'];
setState(() {
_categoryList.add(model);
});
});
}
_getAllHotProducts() async {
var hotProducts = await _productService.getHotProducts();
var result = json.decode(hotProducts.body);
result['data'].forEach((data) {
var model = Product();
model.id = data['id'];
model.name = data['name'];
model.photo = data['photo'];
model.price = data['price'];
model.discount = data['discount'];
model.detail = data['detail'];
setState(() {
_productList.add(model);
});
});
}
_getAllNewArrivalProducts() async {
var newArrivalProducts = await _productService.getNewArrivalProducts();
var result = json.decode(newArrivalProducts.body);
result['data'].forEach((data) {
var model = Product();
model.id = data['id'];
model.name = data['name'];
model.photo = data['photo'];
model.price = data['price'];
model.discount = data['discount'];
model.detail = data['detail'];
setState(() {
_newArrivalproductList.add(model);
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('eComm App'),
backgroundColor: Colors.redAccent,
actions: <Widget>[
InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => CartScreen(_cartItems)));
},
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 150,
width: 30,
child: Stack(
children: <Widget>[
IconButton(
iconSize: 30,
icon: Icon(Icons.shopping_cart, color: Colors.white,),
onPressed: () {
},
),
Positioned(
child: Stack(
children: <Widget>[
Icon(Icons.brightness_1, size: 25, color: Colors
.black),
Positioned(
top: 4.0,
right: 8.0,
child: Center(
child: Text(_cartItems.length.toString())),
),
],
),
),
],
),
),
),
)
],
),
body: Container(
child: ListView(
children: <Widget>[
carouselSlider(items),
Padding(
padding: EdgeInsets.all(10.0),
child: Text('Product Categories'),
),
HomeProductCategories(
categoryList: _categoryList,
),
Padding(
padding: EdgeInsets.all(10.0),
child: Text('Hot Products'),
),
HomeHotProducts(
productList: _productList,
),
Padding(
padding: EdgeInsets.all(10.0),
child: Text('New Arrival Products'),
),
HomeNewArrivalProducts(
productList: _newArrivalproductList,
)
],
)),
);
}
}
import 'dart:convert';
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/models/user.dart';
import 'package:ecom_app/screens/registration_screen.dart';
import 'package:ecom_app/services/user_service.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'checkout_screen.dart';
class LoginScreen extends StatefulWidget {
final List<Product> cartItems;
LoginScreen({this.cartItems});
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final email = TextEditingController();
final password = TextEditingController();
_login(BuildContext context, User user) async {
var _userService = UserService();
var registeredUser = await _userService.login(user);
var result = json.decode(registeredUser.body);
if (result['result'] == true) {
SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.setInt('userId', result['user']['id']);
_prefs.setString('userName', result['user']['name']);
_prefs.setString('userEmail', result['user']['email']);
Navigator.push(
context, MaterialPageRoute(builder: (context) =>
CheckoutScreen(cartItems: this.widget.cartItems,)));
} else {
_showSnackMessage(
Text('Failed to login!', style: TextStyle(color: Colors.red),));
}
}
_showSnackMessage(message) {
var snackBar = SnackBar(
content: message,
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.close,
color: Colors.red,
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
body: Padding(
padding: const EdgeInsets.only(top: 120),
child: ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 48.0, top: 14.0, right: 48.0, bottom: 14.0),
child: TextField(
controller: email,
decoration: InputDecoration(
hintText: 'youremail@example.com',
labelText: 'Enter your email'
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 48.0, top: 14.0, right: 48.0, bottom: 14.0),
child: TextField(
controller: password,
obscureText: true,
decoration: InputDecoration(
hintText: 'Enter your password', labelText: '******'
),
),
),
Column(
children: <Widget>[
ButtonTheme(
minWidth: 320,
height: 45.0,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
color: Colors.redAccent,
onPressed: () {
var user = User();
user.email = email.text;
user.password = password.text;
_login(context, user);
},
child: Text(
'Log in',
style: TextStyle(color: Colors.white),
),
),
),
FlatButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) =>
RegistrationScreen(cartItems: this.widget
.cartItems,)));
},
child: FittedBox(child: Text('Register your account')),
),
],
),
],
),
),
);
}
}
import 'widgets/app.dart';
import 'package:flutter/material.dart';
void main() => runApp(App());
import 'dart:convert';
import 'package:ecom_app/models/product.dart';
class Payment {
int id;
String name;
String email;
String cardNumber;
String expiryMonth;
String expiryYear;
String cvcNumber;
int userId;
List<Product> cartItems;
toJson() {
return {
'id': id.toString(),
'userId': userId.toString(),
'name': name,
'email': email,
'cardNumber': cardNumber,
'expiryMonth': expiryMonth,
'expiryYear': expiryYear,
'cvcNumber': cvcNumber,
'cartItems': json.encoder.convert(cartItems)
};
}
}
import 'dart:async';
import 'dart:convert';
import 'package:ecom_app/models/payment.dart';
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/screens/home_screen.dart';
import 'package:ecom_app/services/cart_service.dart';
import 'package:ecom_app/services/payment_service.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class PaymentScreen extends StatefulWidget {
final List<Product> cartItems;
PaymentScreen({this.cartItems});
@override
_PaymentScreenState createState() => _PaymentScreenState();
}
class _PaymentScreenState extends State<PaymentScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final _cardHolderName = TextEditingController();
final _cardHolderEmail = TextEditingController();
final _cardNumber = TextEditingController();
final _expiryMonth = TextEditingController();
final _expiryYear = TextEditingController();
final _cvcNumber = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Make payment'),
backgroundColor: Colors.redAccent,
leading: Text(''),
elevation: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
body: Padding(
padding: const EdgeInsets.only(top: 0.0),
child: ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 28.0, right: 28.0, bottom: 14.0),
child: Text('Make payment',
style:
TextStyle(fontSize: 28.0, fontWeight: FontWeight.bold)),
),
Divider(
height: 5.0,
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
keyboardType: TextInputType.emailAddress,
controller: _cardHolderEmail,
decoration: InputDecoration(hintText: 'Email'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: _cardHolderName,
decoration: InputDecoration(hintText: 'Name'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: _cardNumber,
decoration: InputDecoration(
hintText: 'Card Number',
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: _expiryMonth,
decoration: InputDecoration(
hintText: 'Expiry Month',
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: _expiryYear,
decoration: InputDecoration(
hintText: 'Expiry Year',
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: _cvcNumber,
obscureText: true,
decoration: InputDecoration(
hintText: 'CVC',
),
),
),
Column(
children: <Widget>[
ButtonTheme(
minWidth: 320.0,
height: 45.0,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7.0)),
color: Colors.redAccent,
onPressed: () async {
SharedPreferences _prefs =
await SharedPreferences.getInstance();
var payment = Payment();
payment.userId = _prefs.getInt('userId');
payment.name = _cardHolderName.text;
payment.email = _cardHolderEmail.text;
payment.cardNumber = _cardNumber.text;
payment.expiryMonth = _expiryMonth.text;
payment.expiryYear = _expiryYear.text;
payment.cvcNumber = _cvcNumber.text;
payment.cartItems = this.widget.cartItems;
_makePayment(context, payment);
},
child: Text('Make Payment',
style: TextStyle(color: Colors.white)),
),
),
],
),
],
),
),
);
}
void _makePayment(BuildContext context, Payment payment) async {
PaymentService _paymentService = PaymentService();
var paymentData = await _paymentService.makePayment(payment);
var result = json.decode(paymentData.body);
if (result['result'] == true) {
CartService _cartService = CartService();
this.widget.cartItems.forEach((cartItem) {
_cartService.deleteCartItemById(cartItem.id);
});
_showPaymentSuccessMessage(context);
Timer(Duration(seconds: 2), () {
Navigator.pop(context);
Navigator.push(
context, MaterialPageRoute(builder: (context) => HomeScreen()));
});
}
}
_showPaymentSuccessMessage(BuildContext context) {
return showDialog(
context: context,
barrierDismissible: true,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0))),
content: Container(
height: 360,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/success.png'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Order & Payment is successfully done!',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 24.0),
),
),
],
),
),
);
});
}
}
import 'package:ecom_app/models/payment.dart';
import 'package:ecom_app/repository/repository.dart';
class PaymentService {
Repository _repository;
PaymentService() {
_repository = Repository();
}
makePayment(Payment payment) async {
return await _repository.httpPost('make-payment', payment.toJson());
}
}
class Product {
int id;
String name;
String photo;
int price;
int discount;
String detail;
int quantity;
toMap() {
var map = Map<String, dynamic>();
map['productId'] = id;
map['productName'] = name;
map['productPhoto'] = photo;
map['detail'] = detail;
map['productPrice'] = price;
map['productDiscount'] = discount;
map['productQuantity'] = quantity;
return map;
}
toJson() {
return {
'productId': id.toString(),
'productName': name.toString(),
'productPhoto': photo.toString(),
'productPrice': price.toString(),
'productDiscount': discount.toString(),
'productQuantity': quantity.toString(),
'detail': detail.toString(),
};
}
}
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/screens/product_detail.dart';
import 'package:flutter/material.dart';
class ProductByCategory extends StatefulWidget {
final Product product;
ProductByCategory(this.product);
@override
_ProductByCategoryState createState() => _ProductByCategoryState();
}
class _ProductByCategoryState extends State<ProductByCategory> {
@override
Widget build(BuildContext context) {
return Container(
height: 260,
width: 190,
child: InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => ProductDetail(this.widget.product)));
},
child: Card(
child: Column(
children: <Widget>[
Text(this.widget.product.name),
Image.network(widget.product.photo, width: 190.0, height: 160.0,),
Row(children: <Widget>[
Text('Price: ${this.widget.product.price}'),
Text('Discount: ${this.widget.product.discount}'),
],)
],
),
),
),
);
}
}
import 'dart:convert';
import 'package:ecom_app/models/product.dart';import 'package:ecom_app/screens/cart_screen.dart';
import 'package:ecom_app/services/cart_service.dart';
import 'package:flutter/material.dart';
class ProductDetail extends StatefulWidget {
final Product product;
ProductDetail(this.product);
@override
_ProductDetailState createState() => _ProductDetailState();
}
class _ProductDetailState extends State<ProductDetail> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
CartService _cartService = CartService();
List<Product> _cartItems;
@override
void initState() {
super.initState();
print(this.widget.product.toJson());
_getCartItems();
}
_getCartItems() async {
_cartItems = List<Product>();
var cartItems = await _cartService.getCartItems();
cartItems.forEach((data) {
var product = Product();
product.id = data['productId'] ?? "";
product.name = data['productName'] ?? "";
product.photo = data['productPhoto'] ?? "";
product.price = data['productPrice'] ?? "";
product.discount = data['productDiscount'] ?? "";
product.detail = data['detail'] ?? 'No detail';
product.quantity = data['productQuantity'] ;
setState(() {
_cartItems.add(product);
});
});
}
_addToCart(BuildContext context, Product product) async {
var result = await _cartService.addToCart(product);
if (result > 0) {
_getCartItems();
_showSnackMessage(Text('Item added to cart successfully!',
style: TextStyle(color: Colors.green),));
} else {
_showSnackMessage(
Text('Failed to add to cart!', style: TextStyle(color: Colors.red),));
}
}
_showSnackMessage(message) {
var snackBar = SnackBar(
content: message,
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text(this.widget.product.name),
backgroundColor: Colors.redAccent,
actions: <Widget>[
InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => CartScreen(_cartItems)));
},
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 150,
width: 30,
child: Stack(
children: <Widget>[
IconButton(
iconSize: 30,
icon: Icon(Icons.shopping_cart, color: Colors.white,),
onPressed: () {
},
),
Positioned(
child: Stack(
children: <Widget>[
Icon(Icons.brightness_1, size: 25, color: Colors
.black),
Positioned(
top: 4.0,
right: 8.0,
child: Center(
child: Text(_cartItems.length.toString())),
),
],
),
),
],
),
),
),
)
],
),
body: ListView(
children: <Widget>[
Container(
height: 300,
child: GridTile(
child: Padding(
padding: const EdgeInsets.only(bottom: 40.0),
child: Container(
child: Image.network(this.widget.product.photo),
),
),
footer: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Container(
child: ListTile(
leading: Text(this.widget.product.name, style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold),),
title: Row(
children: <Widget>[
Expanded(child: Text('\$${this.widget.product.price -
this.widget.product.discount}', style: TextStyle(
color: Colors.redAccent,
fontSize: 20,
fontWeight: FontWeight.bold),)),
Expanded(child: Text('\$${this.widget.product.price}',
style: TextStyle(color: Colors.black54,
fontSize: 20,
fontWeight: FontWeight.bold,
decoration: TextDecoration.lineThrough),)),
],
),
),
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
onPressed: () {
_addToCart(context, this.widget.product);
},
textColor: Colors.redAccent,
child: Row(
children: <Widget>[
Text('Add to cart'),
IconButton(
onPressed: () {
},
icon: Icon(Icons.shopping_cart),
)
],
),
),
IconButton(onPressed: () {
}, icon: Icon(Icons.favorite_border, color: Colors.redAccent,),)
],),
Divider(),
Padding(
padding: const EdgeInsets.only(left: 10.0),
child: ListTile(
title: Text('Product detail', style: TextStyle(fontSize: 20),),
subtitle: Text(this.widget.product.detail),
),
),
],
),
);
}
}
import 'package:ecom_app/repository/repository.dart';
class ProductService {
Repository _repository;
ProductService() {
_repository = Repository();
}
getHotProducts() async {
return await _repository.httpGet('get-all-hot-products');
}
getNewArrivalProducts() async {
return await _repository.httpGet('get-all-new-arrival-products');
}
getProductsByCategoryId(int categoryId) async {
return await _repository.httpGetById(
"get-products-by-category", categoryId);
}
}
import 'dart:convert';
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/services/product_service.dart';
import 'package:ecom_app/widgets/product_by_category.dart';
import 'package:flutter/material.dart';
class ProductsByCategoryScreen extends StatefulWidget {
final String categoryName;
final int categoryId;
ProductsByCategoryScreen({this.categoryName, this.categoryId});
@override
_ProductsByCategoryScreenState createState() => _ProductsByCategoryScreenState();
}
class _ProductsByCategoryScreenState extends State<ProductsByCategoryScreen> {
ProductService _productService = ProductService();
List<Product> _productListByCategory = List<Product>();
_getProductsByCategory() async {
var products = await _productService.getProductsByCategoryId(this.widget.categoryId);
var _list = json.decode(products.body);
_list['data'].forEach((data){
var model = Product();
model.id = data['id'];
model.name = data['name'];
model.photo = data['photo'];
model.price = data['price'];
model.discount = data['discount'];
model.detail = data['detail'];
setState(() {
_productListByCategory.add(model);
});
});
}
@override
void initState() {
super.initState();
_getProductsByCategory();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.redAccent,
title: Text(this.widget.categoryName),
),
body: Container(
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: _productListByCategory.length,
itemBuilder: (context, index){
return ProductByCategory(this._productListByCategory[index]);
},
),
),
);
}
}
import 'dart:convert';
import 'package:ecom_app/models/product.dart';
import 'package:ecom_app/models/user.dart';
import 'package:ecom_app/screens/login_screen.dart';
import 'package:ecom_app/services/user_service.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class RegistrationScreen extends StatefulWidget {
final List<Product> cartItems;
RegistrationScreen({this.cartItems});
@override
_RegistrationScreenState createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final name = TextEditingController();
final email = TextEditingController();
final password = TextEditingController();
_register(BuildContext context, User user) async {
var _userService = UserService();
var registeredUser = await _userService.createUser(user);
var result = json.decode(registeredUser.body);
if (result['result'] == true) {
SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.setInt('userId', result['user']['id']);
_prefs.setString('userName', result['user']['name']);
_prefs.setString('userEmail', result['user']['email']);
} else {
_showSnackMessage(Text(
'Failed to register the user!', style: TextStyle(color: Colors.red),));
}
}
_showSnackMessage(message) {
var snackBar = SnackBar(
content: message,
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.close,
color: Colors.red,
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
body: Padding(
padding: const EdgeInsets.only(top: 100.0),
child: ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: name,
decoration: InputDecoration(
hintText: 'Enter your name', labelText: 'Enter your name'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
keyboardType: TextInputType.emailAddress,
controller: email,
decoration: InputDecoration(
hintText: 'Enter your email address',
labelText: 'Enter your email address'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 14.0, right: 28.0, bottom: 14.0),
child: TextField(
controller: password,
obscureText: true,
decoration:
InputDecoration(hintText: 'Password', labelText: '******'),
),
),
Column(
children: <Widget>[
ButtonTheme(
minWidth: 320.0,
height: 45.0,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7.0)),
color: Colors.redAccent,
onPressed: () {
var user = User();
user.name = name.text;
user.email = email.text;
user.password = password.text;
_register(context, user);
},
child:
Text('Register', style: TextStyle(color: Colors.white)),
),
),
Padding(
padding: const EdgeInsets.all(5),
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoginScreen()));
},
child: FittedBox(child: Text('Log in to your account')),
),
),
],
),
Padding(
padding: const EdgeInsets.only(
left: 65.0, top: 14.0, right: 65.0, bottom: 14.0),
child: Text(
'By signing up you accept the Terms of Service and Privacy Policy',
textAlign: TextAlign.center,
),
),
],
),
),
);
}
}
import 'package:ecom_app/repository/db_connection.dart';
import 'package:http/http.dart' as http;
import 'package:sqflite/sqflite.dart';
class Repository {
DatabaseConnection _connection;
String _baseUrl = 'http://10.0.2.2:8080/api';
var headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
Repository() {
_connection = DatabaseConnection();
}
static Database _database;
Future<Database> get database async {
if (_database != null)
return _database;
_database = await _connection.initDatabase();
return _database;
}
httpGet(String api) async {
return await http.get(_baseUrl + "/" + api);
}
httpGetById(String api, id) async {
return await http.get(_baseUrl + "/" + api + "/" + id.toString());
}
httpPost(String api, data) async {
return await http.post(_baseUrl + "/" + api, body: data);
}
getAllLocal(table) async {
var conn = await database;
return await conn.query(table);
}
saveLocal(table, data) async {
var conn = await database;
return await conn.insert(table, data);
}
updateLocal(table, columnName, data) async {
var conn = await database;
return await conn.update(
table, data, where: '$columnName =?', whereArgs: [data['productId']]);
}
getLocalByCondition(table, columnName, conditionalValue) async {
var conn = await database;
return await conn.rawQuery(
'SELECT * FROM $table WHERE $columnName=?', ['$conditionalValue']);
}
deleteLocalById(table, id) async {
var conn = await database;
return await conn.rawDelete("DELETE FROM $table WHERE id = $id");
}
deleteLocal(table) async {
var conn = await database;
return await conn.rawDelete("DELETE FROM $table");
}
}
class Shipping {
int id;
String name;
String email;
String address;
toJson() {
return {
'id': id.toString(),
'name': name,
'email': email,
'address': address};
}
}
import 'package:ecom_app/models/shipping.dart';import 'package:ecom_app/repository/repository.dart';
class ShippingService {
Repository _repository;
ShippingService() {
_repository = Repository();
}
addShipping(Shipping shipping) async {
return await _repository.httpPost('shipping', shipping.toJson());
}
}
import 'package:ecom_app/repository/repository.dart';
class SliderService {
Repository _repository;
SliderService() {
_repository = Repository();
}
getSliders() async {
return await _repository.httpGet('sliders');
}
}
class User {
int id;
String name;
String email;
String password;
toJson() {
return {
'id': id.toString(),
'name': name.toString(),
'email': email,
'password': password,
};
}
}
import 'package:ecom_app/models/user.dart';
import 'package:ecom_app/repository/repository.dart';
class UserService {
Repository _repository;
UserService() {
_repository = Repository();
}
createUser(User user) async {
return await _repository.httpPost('register', user.toJson());
}
login(User user) async {
return await _repository.httpPost('login', user.toJson());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment