I am trying to merge the key
of type Map<dynamic, int>
with the value
of type Iterable<dynamic>
where the result will be a list in the end and be passed as a json to the api. Below is the json i want to achieve in the end:
{
"productQuantity": [
{
"product_id": 10,
"quantity": 1
},
{
"product_id": 11,
"quantity": 1
}
]
}
Using https://app.quicktype.io/
i generated the model class checkout
:
// To parse this JSON data, do
//
// final checkout = checkoutFromMap(jsonString);
import 'dart:convert';
class Checkout {
Checkout({
this.productQuantity,
});
List<ProductQuantity> productQuantity;
factory Checkout.fromJson(String str) => Checkout.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory Checkout.fromMap(Map<String, dynamic> json) => Checkout(
productQuantity: json["productQuantity"] == null ? null : List<ProductQuantity>.from(json["productQuantity"].map((x) => ProductQuantity.fromMap(x))),
);
Map<String, dynamic> toMap() => {
"productQuantity": productQuantity == null ? null : List<dynamic>.from(productQuantity.map((x) => x.toMap())),
};
}
class ProductQuantity {
ProductQuantity({
this.productId,
this.quantity,
});
int productId;
int quantity;
factory ProductQuantity.fromJson(String str) => ProductQuantity.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory ProductQuantity.fromMap(Map<String, dynamic> json) => ProductQuantity(
productId: json["product_id"] == null ? null : json["product_id"],
quantity: json["quantity"] == null ? null : json["quantity"],
);
Map<String, dynamic> toMap() => {
"product_id": productId == null ? null : productId,
"quantity": quantity == null ? null : quantity,
};
}
I do not know the correct way to merge the productID(Map<dynamic, int>)
and the quantity(Iterable<dynamic>)
and then pass it to the api.
I am using the BLOC pattern for getting the required data from the cart. Below is the checkout screen.
class CheckoutScreen extends StatelessWidget {
const CheckoutScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final List<ProductQuantity>? _OrderProductQuantity = [];
return Scaffold(
appBar: AppBar(
backgroundColor: buttonBG,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const ShippingAddress(),
const SizedBox(height: 20),
Container(
height: 60,
alignment: Alignment.bottomCenter,
decoration: const BoxDecoration(color: buttonBG),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Center(
child: BlocBuilder<CartBloc, CartState>(
builder: (context, state) {
if (state is CartLoaded) {
return TextButton(
onPressed: () {
var alc = state.cart
.productQuantity(state.cart.products);
var pio = alc.keys.toList();
var group = pio
.groupListsBy((element) => element.id)
.map((key, value) =>
MapEntry(key, value.length));
var pid = group.keys.toString();
var qt = alc.values;
debugPrint(
'productID = $pid'); // productID = (11, 10)
debugPrint(
'productQuantity = $qt'); // productQuantity = (1, 1)
BlocProvider.of<CartBloc>(context)
.add(PlaceOrderButtonPressed(
productQuantity: productQuantity,
));
},
child: Text(
'Place Order',
style: Theme.of(context)
.textTheme
.button!
.copyWith(color: Colors.white),
),
);
}
return const Text('There was an error');
},
),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.arrow_forward,
color: Colors.white,
),
)
],
),
),
],
));
}
}
Below is the CartBloc where i get the value of the productID and quantity:
FutureOr<void> _placeOrder(
PlaceOrderButtonPressed event, Emitter<CartState> emit) async {
emit(PlacingOrderState());
try {
await checkoutRepo.placeOrder(event.productQuantity);
emit(OrderSuccessState());
} catch (error) {
emit(OrderPlacingFailureState(error: error.toString()));
}
}
For the cartEvent:
class PlaceOrderButtonPressed extends CartEvent {
final List<ProductQuantity>? productQuantity;
const PlaceOrderButtonPressed({
required this.productQuantity,
});
@override
List<Object> get props => [];
}
The CheckoutRepository is as follows:
Future<void> placeOrder(
List<ProductQuantity>? productQuantity,
) async {
await SecureStorage.readSecureData("token")
.then((value) => finalToken = value);
debugPrint('Place Order With Token: $finalToken');
try {
Map<String, dynamic> cartData = {
"productQuantity": productQuantity,
};
Response response = await _dio.post(
placeOrderUrl,
options: Options(
headers: {
'Content-Type':
'application/x-www-form-urlencoded;charset=UTF-8;application/json;multipart/form-data',
'Accept': 'application/json',
"Authorization": "Bearer $finalToken",
},
),
data: jsonEncode(cartData),
);
} on DioError catch (e) {
debugPrint("Status code: ${e.response?.statusCode.toString()}");
throw Exception('Failed to place order');
}
}
Please how do i achieve this?
CodePudding user response:
as per my understanding you are trying to implement cart functionality , I hace explaind cart functionality here , you can check this , you may have to change model as per your requirement.
CodePudding user response:
I was able to achieve this partially by using the dart extension on funtion
which allowed me to iterate and merge the two lists. Now i get the instance of the list.
extension on List<ProductQuantity> {
void addProductQuantity({required int productID, required int quantity}) {
if (isNotEmpty) {
try {
var productWid = firstWhere((p) => p.productId == productID);
productWid.quantity == quantity;
} catch (e) {
add(ProductQuantity(productId: productID, quantity: quantity));
}
} else {
add(ProductQuantity(productId: productID, quantity: quantity));
}
}
}
Then i used a for loop
to get the individual productID and quantity of each cart item.
setState(() {
for (var i = 0; i < plist.length; i ) {
idInOrder = plist[i];
// debugPrint(plist[i].toString());
}
for (var i = 0; i < qt.length; i ) {
quantityInOrder = qt[i];
// debugPrint(qt[i].toString());
}
});
Then finally added the empty list _orderProductQuantity
to the extension on function
.
_orderProductQuantity.addProductQuantity(
productID: idInOrder,
quantity: quantityInOrder);
So the result becomes a combined list of:
[Instance of ProductQuantity]
which is where i am running into a problem because i only get one instance when i should have multiple instances. If you run jsonEncode(_orderProductQuantity)
the result will be ["{\"product_id\":11,\"quantity\":5}"]}
which is my end target. I will create another question to try and find a way to get multiple instances instead of just 1 instance. Will update after that.