From 0904abf774c6043782c6f1cede9a0559b8626290 Mon Sep 17 00:00:00 2001 From: bestonemitRam Date: Thu, 27 Feb 2025 16:26:08 +0530 Subject: [PATCH] cancelled product --- .DS_Store | Bin 10244 -> 10244 bytes .dart_tool/package_config.json | 2 +- .flutter-plugins-dependencies | 2 +- lib/src/core/constant/api.dart | 6 + lib/src/data/myOrder.dart | 9 + lib/src/data/order_OTP.dart | 32 +++ lib/src/logic/provider/order_provider.dart | 119 +++++++++- lib/src/logic/repo/order_repo.dart | 31 +++ lib/src/logic/services/orderSirvice.dart | 16 ++ lib/src/ui/myOrder/OrderDetailsScreen.dart | 258 +++++++++++++++------ lib/src/ui/myOrder/my_order.dart | 29 ++- 11 files changed, 409 insertions(+), 95 deletions(-) create mode 100644 lib/src/data/order_OTP.dart diff --git a/.DS_Store b/.DS_Store index 2d69e8ddab40db173ef79607b2df128c52649396..c34570ad11f58355199a7257244d05566fe14663 100644 GIT binary patch delta 239 zcmZn(XbIS0B*65?WO9Ol)MP&aF1BZ!c3%ItO^y>#LolUu3Nj3Xlk;;67(js007SAd z=rN=-WHOZGq$9~iwZEKvK|q47u(de>Xv{kSDHxMaP?{-~VY0U1Or~bT$;Sk97!xKN z3wbdY9b7%RK}bex@tT-lKerrn1RBl8kjPLBgsBWA48^(mDK1Gl`AI-=4v3n`$AsjW ziZ4ulE;LctR7b(k!njsPq1w>g#6(BI!qQ}Ow{Q$2(`TK@FGWHaCv3J8{m&1kjxhlM DD~nFm delta 239 zcmZn(XbIS0B*66FWO9Ol)MP&aE;hfwe>)y+nj9yfhG0tR6l53%C+FuDFn|DK0ElE^ z&|^qv$YdzVNk@{?dGdJj1px`R_=0KD_cu*`Cm;o5@(D^a85&I17M#iCKWp+a!5l_| z$;Lun%=$eQlN*F&w74Q{WGvPla|9aA#*oNR41}o+B@D&6`6(_*Ir&LIaSn)@$;X7` znG6~xKNp%PY^I}NXkk>Vqfl*VW@@OTU}<8pxm!4fk?BnQ + DeliveryOtpmodel.fromJson(json.decode(str)); + +String deliveryOtpmodelToJson(DeliveryOtpmodel data) => + json.encode(data.toJson()); + +class DeliveryOtpmodel { + String? code; + DateTime? expiresAt; + + DeliveryOtpmodel({ + this.code, + this.expiresAt, + }); + + factory DeliveryOtpmodel.fromJson(Map json) => + DeliveryOtpmodel( + code: json["code"], + expiresAt: DateTime.parse(json["expiresAt"]), + ); + + Map toJson() => { + "code": code, + "expiresAt": expiresAt!.toIso8601String(), + }; +} diff --git a/lib/src/logic/provider/order_provider.dart b/lib/src/logic/provider/order_provider.dart index 1f9fc43..aea695f 100644 --- a/lib/src/logic/provider/order_provider.dart +++ b/lib/src/logic/provider/order_provider.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:grocery_app/src/core/network_services/service_locator.dart'; import 'package:grocery_app/src/data/myOrder.dart'; import 'package:grocery_app/src/logic/repo/order_repo.dart'; +import 'package:grocery_app/utils/extensions/extensions.dart'; class OrderProvider extends ChangeNotifier { final _orderRepo = getIt(); @@ -22,7 +24,6 @@ class OrderProvider extends ChangeNotifier { }, (response) { orderList = response.data!; - isloading = false; notifyListeners(); @@ -32,9 +33,123 @@ class OrderProvider extends ChangeNotifier { print("sfddsfdfff $e"); isloading = false; - notifyListeners(); + notifyListeners(); } } + bool isSendOtp = false; + Future getAssignedOtp(BuildContext context, String assignmentId) async { + context.showLoader(show: true); + notifyListeners(); + var data = {"orderItemId": assignmentId}; + + print("ldflkgfkgjdh ${data}"); + + try { + var result = await _orderRepo.getAssignedOtp(data); + + return result.fold( + (error) { + context.showLoader(show: false); + }, + (response) { + _showOtpPopup(context, response.code!); // + + context.showLoader(show: false); + }, + ); + } catch (e) { + context.showLoader(show: false); + Fluttertoast.showToast( + msg: "Something went wrong", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.red, + textColor: Colors.white, + fontSize: 14.0, + ); + } + } + + void _showOtpPopup(BuildContext context, String otp) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Center(child: Text("Your OTP")), // Center the title + content: Column( + mainAxisSize: MainAxisSize.min, // Prevent excessive height + children: [ + Center( + child: Text( + otp, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.blue, + ), + ), + ), + ], + ), + actions: [ + Center( + child: TextButton( + onPressed: () => Navigator.pop(context), + child: Text("OK"), + ), + ), + ], + ), + ); + } + + Future updateStatus( + BuildContext context, String orderStatus, String orderItemId) async { + context.showLoader(show: true); + + var data = {"status": orderStatus, "comment": "string"}; + try { + var result = await _orderRepo.updateStatus(data, orderItemId); + + return result.fold( + (error) { + context.showLoader(show: false); + return false; + }, + (response) { + context.showLoader(show: false); + getMyOrder(context); + Fluttertoast.showToast( + msg: "Order cancelled successfully!", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.green, + textColor: Colors.white, + fontSize: 14.0, + ); + Navigator.pop(context); + + notifyListeners(); + + return true; + }, + ); + } catch (e) { + context.showLoader(show: false); + + print("lkjdgkfjhfdkg"); + + Fluttertoast.showToast( + msg: "Status already updated", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.red, + textColor: Colors.white, + fontSize: 14.0, + ); + + return false; + } + } } diff --git a/lib/src/logic/repo/order_repo.dart b/lib/src/logic/repo/order_repo.dart index 2d67e05..2ab7c41 100644 --- a/lib/src/logic/repo/order_repo.dart +++ b/lib/src/logic/repo/order_repo.dart @@ -3,6 +3,7 @@ import 'package:fpdart/fpdart.dart'; import 'package:grocery_app/src/core/utils/custom_dio_exception.dart'; import 'package:grocery_app/src/core/utils/response_type_def.dart'; import 'package:grocery_app/src/data/myOrder.dart'; +import 'package:grocery_app/src/data/order_OTP.dart'; import 'package:grocery_app/src/data/order_paymnet.dart'; import 'package:grocery_app/src/logic/services/orderSirvice.dart'; @@ -23,4 +24,34 @@ class OrderRepo { return left(error); } } + + FutureResult getAssignedOtp(data) async { + try { + var response = await _orderService.getAssignedOtp(data); + + DeliveryOtpmodel storeModel = + deliveryOtpmodelFromJson(response.toString()); + + //final String model = response.toString(); + return right(storeModel); + } on DioException catch (e) { + var error = CustomDioExceptions.handleError(e); + return left(error); + } + } + + FutureResult updateStatus(data, orderItemId) async { + try { + var response = await _orderService.updateStatus(data, orderItemId); + + final String model = response.toString(); + return right(model); + } on DioException catch (e) { + var error = CustomDioExceptions.handleError(e); + return left(error); + } + } + + + } diff --git a/lib/src/logic/services/orderSirvice.dart b/lib/src/logic/services/orderSirvice.dart index 50b7e74..8a15747 100644 --- a/lib/src/logic/services/orderSirvice.dart +++ b/lib/src/logic/services/orderSirvice.dart @@ -13,4 +13,20 @@ class OrderService extends ApiService return response; } + + Future getAssignedOtp(data) async { + var response = await api.get(APIURL.getAssignedOtp, + data: jsonEncode(data), queryParameters: data); + + return response; + } + + Future updateStatus(data, orderItemId) async { + var response = await api.patch( + APIURL.updateStatus + orderItemId + "/status", + data: jsonEncode(data)); + + return response; + } + } \ No newline at end of file diff --git a/lib/src/ui/myOrder/OrderDetailsScreen.dart b/lib/src/ui/myOrder/OrderDetailsScreen.dart index 8a2a3f6..749c379 100644 --- a/lib/src/ui/myOrder/OrderDetailsScreen.dart +++ b/lib/src/ui/myOrder/OrderDetailsScreen.dart @@ -1,7 +1,12 @@ +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; import 'package:grocery_app/src/common_widget/network_image.dart'; import 'package:grocery_app/src/data/myOrder.dart'; +import 'package:grocery_app/src/logic/provider/order_provider.dart'; +import 'package:grocery_app/utils/extensions/extensions.dart'; import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; class OrderDetailsScreen extends StatefulWidget { final Datum order; @@ -13,20 +18,16 @@ class OrderDetailsScreen extends StatefulWidget { } class _OrderDetailsScreenState extends State { - int currentStep = 1; String convertUtcToIst(String utcTime) { - // Parse the UTC time string DateTime utcDateTime = DateTime.parse(utcTime).toUtc(); - // Convert to IST (UTC +5:30) DateTime istDateTime = utcDateTime.add(const Duration(hours: 5, minutes: 30)); - // Format the IST datetime with AM/PM String formattedDateTime = DateFormat("dd-MM-yyyy hh:mm a").format(istDateTime); - return formattedDateTime; // Example: 11-02-2025 10:44 AM + return formattedDateTime; } @override @@ -34,17 +35,39 @@ class _OrderDetailsScreenState extends State { return Scaffold( appBar: AppBar(title: Text('Order Details')), body: Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _orderInfo(), - SizedBox(height: 20), - _animatedShippingTimeline(), - SizedBox(height: 20), + Container( + width: MediaQuery.of(context).size.width, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.order.orderNumber, + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.bold)), + SizedBox(height: 5), + Text(widget.order.deliveryAddress!.addressLine ?? " ", + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.bold)), + SizedBox(height: 5), + Text(convertUtcToIst(widget.order.createdAt.toString())), + SizedBox(height: 5), + // Text( + // "Status: ${_getStatusText(widget.order.orderStatus)}", + // style: TextStyle( + // color: Colors.blue, fontWeight: FontWeight.bold), + // ), + // _itemsList(), + ], + ), + ), + ), _itemsList(), SizedBox(height: 20), - //_cancelButton(), ], ), ), @@ -76,6 +99,7 @@ class _OrderDetailsScreenState extends State { style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold), ), + // _itemsList(), ], ), ), @@ -83,61 +107,73 @@ class _OrderDetailsScreenState extends State { ); } - /// Animated Shipping Timeline - Widget _animatedShippingTimeline() { - return Column( + final List statuses = [ + "PENDING", + "PROCESSING", + "SHIPPED", + "DELIVERED" + ]; + + Widget _animatedShippingTimeline(orderItemStatus) { + var currentStep = statuses.indexOf(orderItemStatus); + + return Row( + mainAxisAlignment: MainAxisAlignment.start, // Align items properly children: [ - for (int i = 0; i < 3; i++) _timelineStep(i), + for (int i = 0; i < statuses.length; i++) + _timelineStep(i, statuses[i], currentStep), ], ); } - /// Each Step in the Timeline - Widget _timelineStep(int step) { + Widget _timelineStep(int step, String status, currentStep) { bool isCompleted = step <= currentStep; return Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Column( - children: [ - AnimatedContainer( - duration: Duration(milliseconds: 500), - width: 20, - height: 20, - decoration: BoxDecoration( - color: isCompleted ? Colors.green : Colors.grey, - shape: BoxShape.circle, - ), - child: Icon(Icons.check, size: 14, color: Colors.white), - ), - if (step < 2) - AnimatedContainer( - duration: Duration(milliseconds: 500), - width: 5, - height: 50, - color: isCompleted ? Colors.green : Colors.grey, - ), - ], + AnimatedContainer( + duration: Duration(milliseconds: 500), + width: 15, + height: 15, + decoration: BoxDecoration( + color: isCompleted ? Colors.green : Colors.grey, + shape: BoxShape.circle, + ), + child: Icon(Icons.check, size: 12, color: Colors.white), ), - SizedBox(width: 10), + SizedBox(width: 5), Text( - _getStatusTextForStep(widget.order.orderStatus), - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + status, + style: TextStyle(fontSize: 10, fontWeight: FontWeight.bold), ), + if (step < statuses.length - 1) ...[ + SizedBox(width: 5), + AnimatedContainer( + duration: Duration(milliseconds: 500), + width: 20, + height: 3, + color: isCompleted ? Colors.green : Colors.grey, + ), + SizedBox(width: 5), + ], ], ); } - /// Status Texts +// PENDING PROCESSING SHIPPED DELIVERED CANCELLED RETURNED) + String _getStatusTextForStep(orderStatus) { switch (orderStatus) { case 'PENDING': return "PENDING"; case 'SHIPPED': return "SHIPPED"; - case 'DELIVERD': - return "DELIVERD"; + case 'PROCESSING': + return "PROCESSING"; + case 'DELIVERED': + return "DELIVERED"; + default: return ""; } @@ -165,22 +201,93 @@ class _OrderDetailsScreenState extends State { // final item = items[index]; var orderitem = widget.order.orderItems![index]; return Card( - margin: EdgeInsets.symmetric(vertical: 8), - child: ListTile( - leading: Container( - width: 50, - height: 50, - child: AppNetworkImage( - height: MediaQuery.of(context).size.height * 0.08, - width: 48, - imageUrl: orderitem.productImage ?? "", - backGroundColor: Colors.transparent, + margin: EdgeInsets.symmetric(vertical: 2), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (orderitem.orderItemStatus == "PENDING") + InkWell( + onTap: () async { + var status = await Provider.of( + context, + listen: false) + .updateStatus( + context, "CANCELLED", orderitem.id); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5, vertical: 5), + decoration: BoxDecoration( + color: Colors.green.shade100, + borderRadius: BorderRadius.circular(10), + ), + child: Text(" Cancel ", + style: TextStyle(color: Colors.black)), + ), + ), + Gap(5), + if (orderitem.orderItemStatus != "PENDING") + RichText( + text: TextSpan( + text: " ", + style: context.buttonTestStyle.copyWith( + color: context.appColor.blackColor, + ), + children: [ + TextSpan( + text: "GET OTP", + style: context.buttonTestStyle.copyWith( + color: Colors.blue, + decoration: TextDecoration.underline, + ), + recognizer: TapGestureRecognizer() + ..onTap = () { + Provider.of(context, + listen: false) + .getAssignedOtp(context, orderitem.id); + }, + ), + ], + ), + ), + ], + ), ), - ), - title: Text(orderitem.productName ?? ""), - subtitle: Text("Qty: ${orderitem.quantity.toString()}"), - trailing: Text("₹${orderitem.totalOrderItemPrice ?? ""}", - style: TextStyle(fontWeight: FontWeight.bold)), + ListTile( + leading: Container( + width: 50, + height: 50, + child: AppNetworkImage( + height: MediaQuery.of(context).size.height * 0.08, + width: 48, + imageUrl: orderitem.productImage ?? "", + backGroundColor: Colors.transparent, + ), + ), + title: Text(orderitem.productName ?? ""), + subtitle: Text("Qty: ${orderitem.quantity.toString()}"), + trailing: Text("₹${orderitem.totalOrderItemPrice ?? ""}", + style: TextStyle(fontWeight: FontWeight.bold)), + ), + if (orderitem.orderItemStatus == "CANCELLED") ...{ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Order Cancelled", + style: TextStyle( + color: Colors.black, fontWeight: FontWeight.bold)), + ) + } else ...{ + Padding( + padding: const EdgeInsets.all(8.0), + child: _animatedShippingTimeline(orderitem.orderItemStatus), + ), + } + ], ), ); }, @@ -188,21 +295,20 @@ class _OrderDetailsScreenState extends State { ); } - /// Cancel Order Button (Only if not delivered) - Widget _cancelButton() { - return ElevatedButton( - onPressed: currentStep < 2 - ? () { - setState(() { - currentStep = 2; // Simulate cancellation - }); - } - : null, // Disable if already delivered - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - disabledBackgroundColor: Colors.grey, - ), - child: Text("Cancel Order", style: TextStyle(color: Colors.white)), - ); - } + // Widget _cancelButton() { + // return ElevatedButton( + // onPressed: currentStep < 2 + // ? () { + // setState(() { + // currentStep = 2; + // }); + // } + // : null, + // style: ElevatedButton.styleFrom( + // backgroundColor: Colors.red, + // disabledBackgroundColor: Colors.grey, + // ), + // child: Text("Cancel Order", style: TextStyle(color: Colors.white)), + // ); + // } } diff --git a/lib/src/ui/myOrder/my_order.dart b/lib/src/ui/myOrder/my_order.dart index 565af21..0e7c54d 100644 --- a/lib/src/ui/myOrder/my_order.dart +++ b/lib/src/ui/myOrder/my_order.dart @@ -26,18 +26,15 @@ class _MyOrderScreenState extends State { } String convertUtcToIst(String utcTime) { - // Parse the UTC time string DateTime utcDateTime = DateTime.parse(utcTime).toUtc(); - // Convert to IST (UTC +5:30) DateTime istDateTime = utcDateTime.add(const Duration(hours: 5, minutes: 30)); - // Format the IST datetime with AM/PM String formattedDateTime = DateFormat("dd-MM-yyyy hh:mm a").format(istDateTime); - return formattedDateTime; // Example: 11-02-2025 10:44 AM + return formattedDateTime; } @override @@ -145,16 +142,16 @@ class _MyOrderScreenState extends State { ], ), Spacer(), - Container( - padding: EdgeInsets.symmetric( - horizontal: 5, vertical: 5), - decoration: BoxDecoration( - color: Colors.green.shade100, - borderRadius: BorderRadius.circular(10), - ), - child: Text(order.orderStatus, - style: TextStyle(color: Colors.green)), - ), + // Container( + // padding: EdgeInsets.symmetric( + // horizontal: 5, vertical: 5), + // decoration: BoxDecoration( + // color: Colors.green.shade100, + // borderRadius: BorderRadius.circular(10), + // ), + // child: Text(order.orderStatus, + // style: TextStyle(color: Colors.green)), + // ), ], ), SizedBox(height: 10), @@ -232,7 +229,9 @@ class _MyOrderScreenState extends State { ); } - Future _makePhoneCall(String number) async { + Future _makePhoneCall(String number) async + { + try { final Uri phoneUri = Uri(scheme: 'tel', path: number); if (await canLaunchUrl(phoneUri)) {