Reputation: 309
I am working to build basic shopping functions in my Flutter app. I'm new to coding and Flutter. When the user clicks the PlaceOrderPageContainer (button) to confirm check out the addOrderDetails() method is called which then updates the Firebase database. Everything is updating in Firestore Database correctly other than the Total Amount which is being added as zero regardless of the total amount in the shopping cart. I'm not getting any errors in the console but it's obvious my code isn't written correctly. Any help will be greatly appreciated. I can add any additional code if that will be helpful.
class ShoppingCartPage extends StatefulWidget {
const ShoppingCartPage({Key? key}) : super(key: key);
@override
_ShoppingCartPageState createState() => _ShoppingCartPageState();
}
class _ShoppingCartPageState extends State<ShoppingCartPage> {
late double totalAmount;
@override
void initState() {
super.initState();
totalAmount = 0;
Provider.of<TotalAmountProvider>(
context,
listen: false,
).display(0);
}
@override
Widget build(BuildContext context) {
return Consumer2<TotalAmountProvider, CartItemCounterProvider>(
builder: (context, amountProvider, cartProvider, c) {
return SafeArea(
child: Scaffold(
appBar: const ShoppingCartAppBar(),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
if (ShoppingApp.sharedPreferences
.getStringList(
ShoppingApp.userCartList,
)
?.length ==
1) {
Fluttertoast.showToast(msg: ToastString.cartEmpty);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddressPage(
totalAmount: totalAmount,
),
),
);
}
},
icon: const Icon(
Icons.navigate_next,
),
label: Text(
ButtonString.checkOut.toUpperCase(),
),
),
body: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child:
Consumer2<TotalAmountProvider, CartItemCounterProvider>(
builder: (context, amountProvider, cartProvider, c) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: cartProvider.count == 0
? Container()
: Text(
'Total Price: \$${amountProvider.totalAmount.toString()}',
style: Theme.of(context).textTheme.headline6,
),
),
);
},
),
),
StreamBuilder<QuerySnapshot>(
stream: ShoppingApp.firestore
.collection('items')
.where('shortInfo',
whereIn: ShoppingApp.sharedPreferences
.getStringList(ShoppingApp.userCartList))
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
return !snapshot.hasData
? const AdaptiveCircularProgressSliver()
: snapshot.data.docs.isEmpty
? const EmptyShoppingCartContainer()
: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
ItemModel model = ItemModel.fromJson(
snapshot.data.docs[index].data(),
);
if (index == 0) {
totalAmount = 0;
// totalAmount = model.price! + totalAmount;
} else {
totalAmount =
model.price! + totalAmount;
}
if (snapshot.data?.docs.length - 1 ==
index) {
WidgetsBinding.instance!
.addPostFrameCallback((timeStamp) {
Provider.of<TotalAmountProvider>(
context,
listen: false)
.display(totalAmount);
});
}
return sourceInfo(
model,
context,
removeCartFunction: () =>
removeItemFromUserCart(
model.shortInfo as String,
),
);
},
childCount: snapshot.hasData
? snapshot.data?.docs.length
: 0,
),
);
}),
],
),
),
);
},
);
}
Future<void> removeItemFromUserCart(
String shortInfoAsID,
) async {
List<String>? tempCartList = ShoppingApp.sharedPreferences.getStringList(
ShoppingApp.userCartList,
);
tempCartList?.remove(shortInfoAsID);
await ShoppingApp.firestore
.collection(ShoppingApp.collectionUser)
.doc(ShoppingApp.sharedPreferences.getString(
ShoppingApp.userUID,
))
.update({
ShoppingApp.userCartList: tempCartList,
}).then((value) {
Fluttertoast.showToast(
msg: ToastString.removeFromCart,
);
ShoppingApp.sharedPreferences.setStringList(
ShoppingApp.userCartList,
tempCartList as List<String>,
);
Provider.of<CartItemCounterProvider>(
context,
listen: false,
).displayResult();
totalAmount = 0;
});
}
}
class AddressPage extends StatefulWidget {
const AddressPage({
Key? key,
required this.totalAmount,
}) : super(key: key);
final double totalAmount;
@override
_AddressPageState createState() => _AddressPageState();
}
class _AddressPageState extends State<AddressPage> {
@override
Widget build(BuildContext context) {
return SafeArea(
child: AdaptiveLayoutScaffold(
appBar: const AddressPageAppBar(),
floatingActionButton: const AddNewAddressFAB(),
landscapeBodyWidget: Container(),
portraitBodyWidget: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
const AddressPageHeadline(
headlineText: ShoppingPageString.selectAddress,
),
Consumer<AddressChangerProvider>(builder: (
context,
address,
c,
) {
return Flexible(
child: StreamBuilder<QuerySnapshot>(
stream: ShoppingApp.firestore
.collection(ShoppingApp.collectionUser)
.doc(ShoppingApp.sharedPreferences
.getString(ShoppingApp.userUID))
.collection(ShoppingApp.subCollectionAddress)
.snapshots(),
builder: (context, snapshot) {
return !snapshot.hasData
? const AdaptiveCircularProgressCenter()
: snapshot.data!.docs.isEmpty
? const EmptyShippingAddressContainer()
: ListView.builder(
itemCount: snapshot.data?.docs.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return AddressCard(
addressID: snapshot.data?.docs[index].id
as String,
currentIndex: address.count,
model: AddressModel.fromJson(
snapshot.data?.docs[index].data()
as Map<String, dynamic>,
),
totalAmount: widget.totalAmount,
value: index,
);
},
);
}),
);
}),
],
),
),
);
}
}
class AddressCard extends StatefulWidget {
const AddressCard({
Key? key,
required this.addressID,
required this.currentIndex,
required this.model,
required this.totalAmount,
required this.value,
}) : super(key: key);
final String addressID;
final int currentIndex;
final AddressModel model;
final double totalAmount;
final int value;
@override
_AddressCardState createState() => _AddressCardState();
}
class _AddressCardState extends State<AddressCard> {
@override
Widget build(BuildContext context) {
return AddressCardContainer(
onTap: () {
Provider.of<AddressChangerProvider>(
context,
listen: false,
).displayResult(widget.value);
},
addressCardColumn: AddressCardColumn(
children: [
Row(
children: [
AddressCardRadioButton(
groupValue: widget.currentIndex,
onChanged: (value) {
Provider.of<AddressChangerProvider>(
context,
listen: false,
).displayResult(
value as int,
);
},
value: widget.value,
),
AddressCardContent(
city: widget.model.city as String,
fullName: widget.model.name as String,
phoneNumber: widget.model.phoneNumber as String,
postalCode: widget.model.postalCode as String,
state: widget.model.state as String,
streetAddress: widget.model.streetAddress as String,
),
],
),
widget.value == Provider.of<AddressChangerProvider>(context).count
? ShippingAddressProceedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (
context,
) =>
PlaceOrderPaymentPage(
addressID: widget.addressID,
totalAmount: widget.totalAmount,
),
),
);
},
)
: Container(),
],
),
);
}
}
class PlaceOrderPaymentPage extends StatefulWidget {
const PlaceOrderPaymentPage({
Key? key,
required this.addressID,
required this.totalAmount,
}) : super(key: key);
final String addressID;
final double totalAmount;
@override
_PlaceOrderPaymentPageState createState() => _PlaceOrderPaymentPageState();
}
class _PlaceOrderPaymentPageState extends State<PlaceOrderPaymentPage> {
@override
Widget build(BuildContext context) {
return AdaptiveLayoutScaffold(
appBar: const PlaceOrderPaymentPageAppBar(),
landscapeBodyWidget: Container(),
portraitBodyWidget: PlaceOrderPageContainer(
orderOnPressed: () => addOrderDetails(),
),
);
}
void addOrderDetails() {
final time = DateTime.now().millisecondsSinceEpoch;
writeOrderDetailsForUser({
ShoppingApp.addressID: widget.addressID,
ShoppingApp.totalAmount: widget.totalAmount,
'orderBy': ShoppingApp.sharedPreferences.getString(
ShoppingApp.userUID,
),
ShoppingApp.productID: ShoppingApp.sharedPreferences.getStringList(
ShoppingApp.userCartList,
),
ShoppingApp.paymentDetails: ShoppingPageString.cashOnDelivery,
ShoppingApp.orderTime: time.toString(),
ShoppingApp.isSuccess: true,
});
writeOrderDetailsForAdmin({
ShoppingApp.addressID: widget.addressID,
ShoppingApp.totalAmount: widget.totalAmount,
'orderBy': ShoppingApp.sharedPreferences.getString(
ShoppingApp.userUID,
),
ShoppingApp.productID: ShoppingApp.sharedPreferences.getStringList(
ShoppingApp.userCartList,
),
ShoppingApp.paymentDetails: ShoppingPageString.cashOnDelivery,
ShoppingApp.orderTime: time.toString(),
ShoppingApp.isSuccess: true,
}).whenComplete(() => {
emptyCartNow(),
});
}
void emptyCartNow() {
ShoppingApp.sharedPreferences.setStringList(ShoppingApp.userCartList, [
'garbageValue',
]);
List<String>? tempList = ShoppingApp.sharedPreferences.getStringList(
ShoppingApp.userCartList,
);
FirebaseFirestore.instance
.collection('users')
.doc(ShoppingApp.sharedPreferences.getString(
ShoppingApp.userUID,
))
.update({
ShoppingApp.userCartList: tempList,
}).then((value) {
ShoppingApp.sharedPreferences.setStringList(
ShoppingApp.userCartList,
tempList as List<String>,
);
Provider.of<CartItemCounterProvider>(
context,
listen: false,
).displayResult();
});
Fluttertoast.showToast(
msg: ToastString.orderPlacedSuccessfully,
);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const ShoppingPage(),
),
);
}
Future<void> writeOrderDetailsForUser(
Map<String, dynamic> data,
) async {
await ShoppingApp.firestore
.collection(ShoppingApp.collectionUser)
.doc(ShoppingApp.sharedPreferences.getString(ShoppingApp.userUID))
.collection(ShoppingApp.collectionOrders)
.doc(
ShoppingApp.sharedPreferences.getString(ShoppingApp.userUID)! +
data['orderTime'],
)
.set(data);
}
Future<void> writeOrderDetailsForAdmin(Map<String, dynamic> data) async {
await ShoppingApp.firestore
.collection(ShoppingApp.collectionOrders)
.doc(
ShoppingApp.sharedPreferences.getString(ShoppingApp.userUID)! +
data['orderTime'],
)
.set(data);
}
}
class CartItemCounterProvider extends ChangeNotifier {
final int _counter = (ShoppingApp.sharedPreferences
.getStringList(
ShoppingApp.userCartList,
)
?.length ??
0) -
1;
int get count => _counter;
Future<void> displayResult() async {
int _counter = (ShoppingApp.sharedPreferences
.getStringList(
ShoppingApp.userCartList,
)
?.length ??
0) -
1;
await Future.delayed(
const Duration(
milliseconds: 100,
), () {
notifyListeners();
});
}
}
Upvotes: 0
Views: 172
Reputation: 406
CartCheckOutFAB is first being instantiated with value 0 always since ShoppingCartPage state is not being changed. You could try to move Consumer2<TotalAmountProvider, CartItemCounterProvider> as parent of AdaptiveLayoutScaffold and instantiate the CartCheckOutFAB with amountProvider.totalAmount
Upvotes: 1