import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; import '../../../Controller/Orders/Ordercontroller.dart'; import '../../../Controller/products/product_controller.dart'; import '../../../Globalwidgets/textwidget.dart'; import '../../../Helper/Constants/Colorconstants.dart'; import '../../../Helper/Logger.dart'; import '../../../Model/Response/Summary/Getsummarysresponse.dart'; import '../../../widgets/product_bottom_sheet.dart'; import '../../Orders/Deliverydetails/delivery_detail_view.dart'; import '../Dashboardview.dart'; class OrderView extends StatelessWidget { const OrderView({super.key}); @override Widget build(BuildContext context) { final OrderController controller = Get.put(OrderController()); controller.getOrders('today'); return DefaultTabController( length: 4, child: Scaffold( appBar: AppBar( automaticallyImplyLeading: false, title: Obx(() { return controller.searchMode.value ? TextField( controller: controller.searchController, autofocus: true, decoration: InputDecoration( hintText: 'Search Orders', filled: true, fillColor: Colors.white, contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), suffixIcon: IconButton( icon: const Icon(Icons.close, color: ColorConstants.primaryColor), onPressed: () { controller.searchController.clear(); controller.searchMode.value = false; controller.search(''); }, ), ), onChanged: (value) { controller.search(value); }, ) : const TextWidget( text: 'Orders', fontWeight: FontWeight.w700, fontSize: 20, ); }), actions: [ /// Search icon — hidden when searchMode is ON Obx(() { if (controller.currentTabIndex.value == 3) { return SizedBox(); } return controller.searchMode.value ? SizedBox() // <- Hides extra close icon : IconButton( icon: const Icon(Icons.search, color: ColorConstants.primaryColor), onPressed: () { controller.searchMode.value = true; }, ); }), ], bottom: TabBar( indicatorColor: ColorConstants.primaryColor, labelColor: ColorConstants.primaryColor, unselectedLabelColor: ColorConstants.darkGreyColor, onTap: (index) { controller.currentTabIndex.value = index; switch (index) { case 0: controller.getOrders('today'); break; case 1: controller.getOrders('week'); break; case 2: controller.getOrders('month'); break; case 3: controller.getSummary(); break; } controller.searchMode.value = false; controller.searchController.clear(); controller.update(); }, tabs: const [ Tab(text: 'Today'), Tab(text: 'This Week'), Tab(text: 'This Month'), Tab(text: 'Summary'), ], ), ), body: Column( children: [ SizedBox(height: 10,), Expanded( child: TabBarView( physics: NeverScrollableScrollPhysics(), children: [ /// Today Tab OrderListView(controller: controller), /// Week Tab OrderListView(controller: controller), /// Month Tab OrderListView(controller: controller), /// Summary Tab GetBuilder( builder: (_) { return OrderInsightsGrid( total: controller.orderSummaryDetails.total ?? 0, pending: controller.orderSummaryDetails.pending ?? 0, delivered: controller.orderSummaryDetails.delivered ?? 0, cancelled: controller.orderSummaryDetails.cancelled ?? 0, ); }, ), ], ), ), ], ), ), ); } } /// Widget to display the list of orders class OrderListView extends StatelessWidget { final OrderController controller; OrderListView({super.key, required this.controller}); final ProductController productController = Get.put(ProductController()); @override Widget build(BuildContext context) { return GetBuilder( builder: (controller) { if (controller.isOrdersLoading.value) { return const Center(child: ShimmerListView(height: 180)); } final displayList = controller.searchMode.value ? controller.searchOrderList : controller.orderAllList; logger.i('orderAllList : ${controller.orderAllList}'); logger.i('SearchList : ${controller.searchOrderList}'); logger.i('DisplayList : ${displayList}'); return Column( children: [ // Visibility( // visible: controller.currentTabIndex.value != 3 && controller.orderAllList.isNotEmpty, // child: Padding( // padding: const EdgeInsets.all(12.0), // child: TextField( // controller: controller.searchController, // decoration: InputDecoration( // hintText: 'Search Orders', // filled: true, // fillColor: ColorConstants.secondaryColor, // border: OutlineInputBorder( // borderRadius: BorderRadius.circular(8.0), // ), // enabledBorder: OutlineInputBorder( // borderSide: BorderSide(color: Colors.grey.shade300), // borderRadius: BorderRadius.circular(8.0), // ), // focusedBorder: OutlineInputBorder( // borderSide: BorderSide( // color: ColorConstants.primaryColor, width: 2), // borderRadius: BorderRadius.circular(8.0), // ), // suffixIcon: Visibility( // visible: controller.searchController.text.isNotEmpty, // child: IconButton( // icon: const Icon( // Icons.cancel, // color: ColorConstants.primaryColor, // ), // onPressed: () { // controller.searchController.clear(); // controller.search(controller.searchController.text); // controller.searchMode.value = false; // FocusScope.of(context).unfocus(); // }, // ), // ), // ), // onChanged: (value) { // controller.search(value); // }, // ), // ), // ), Expanded( child: displayList.isEmpty && !controller.isOrdersLoading.value ? emptyOrdersWidget() : ListView.builder( itemCount: displayList.length, itemBuilder: (context, index) { final order = displayList[index]; logger.i('FinalOrder : ${order.orderid}'); return OrderListItem( order: order, controller: controller, index: index, ); }, ), ), ], ); }, ); } } /// Order List Items class OrderListItem extends StatelessWidget { final DeliveriesDetails order; final int index; final dynamic controller; OrderListItem({ Key? key, required this.order, required this.index, required this.controller, }) : super(key: key); final ProductController productController = Get.put(ProductController()); @override Widget build(BuildContext context) { // final currentOrder = controller.orderAllList[index]; logger.i('Current Order List : ${order.orderid}'); final date = order.deliverydate != "" ? DateFormat("yyyy-MM-dd'T'HH:mm:ss", "en_US").parse(order.deliverydate!) : null; final formattedDate = date != null ? DateFormat("dd MMM yyyy").format(date) : "--"; final time = date != null ? DateFormat("hh:mm a").format(date) : "--:--"; logger.i('Current Order : ${order.actualkms}'); return Card( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: InkWell( borderRadius: BorderRadius.circular(16), onTap: () async { final orderId = order.orderheaderid ?? 0; print("order id :${orderId}"); // Fetch products for this order await productController.getProductDetails(orderId); Get.to(() => OrderDetailsPage( productDetails: productController.productDetail, orderDetails: order, ) ); }, child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Order ID, Date, and Info Icon Row Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Order ID: ${order.orderid}", style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), const SizedBox(height: 4), Row( children: [ Text( formattedDate, style: const TextStyle( color: Colors.grey, fontSize: 13, ), ), const SizedBox(width: 5), Container( height: 10, width: 1, color: Colors.grey, ), const SizedBox(width: 5), Text( time, style: const TextStyle( color: Colors.grey, fontSize: 13, ), ), ], ), ], ), IconButton( padding: EdgeInsets.zero, icon: const Icon(Icons.info_outline, size: 20), onPressed: () async { final orderId = order.orderheaderid ?? 1; await productController.getProductDetails(orderId); if (context.mounted) { ProductBottomSheet.show(context, productController.productDetail, isAmountReceived: true); } }, ), ], ), const SizedBox(height: 12), // Distance Row Row( children: [ const Icon(Icons.delivery_dining, size: 20, color: Colors.orange), const SizedBox(width: 6), Text( "${order.actualkms != null && order.actualkms != 'null' ? order.actualkms : '0.0'} Km", style: const TextStyle(fontWeight: FontWeight.w500), ), ], ), const SizedBox(height: 12), // Rider and Customer Info Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Icon(Icons.person, size: 20, color: Colors.teal), const SizedBox(width: 6), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Rider: ${order.ridername ?? "Unknown"}", style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis, ), const SizedBox(height: 4), Text( "Customer: ${order.deliverycustomer ?? "Unknown"}", style: const TextStyle(fontSize: 14, color: Colors.grey), overflow: TextOverflow.ellipsis, ), ], ), ), ], ), const SizedBox(height: 10), // Payment and Status Row Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ const Icon(Icons.wallet, size: 20, color: Colors.green), const SizedBox(width: 6), Text( "₹ ${order.orderamount ?? 0}", style: const TextStyle(fontWeight: FontWeight.w600), ), ], ), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: _getStatusColor(order.orderstatus), borderRadius: BorderRadius.circular(12), ), child: Text( order.orderstatus?.toUpperCase() ?? "-", style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 13, color: Colors.white, ), ), ), ], ), ], ), ), ), ); } Color _getStatusColor(String? status) { switch (status) { case 'delivered': return Colors.green; case 'cancelled': return Colors.red; default: return Colors.orange; } } } class OrderInsightsGrid extends StatelessWidget { final int total; final int pending; final int delivered; final int cancelled; OrderInsightsGrid({ super.key, required this.total, required this.pending, required this.delivered, required this.cancelled, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), child: GridView.count( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisCount: 2, mainAxisSpacing: 16, crossAxisSpacing: 16, childAspectRatio: .70, children: [ _buildInsightCard( label: "Total Orders", count: total, icon: Icons.list_alt, color: Colors.blue, showChart: false, ), _buildInsightCard( label: "Pending", count: pending, percent: total > 0 ? pending / total : 0.0, icon: Icons.schedule, color: Colors.orange, ), _buildInsightCard( label: "Delivered", count: delivered, percent: total > 0 ? delivered / total : 0.0, icon: Icons.check_circle, color: Colors.green, ), _buildInsightCard( label: "Cancelled", count: cancelled, percent: total > 0 ? cancelled / total : 0.0, icon: Icons.cancel, color: Colors.red, ), ], ), ); } Widget _buildInsightCard({ required String label, required int count, double percent = 1.0, required IconData icon, required Color color, bool showChart = true, }) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), ), padding: const EdgeInsets.all(16), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if (showChart) SizedBox( height: 60, width: 60, child: CircularPercentIndicator( radius: 30, lineWidth: 5, percent: percent.clamp(0.0, 1.0), center: Icon(icon, color: color, size: 24), backgroundColor: color.withOpacity(0.1), progressColor: color, animation: true, ), ) else Icon(icon, color: color, size: 32), const SizedBox(height: 12), TextWidget( text: "$count", fontWeight: FontWeight.w700, color: color, fontSize: 20, ), const SizedBox(height: 6), TextWidget( text: label, fontSize: 16, textAlign: TextAlign.center, ), if (showChart) Padding( padding: const EdgeInsets.only(top: 4), child: TextWidget( text: "${(percent * 100).toStringAsFixed(1)}%", fontSize: 14, color: ColorConstants.darkGreyColor?.withOpacity(0.5), fontWeight: FontWeight.w700, ), ), ], ), ); } }