import 'package:country_currency_pickers/currency_picker_cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:rounded_loading_button_plus/rounded_loading_button.dart'; import 'package:timeline_tile/timeline_tile.dart'; import '../../Controller/Dashboard/Tabs/Ordercontroller.dart'; import '../../Globalwidgets/textwidget.dart'; import '../../Helper/Constants/Colorconstants.dart'; import '../../Helper/Logger.dart'; import '../../Model/Response/Orders/Getorderresponse.dart'; import '../../Model/Response/products/product_info.dart'; import '../Rider/rider_assign.dart'; class OrderDetailsPage extends StatelessWidget { final OrderDetails orderDetails; final List productDetails; final CurrentOrderController controller; const OrderDetailsPage({ super.key, required this.productDetails, required this.orderDetails, required this.controller, }); @override Widget build(BuildContext context) { double totalAmount = 0; double totalTax = 0; for (var product in productDetails) { totalAmount = product.productsumprice ?? 0.0; totalTax += product.taxamount ?? 0.0; } final totalWithTax = totalAmount + totalTax; final DateTime dateTime = DateTime.parse(orderDetails.orderdate ?? ''); final String formattedDate = DateFormat('dd-MM-yy').format(dateTime); final String formattedTime = DateFormat('hh:mm a').format(dateTime); logger.i('Order Status : ${orderDetails.orderstatus}'); return SafeArea( top: false, child: Scaffold( appBar: AppBar( automaticallyImplyLeading: true, title: TextWidget( text: 'Order Details', fontSize: 20, fontWeight: FontWeight.w700, ), backgroundColor: ColorConstants.secondaryColor, leading: InkWell( onTap: () { Get.back(); }, child: Icon( Icons.arrow_back, color: ColorConstants.blackColor, ) ), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _sectionCard( icon: Icons.receipt_long, title: "Order Info", children: [ _infoRow("Order ID", orderDetails.orderid ?? ''), _infoRow("Date", "${formattedDate}"), _infoRow("Time", "${formattedTime}"), ], ), const SizedBox(height: 12), _sectionCard( icon: Icons.shopping_cart, title: "Products", children: [ // List of products ...productDetails.map((product) => Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(child: Text("${product.productname} x${product.orderqty}")), Text( "₹${((product.price ?? 0.0) * (product.orderqty ?? 1)).toStringAsFixed(2)}", style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.black87, ), ), ], ), )), const Divider(height: 24), // Additional totals _infoRow("Amount", "₹${totalAmount.toStringAsFixed(2)}", isForProducts: true), _infoRow("Tax", "₹${totalTax.toStringAsFixed(2)}", isForProducts: true), _infoRow( "Total", "₹${totalWithTax.toStringAsFixed(2)}", isForProducts: true ), ], ), const SizedBox(height: 12), _sectionCard( icon: Icons.person, title: "Customer", children: [ _infoRow("Name", orderDetails.deliverycustomer ?? ''), _infoRow("Address", orderDetails.deliveryaddress ?? ''), _infoRow("Phone", orderDetails.deliverycontactno ?? ''), ], ), const SizedBox(height: 12), Visibility( visible: orderDetails.rider?.isNotEmpty ?? false, child: _sectionCard( icon: Icons.delivery_dining, title: "Rider", children: [ _infoRow("Name", orderDetails.rider ?? ''), _infoRow("Phone", orderDetails.ridercontactno ?? ''), ], ), ), const SizedBox(height: 12), SizedBox( height: 200, child: OrderStatusTimeline( stages: [ Stage( label: "Accepted", icon: Icons.check, completed: orderDetails.starttime?.isNotEmpty ?? false, time: convertTo12HourFormat(orderDetails.starttime ?? '', ), ), Stage( label: "Arrived", icon: Icons.location_on, completed: orderDetails.arrivaltime?.isNotEmpty ?? false, time: convertTo12HourFormat(orderDetails.arrivaltime ?? '', ), ), Stage( label: "Picked", icon: Icons.shopping_bag, completed: orderDetails.pickuptime?.isNotEmpty ?? false, time: convertTo12HourFormat(orderDetails.pickuptime ?? '') ), Stage( label: "Delivered", icon: Icons.delivery_dining, completed:orderDetails.deliverytime?.isNotEmpty ?? false, time: convertTo12HourFormat(orderDetails.deliverytime ?? '') ), ], ), ), const SizedBox(height: 12), ], ), ), bottomNavigationBar: orderDetails.orderstatus == 'cancelled' || orderDetails.orderstatus == 'delivered' ? SizedBox() : SafeArea( child: SizedBox( height: 80, child: Padding( padding: const EdgeInsets.only(left: 14,right: 14), child: Row( children: [ Visibility( visible: (orderDetails.orderstatus == 'pending' || orderDetails.orderstatus == 'created') , child: Expanded( child: RoundedLoadingButton( controller: controller.cancelOrderButton, color: Colors.red, onPressed: () { showCancelOrderDialog( context, () { controller.declineOrder( orderDetails.orderheaderid, orderDetails.orderid, orderDetails.customertoken, orderDetails.ridertoken, ); }, ); }, child: TextWidget( text: 'Cancel', fontSize: 15, fontWeight: FontWeight.w700, color: ColorConstants.secondaryColor, ) ) ), ), const SizedBox(width: 16), Visibility( visible: orderDetails.orderstatus == 'created', child: Expanded( child: RoundedLoadingButton( controller: controller.acceptOrderButton, color: Colors.green, onPressed: () { Get.to(() => ReassignRidersView(deliveryDetails: orderDetails)); controller.acceptOrderButton.reset(); }, child: TextWidget( text: 'Accept', fontSize: 15, fontWeight: FontWeight.w700, color: ColorConstants.secondaryColor, ), ), ), ), ], ), ), ), ), ), ); } /// Alert dialog for the Cancel Order void showCancelOrderDialog(BuildContext context, VoidCallback onConfirm) { controller.cancelOrderButton.reset(); showDialog( context: context, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), title: const TextWidget( text: 'Cancel Order', fontWeight: FontWeight.w700, fontSize: 18, ), content: const TextWidget(text: 'Would you like to cancel this order?', fontSize: 14,), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const TextWidget(text: 'No'), ), ElevatedButton( style: ButtonStyle( backgroundColor: WidgetStateProperty.all(Colors.red), foregroundColor: WidgetStateProperty.all(ColorConstants.secondaryColor), ), onPressed: () { Navigator.of(context).pop(); onConfirm(); }, child: TextWidget( text: 'Yes, Cancel' , color: ColorConstants.secondaryColor, fontWeight: FontWeight.w700, ), ), ], ); }, ); } Widget _sectionCard({ required IconData icon, required String title, String? Amount, String? TaxAmount, String? Total, required List children, }) { return Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: ColorConstants.secondaryColor, borderRadius: BorderRadius.circular(12), // boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 4)], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(icon, size: 20, color: ColorConstants.primaryColor), const SizedBox(width: 8), Text(title, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16)), ], ), const Divider(), ...children, ], ), ); } Widget _infoRow(String label, String value, {bool? isForProducts}) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 100, // fixed width for label child: Text( label, style: const TextStyle(color: Colors.black54), ), ), (isForProducts ?? false) ? Spacer() : const SizedBox(width: 8), (isForProducts ?? false) ? Text( value, style: const TextStyle(fontWeight: FontWeight.w500), maxLines: 3, // Allow wrapping for address overflow: TextOverflow.ellipsis, ) : Expanded( child: Text( value, style: const TextStyle(fontWeight: FontWeight.w500), maxLines: 3, // Allow wrapping for address overflow: TextOverflow.ellipsis, ), ), ], ), ); } showBottomSheet(BuildContext context, {required VoidCallback onAccept}) { showModalBottomSheet( context: context, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)), ), builder: (BuildContext context) { return Container( padding: EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Optional: Add a handle or title Center( child: Container( width: 40, height: 5, margin: EdgeInsets.symmetric(vertical: 8.0), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(2.5), ), ), ), SizedBox(height: 16.0), Text( 'Confirm Order', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), SizedBox(height: 16.0), Text( 'Accept this order and assign a rider?', style: TextStyle(fontSize: 16), textAlign: TextAlign.center, ), SizedBox(height: 24.0), // Buttons Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( child: ElevatedButton( onPressed: () { // Handle Cancel action Navigator.pop(context); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[300], foregroundColor: Colors.black, padding: EdgeInsets.symmetric(vertical: 16.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), child: TextWidget( text: 'Cancel' ), ), ), SizedBox(width: 16.0), Expanded( child: ElevatedButton( onPressed: () { // Handle Accept action onAccept(); // Add your accept logic here }, style: ElevatedButton.styleFrom( backgroundColor: ColorConstants.primaryColor, padding: EdgeInsets.symmetric(vertical: 16.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), child: TextWidget( text: 'Accept', color: ColorConstants.secondaryColor, ), ), ), ], ), SizedBox(height: 16.0), ], ), ); }); } } class OrderStatusTimeline extends StatelessWidget { final List stages; const OrderStatusTimeline({super.key, required this.stages}); @override Widget build(BuildContext context) { return Container( width: double.infinity, padding: const EdgeInsets.all(5), decoration: BoxDecoration( color: ColorConstants.secondaryColor, borderRadius: BorderRadius.circular(12), // boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 4)], ), child: Padding( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title const Padding( padding: EdgeInsets.only(left: 12, bottom: 8), child: Text( 'Order Status', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), const Divider(), // Horizontal Timeline SingleChildScrollView( scrollDirection: Axis.horizontal, child: SizedBox( height: 100, child: Row( children: List.generate(stages.length, (index) { final isFirst = index == 0; final isLast = index == stages.length - 1; final stage = stages[index]; return TimelineTile( axis: TimelineAxis.horizontal, alignment: TimelineAlign.center, isFirst: isFirst, isLast: isLast, beforeLineStyle: LineStyle( color: stage.completed ? Colors.green : Colors.grey.shade400, thickness: 2, ), afterLineStyle: LineStyle( color: stage.completed ? Colors.green : Colors.grey.shade400, thickness: 2, ), indicatorStyle: IndicatorStyle( width: 30, height: 30, indicator: Container( decoration: BoxDecoration( color: stage.completed ? Colors.green : Colors.grey.shade400, shape: BoxShape.circle, ), child: Icon( stage.icon, color: Colors.white, size: 16, ), ), ), endChild: Container( margin: const EdgeInsets.only(top: 8), padding: const EdgeInsets.symmetric(horizontal: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Text( stage.label, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: stage.completed ? Colors.black : Colors.grey, ), textAlign: TextAlign.center, ), ), if (stage.time != null) Expanded( child: Text( stage.time!, style: const TextStyle( fontSize: 11, color: Colors.black54, ), textAlign: TextAlign.center, ), ), ], ), ), ); }), ), ), ), ], ), ), ); } } class Stage { final String label; final IconData icon; final bool completed; final String? time; Stage({ required this.label, required this.icon, this.completed = false, this.time, }); } String convertTo12HourFormat(String dateTimeString) { logger.i('Convert This into 12 : ${dateTimeString}'); // Check if input is empty if (dateTimeString.isEmpty) { return ''; } // Parse the input string to DateTime DateTime dateTime = DateTime.parse(dateTimeString); // Get hour and minute int hour = dateTime.hour; int minute = dateTime.minute; // Determine AM/PM String period = hour >= 12 ? 'PM' : 'AM'; // Convert to 12-hour format hour = hour % 12; if (hour == 0) hour = 12; // Format minute to always show two digits String minuteStr = minute.toString().padLeft(2, '0'); return '$hour:$minuteStr $period'; }