List cart =[];
double totalPrice = 0.0;
//here is i retrieve cart item from database to calculate
Future getData() async {
final CollectionReference reference = FirebaseFirestore.instance.collection('cart');
reference.doc(FirebaseAuth.instance.currentUser!.email).collection('items').get().then((ds) {
ds.docs.forEach((data) {
/*var temp = {
'image': data['image'],
'name': data['name'],
'category': data['category'],
'price': data['price'],
};*/
setState(() {
cart.add(data['price']);
double e = double.parse(data['price']);
totalPrice = totalPrice + e;
});
print(totalPrice.toStringAsFixed(2));
});
});
}
double getTotalPrice() { // calculate of my total price
double totPrice = 0.00;
for(int i=0; i<cart.length; i++){
String price = cart[i];
double p = double.parse(price);
totPrice = totPrice + p;
}
return totPrice;
}
#override
void initState() {
// TODO: implement initState
super.initState();
getData();
getTotalPrice();
}
Future<void> initPayment({required String email, required double amount, required BuildContext context}) async {
double newAmount = amount * 100;
try {
// create a payment intent on the server
final response = await http.post(
Uri.parse('https://us-central1-market-3387e.cloudfunctions.net/stripePaymentIntentRequest'),
body: {
'email': email,
'amount': newAmount.toString(),
'payment_method_types[]': "card",
});
double roundDouble(double value, int places){
num mod = pow(10.0, places);
return ((value * mod).round().toDouble() / mod);
}
#override
Widget build(BuildContext context) {
bottomNavigationBar: Container(
child: ElevatedButton(
child: Text('Payment', style: GoogleFonts.hammersmithOne(
// i can't display total price value here at amount:
onPressed: () async {
double h = roundDouble(totalPrice, 2);
await initPayment(amount: h, context: context, email: 'test#gmail.com');
},
),
),
I do not know why but i already calculate the total price at getTotalPrice() function, but when i declare var h at the amount, it doesn't display the value cause i think i already did true. can someone show me how it supposed to be the calculation because i already declare in the stripe function.
var h is where i declare my calculation of total price but i doesn't display the value it doesn't working. When i route from shopping cart to payment page , the total price doesn't retrieve and display the value. I already retrieve data from my database from "cart" collection
Related
I am using Provider to manage the app state in flutter and use provider to call api and store it in model class and provider is called inside build method, its an inventory app.
when cart page is opened, provider to fetch cart items is called and cart items will be displayed, but the issue is the api to fetch cart items keeps on executing infinitly, in ui data gets replicated. Can anyone please help with this issue.
the code to call cart provider is
#override
Widget build(BuildContext context)
{
final FirebaseAuth _auth = FirebaseAuth.instance;
User? user = _auth.currentUser;
var phoneNumber = user!.phoneNumber;
final cartProvider = Provider.of<CartProvider>(context);
cartProvider.fetchCartByUser(user.phoneNumber.toString());
final testString = ModalRoute.of(context)!.settings.arguments as String;
return
isEmpty
? Scaffold(body: CartEmpty())
:
Scaffold
( //display cart items)
cart provider class is
class CartProvider with ChangeNotifier {
List<CartModel> _cartItems = [];
List<CartModel> get cartItems {
return [..._cartItems];
}
CollectionReference cart = FirebaseFirestore.instance.collection('cart');
Future<void> fetchCartByUser(String phoneNumber) async
{
await Server.getCartData().then((value)
{
for(var item in value)
{
_cartItems.insert
(
0,
CartModel
(
cartId: item['cartId'],
clientAddress: item['clientAddress'],
clientFullname: item['clientFullname'],
clientPhoneNumber: item['clientPhoneNumber'],
createdAt: item['createdAt'],
merchant: item['merchant'],
merchantCode: item['merchantCode'],
price: item['price'],
productCode: item['productCode'],
productImage: item['productImage'],
productName: item['productName'],
productQty: item['productQty'],
productSKU: item['productSKU'],
),
);
}
});
notifyListeners();
}
Future<void> deleteSingleCart(String cartId) async {
await cart
.doc(cartId)
.delete()
.then((value) => print("Cart Deleted"))
.catchError((error) => print("Failed to delete user: $error"));
// this.fetchCartByUser();
notifyListeners();
}
Future<void> updateProductQty(String cartId, String qty) async {
await cart.doc(cartId).update({'productQty': qty});
}
double get totalAmount {
var total = 0.0;
for (var i = 0; i < _cartItems.length; i++) {
total +=
int.parse(_cartItems[i].price) * int.parse(cartItems[i].productQty);
}
return total;
}
}
#override
void initState() {
super.initState();
WidgetsBinding.instance!.addPostFrameCallback((_) {
// Here you can fetch data login
});
}
Warning:
This function has a return type of 'int', but doesn't end with a return statement. Try adding a return statement, or changing the return type to 'void'.
I am getting a warning in this code:
int _duration = 0;
int getDuration(String date) {
//print("Date $date");
//load the data from firebase and add to the list
fb.reference()
..child(cuser.uid)
.child('Seizure_history')
.child(date)
.once()
.then((DataSnapshot snapshot) {
var data = snapshot.value;
list = List();
if (data != null) {
data.forEach((key, value) {
EventList seizure_history = new EventList(
seiz_duration: value['duration'],
dateTime: value['datetime'],
key: key,
);
list.add(seizure_history);
setState(() {
_duration = int.parse(list[list.length - 1].seiz_duration);
});
print("Duration $_duration");
return _duration;
});
}
});
}
I have also returned the duration but it is still showing the warning, please help me out where I am going wrong? It is printing duration correctly on the console but not returning.
I want to return the duration after finding it in firebase but it is still showing zero which means no value is returning, why is it happening. I am new to flutter and I am still learning.
UPDATED:
this function is called inside initState():
var series;
var data;
//Charts
getCharts()
{
data = [
addcharts(sevenDay.substring(0, 2), getDuration(seven),
charts.ColorUtil.fromDartColor(const Color(0xffe8e5af))),
addcharts(sixDay.substring(0, 2), getDuration(six),
charts.ColorUtil.fromDartColor(const Color(0xffe8e5af))),
addcharts(fiveDay.substring(0, 2),getDuration(five),
charts.ColorUtil.fromDartColor(const Color(0xffe8e5af))),
addcharts(fourDay.substring(0, 2), getDuration(four),
charts.ColorUtil.fromDartColor(const Color(0xffe8e5af))),
addcharts(threeDay.substring(0, 2), getDuration(three),
charts.ColorUtil.fromDartColor(const Color(0xffe8e5af))),
addcharts(twoDay.substring(0, 2), getDuration(two),
charts.ColorUtil.fromDartColor(const Color(0xffe8e5af))),
addcharts(oneDay.substring(0, 2), getDuration(one),
charts.ColorUtil.fromDartColor(const Color(0xffe8e5af))),
];
series = [
charts.Series(
domainFn: (addcharts addcharts, _) => addcharts.weeks,
measureFn: (addcharts addcharts, _) => addcharts.duration,
colorFn: (addcharts addcharts, _) => addcharts.barColor,
id: 'addcharts',
data: data,
),
];
}
How can I use the future Builder inside it? That's where i am stuck if i use FutureBuilder
Expanded(
child: charts.BarChart(
series,
animationDuration: Duration(microseconds: 2000),
),
)
First, you should do asynchonous computation inside an asynchoronous method:
// Return a Future<int> and add async to its declaration
Future<int> getDuration(String date) async {
final DataSnapshot snapshot = await (fb.reference()
..child(cuser.uid)
.child('Seizure_history')
.child(date)
.once());
var data = snapshot.value;
// Return a default value in case `snapshot.value` is null
if (data == null) return 0;
list = [];
data.forEach((key, value) {
final EventList seizure_history = new EventList(
seiz_duration: value['duration'],
dateTime: value['datetime'],
key: key,
);
list.add(seizure_history);
setState(() {
_duration = int.parse(list[list.length - 1].seiz_duration);
});
return _duration;
});
}
However, your logic doesn't make sense. You're trying to return a value (_duration) inside a for-each, so there are two possibilities: 1) you want to return the first duration from data; or 2) you want to return all the durations from data. Here's how you can do in both situations:
Returning the first duration from data
Future<int> getDuration(String date) async {
// ...
list = [];
// Get the first entry from data
var entry = data.first;
final EventList seizure_history = EventList(
seiz_duration: entry.value['duration'],
dateTime: entry.value['datetime'],
key: entry.key,
);
list.add(seizure_history);
// Get the seizure duration
final int duration = int.parse(seizure_history.seiz_duration);
setState(() => _duration = duration);
return duration;
}
Returning all the durations from data
// Since there are multiple durations, use a List<int> instead of int
final List<int> _durations = [];
// Update the method signature
Future<List<int>> getDuration(String date) async {
// ...
// Create a local `_durations` to update the property's one only once
final List<int> durations = [];
// Use a map to fetch all the durations
list = data.map((key, value) {
final EventList seizure_history = new EventList(
seiz_duration: value['duration'],
dateTime: value['datetime'],
key: key,
);
// Add the duration to the local's one
durations.add(int.parse(seizure_history.seiz_duration);
// Add the seizure history to the list
return seizure_history;
}).toList();
setState(() => _durations = durations);
return durations;
}
Of course you need to change where are you calling getDuration since now it returns a Future, but you can use a FutureBuilder widget to help you with that.
You just have to return an int at the end of your function like so:
int getDuration(String date) {
//print("Date $date");
//load the data from firebase and add to the list
fb.reference()
..child(cuser.uid)
.child('Seizure_history')
.child(date)
.once()
.then((DataSnapshot snapshot) {
var data = snapshot.value;
list = List();
if (data != null) {
data.forEach((key, value) {
EventList seizure_history = new EventList(
seiz_duration: value['duration'],
dateTime: value['datetime'],
key: key,
);
list.add(seizure_history);
setState(() {
_duration = int.parse(list[list.length - 1].seiz_duration);
});
print("Duration $_duration");
return _duration;
});
}
});
return 0;
}
The error comes from the fact that when you defined your function you said that it will return an int type, but if the conditions are not fulfilled, it will return nothing (and therefore, don't return an int)
You also need to return int in case your Future fails.
int getDuration(String date) {
fb.reference(...);
return 0; // Return something here.
}
or
Change your return type to int?:
int? getDuration(String date) {...}
I am trying to check if the product already added to the basket and give the message with snackbar "This product already added". So user can not add the same product to the cart again.
here is the code of mine :
//Button calling controller adding item to cart
InkWell(
onTap:(){
_con.addItemToCart(_con.product);
});
//Controller adding item to cart
Future addItemToCart(Product product, {bool reset = false}) async {
setState(() {
this.loadCart = true;
});
Cart value =
await addToCart(product, scaffoldKey, context, quantity: quantity);
setState(() {
this.cart = value;
this.loadCart = false;
this.totalProductsInStock = this.product.availability;
this.totalProductsInStock -= this.totalProductsInStock - this.quantity ;
});
}
Future<Cart> addToCart(Product product, GlobalKey<ScaffoldState> scaffoldKey, BuildContext buildContext, {bool reset = false, int quantity = 1}) async {
var _cartPoduct = new CartProduct();
_cartPoduct.productId = product.id;
_cartPoduct.optionId = product.optionId;
_cartPoduct.quantity = quantity;
Cart value = await CartRepository.addCart(_cartPoduct, reset);
return value;
}
//Request
static Future<Cart> addCart(CartProduct cartProduct, bool reset) async {
User _user = userRepo.currentUser.value;
if (_user.apiToken == null) {
return new Cart();
}
Map<String, dynamic> decodedJSON = {};
cartProduct.userId = _user.id;
final String url =
'${GlobalConfiguration().getString('api_base_url')}';
final client = new http.Client();
final response = await client
.get(url, headers: {HttpHeaders.contentTypeHeader: 'application/json'});
try {
decodedJSON = json.decode(response.body)['data'] as Map<String, dynamic>;
} on FormatException catch (e) {
}
return Cart.fromJSON(decodedJSON);
}
I created a temporary list to check if the product has been added to the cart, and I have it checked with provider. You can check it maybe it will be useful for you
link
I am implementing a ListView that will show a Card with the distance between the user and each card location, the location of the card is obtained from Firestore. Im using the geoLocator package but i have an issue to receive the distance, i got null when i call the method and i know that i have to use async-wait in order to wait for the value of the distance but i do not know where to implement it.
This is the class that i call to the get the distance:
class Distance {
double distance;
void getDistance(double startLatitude, double startLongitude, double endLatitude,
double endLongitude) async {
try {
distance = await Geolocator().distanceBetween(
startLatitude, startLongitude, endLatitude, endLongitude);
} catch (e) {
print('SE DISPARO EL ERROR DE DISTANCE = $e');
}
}
This is the Widget that i return:
Widget cardList(double userLatitude, double userLongitude) {
double result;
// Method to get the distance
dynamic getDistance(double cardLatitude, double cardLongitude) async {
Distance distancia = Distance();
await distancia.getDistance(
userLatitude, userLongitude, cardLatitude, cardLongitude);
result = distancia.distance;
return result;
}
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('salonesInfantiles').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.pink,
),
);
}
final rooms = snapshot.data.documents.reversed;
List<SalonesFeed> listaDeSalones = [];
// List<SalonesFeed> listaDeSalonesDistancia = [];
for (var room in rooms) {
final nombreSalonText = room.data['nombre'];
final salonLatitude = room.data['latitude'];
final salonLongitude = room.data['longitude'];
// This is the method that i dont know how to implement the wait in order to receive the value before the ListView is showed
double distance = getDistance(salonLatitude, salonLongitude);
print('result 2 = $result');
final salonCard = SalonesFeed(
nombreSalon: nombreSalonText,
distanciaSalon: distance,
);
listaDeSalones.add(salonCard);
}
return Expanded(
child: ListView(
children: listaDeSalones,
),
);
},
);
}
I got this result:
type 'Future<dynamic>' is not a subtype of type 'double'
I also try to make it Future but still have the same issue of null
type 'Future<double>' is not a subtype of type 'double'
The return type of getDistance should be Future and you should await the response
double distance = await getDistance(salonLatitude, salonLongitude);
I want to get the total of the price column values and save it in a variable and return it...I have gone through other posts one of which is the question which i am asking but it was in android native and i am new to sqflite so i couldnt figure out how to write the code. So please help me with suggestions.
this is my code of the columns i am using
void _onCreate(Database db, int version) async {
await db.execute(
"CREATE TABLE Cart(id INTEGER PRIMARY KEY,name TEXT, price TEXT,category
TEXT,images TEXT)");
print("DB created");
}
I am trying to do this
Future calculateTotal() async{
var dbClient = await db;// couldnt figure out after this
var cursor = dbClient.rawQuery("SELECT SUM(price) as Total FROM Cart",
null);
if(cursor.move)
}
According to https://www.techiediaries.com/flutter-sqlite-crud-tutorial/ this should do:
Future calculateTotal() async {
var dbClient = await db;
var result = await dbClient.rawQuery("SELECT SUM(price) as Total FROM Cart");
print(result.toList());
}
int _total;
void _calcTotal() async{
var total = (await db.calculateTotal())[0]['Total'];
print(total);
setState(() => _total = total)
}
#override
Widget build(BuildContext context) {
...
Text(_total != null ? _total : 'waiting ...', ... )
Future<List> calculateTotal() async {
var dbClient = await db;
var result = await dbClient.rawQuery("SELECT * FROM Cart");
return result.toList();
}
int _total = 0;
List priceList;
void _calcTotal() async{
priceList = await db.calculateTotal();
priceList.forEach((price){ _total = _total + price['price'];});
print(_total);
setState(() => _total = total);
}
#override
Widget build(BuildContext context) {
...
Text(_total != null ? _total : 'waiting ...', ... )