From 0bdaa99c55036b0ec7d286a2c4781290aaf49d12 Mon Sep 17 00:00:00 2001 From: Sneha Date: Wed, 25 Feb 2026 12:07:23 +0530 Subject: [PATCH] changes --- lib/common/settings.dart | 24 +++++- lib/plans/calendar.dart | 156 ++++++++++++++++++++++-------------- lib/plans/plan_details.dart | 123 +++++++++++++++++----------- 3 files changed, 194 insertions(+), 109 deletions(-) diff --git a/lib/common/settings.dart b/lib/common/settings.dart index 6bd9c19..4cc341c 100644 --- a/lib/common/settings.dart +++ b/lib/common/settings.dart @@ -187,7 +187,9 @@ class AppSettings{ static String acceptAdvanceFromCustomerUrl = host + 'advance/confirm'; static String getAdvanceTransactionsBySupplierAndCustomerUrl = host + 'advance/transactions'; static String respondRecurringBookingUrl = host + 'customer/recurring/respond'; - static String getSupplierBookingsUrl = host + 'getsupplierbookings'; + static String getSupplierBookingsUrl = host + 'getuserRequestbookingsforplansforsupplier'; + static String recurringDateActionUrl = host + 'recurring-booking/date-action'; + @@ -1424,6 +1426,26 @@ class AppSettings{ } } + static Future recurringDateAction( + String bookingId, + Map payload, + ) async { + + final url = Uri.parse("$recurringDateActionUrl/${bookingId}"); + + + final response = await http.post( + url, + headers: await buildRequestHeaders(), + body: jsonEncode(payload), + ); + + if (response.statusCode != 200) { + throw Exception( + "Recurring date action failed: ${response.body}", + ); + } + } /*Apis ends here*/ diff --git a/lib/plans/calendar.dart b/lib/plans/calendar.dart index 711e38d..142c68f 100644 --- a/lib/plans/calendar.dart +++ b/lib/plans/calendar.dart @@ -18,6 +18,56 @@ class _SupplierCalendarState extends State { bool isLoading = true; + Future cancelSingleDate(Map delivery) async { + try { + await AppSettings.recurringDateAction( + delivery["_id"], + { + "action": "cancel", + "date": delivery["date"], // IMPORTANT + "reason": "Cancelled by supplier", + }, + ); + + await fetchOrdersFromApi(); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Delivery cancelled successfully")), + ); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Cancel failed")), + ); + } + } + + Future rescheduleSingleDate( + Map delivery, + String newDate, + ) async { + try { + await AppSettings.recurringDateAction( + delivery["_id"], + { + "action": "reschedule", + "date": delivery["date"], // original date + "new_date": newDate, // selected date + "reason": "Rescheduled by supplier", + }, + ); + + await fetchOrdersFromApi(); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Delivery rescheduled")), + ); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Reschedule failed")), + ); + } + } + @override void initState() { super.initState(); @@ -49,66 +99,48 @@ class _SupplierCalendarState extends State { calendarEvents.clear(); for (var order in orders) { - String? originalDate = order["date"]; - String? newDate = order["reScheduleDateOfDelivery"]; - String? resStatus = order["rescheduleOrderStatus"]; - - bool isRescheduled = - newDate != null && newDate.isNotEmpty && resStatus != null && resStatus.isNotEmpty; - - // ===================== ORIGINAL DATE EVENT ===================== - if (originalDate != null && order["orderStatus"] != "cancelled") { - try { - DateTime d = DateTime.parse(originalDate); - DateTime key = DateTime(d.year, d.month, d.day); - - calendarEvents.putIfAbsent(key, () => []); - calendarEvents[key]!.add({ - "status": isRescheduled ? "rescheduled_from" : "delivery", - "_id": order["_id"], - "supplierName": order["supplierName"] ?? "Supplier", - "capacity": order["capacity"] ?? "", - "time": order["time"] ?? "", - "originalDate": originalDate, - "newDate": newDate, - }); - } catch (e) {} - } - - // ===================== NEW RESCHEDULED DATE EVENT ===================== - if (isRescheduled) { - try { - DateTime d2 = DateTime.parse(newDate); - DateTime key2 = DateTime(d2.year, d2.month, d2.day); - - calendarEvents.putIfAbsent(key2, () => []); - calendarEvents[key2]!.add({ - "status": "rescheduled_to", - "_id": order["_id"], - "supplierName": order["supplierName"] ?? "Supplier", - "capacity": order["capacity"] ?? "", - "time": order["time"] ?? "", - "originalDate": originalDate, - "newDate": newDate, - }); - } catch (e) {} - } - - // ===================== CANCELLED EVENT ===================== - if (order["orderStatus"] == "cancelled") { - try { - DateTime d = DateTime.parse(originalDate!); - DateTime key = DateTime(d.year, d.month, d.day); - - calendarEvents.putIfAbsent(key, () => []); - calendarEvents[key]!.add({ - "status": "cancelled", - "_id": order["_id"], - "supplierName": order["supplierName"] ?? "Supplier", - "capacity": order["capacity"] ?? "", - "time": order["time"] ?? "", - }); - } catch (e) {} + final String capacity = order["capacity"] ?? ""; + final String time = order["time"] ?? ""; + final String bookingStatus = order["booking_status"] ?? ""; + final String supplierName = + order["customer_details"]?["profile"]?["username"] ?? "Customer"; + + final List dates = order["dates"] ?? []; + + for (var d in dates) { + final String? dateStr = d["date"]; + if (dateStr == null) continue; + + DateTime date = DateTime.parse(dateStr); + DateTime key = DateTime(date.year, date.month, date.day); + + calendarEvents.putIfAbsent(key, () => []); + + // ---------------- STATUS LOGIC ---------------- + String status = "delivery"; + + if (d["status"] == "rescheduled") { + status = "rescheduled_from"; + } + + if (d["rescheduled_from"] != null) { + status = "rescheduled_to"; + } + + if (d["status"] == "cancelled") { + status = "cancelled"; + } + + calendarEvents[key]!.add({ + "status": status, + "_id": order["_id"], + "supplierName": supplierName, + "capacity": capacity, + "time": time, + "date": dateStr, + "originalDate": d["rescheduled_from"], + "newDate": d["rescheduled_to"], + }); } } @@ -118,6 +150,7 @@ class _SupplierCalendarState extends State { } } + // =========================================================================== // CANCEL ORDER API // =========================================================================== @@ -219,6 +252,7 @@ class _SupplierCalendarState extends State { String formatted = "${pickedDate.year}-${pickedDate.month.toString().padLeft(2,'0')}-${pickedDate.day.toString().padLeft(2,'0')}"; + await rescheduleSingleDate(delivery, formatted); //await sendRescheduleToServer(delivery["_id"], formatted); } @@ -379,7 +413,7 @@ class _SupplierCalendarState extends State { title: Text("Cancel Delivery"), onTap: () { Navigator.pop(context); - // _confirmCancel(delivery["_id"]); + cancelSingleDate(delivery); }, ), ], diff --git a/lib/plans/plan_details.dart b/lib/plans/plan_details.dart index e1deedc..8a00db9 100644 --- a/lib/plans/plan_details.dart +++ b/lib/plans/plan_details.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import '../common/settings.dart'; class PlanDetails extends StatefulWidget { - final Map plan; // 🔥 pass full plan object + final Map plan; const PlanDetails({super.key, required this.plan}); @@ -11,14 +11,19 @@ class PlanDetails extends StatefulWidget { } class _PlanDetailsState extends State { - late List deliveryDates; + late List> deliveryDates; @override void initState() { super.initState(); - deliveryDates = (widget.plan["dates"] as List) - .map((d) => DateTime.parse(d)) - .toList(); + + // 🔥 Now expecting: + // "dates": [ + // { "date": "2026-02-10", "status": "scheduled" } + // ] + + deliveryDates = + List>.from(widget.plan["dates"] ?? []); } // ================= INFO CARD ================= @@ -36,8 +41,7 @@ class _PlanDetailsState extends State { style: fontTextStyle(18, Colors.black, FontWeight.w600)), const SizedBox(height: 4), Text(label, - style: - fontTextStyle(13, Colors.black54, FontWeight.w400)), + style: fontTextStyle(13, Colors.black54, FontWeight.w400)), ], ), ), @@ -45,22 +49,12 @@ class _PlanDetailsState extends State { } // ================= DELIVERY CARD ================= - Widget _buildDeliveryCard(DateTime date) { - final now = DateTime.now(); - String status; + Widget _buildDeliveryCard(Map delivery) { + DateTime date = DateTime.parse(delivery["date"]); + String status = delivery["status"] ?? "scheduled"; + String buttonText = ""; - bool showButton = true; - - if (date.isBefore(now)) { - status = "completed"; - showButton = false; - } else if (date.difference(now).inHours < 24) { - status = "in-progress"; - buttonText = "Track Order"; - } else { - status = "pending"; - buttonText = "Assign Tanker"; - } + bool showButton = false; Color statusBg; Color statusText; @@ -70,13 +64,26 @@ class _PlanDetailsState extends State { statusBg = Colors.green.withOpacity(0.15); statusText = Colors.green; break; + + case "rescheduled": + statusBg = Colors.purple.withOpacity(0.15); + statusText = Colors.purple; + buttonText = "View Details"; + showButton = true; + break; + case "in-progress": statusBg = Colors.blue.withOpacity(0.15); statusText = Colors.blue; + buttonText = "Track Order"; + showButton = true; break; - default: + + default: // scheduled statusBg = Colors.orange.withOpacity(0.15); statusText = Colors.orange; + buttonText = "Assign Tanker"; + showButton = true; } return Container( @@ -100,15 +107,16 @@ class _PlanDetailsState extends State { borderRadius: BorderRadius.circular(8), ), child: Text( - status, - style: fontTextStyle(12, statusText, FontWeight.w600), + status.toUpperCase(), + style: + fontTextStyle(12, statusText, FontWeight.w600), ), ), const Spacer(), Text( "${date.day}-${date.month}-${date.year}", - style: - fontTextStyle(12, Colors.black54, FontWeight.w400), + style: fontTextStyle( + 12, Colors.black54, FontWeight.w400), ), ], ), @@ -118,7 +126,7 @@ class _PlanDetailsState extends State { style: fontTextStyle(14, Colors.black, FontWeight.w600), ), const SizedBox(height: 10), - /* if (showButton) + if (showButton) Align( alignment: Alignment.centerRight, child: ElevatedButton( @@ -135,7 +143,7 @@ class _PlanDetailsState extends State { fontTextStyle(13, Colors.white, FontWeight.w600), ), ), - )*/ + ), ], ), ); @@ -147,8 +155,14 @@ class _PlanDetailsState extends State { final plan = widget.plan; final int totalDeliveries = deliveryDates.length; - final int pendingCount = - deliveryDates.where((d) => d.isAfter(DateTime.now())).length; + + final int pendingCount = deliveryDates + .where((d) => d["status"] == "scheduled") + .length; + + final int rescheduledCount = deliveryDates + .where((d) => d["status"] == "rescheduled") + .length; return Scaffold( backgroundColor: Colors.white, @@ -156,7 +170,8 @@ class _PlanDetailsState extends State { backgroundColor: Colors.white, elevation: 0, leading: IconButton( - icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black), + icon: + const Icon(Icons.arrow_back_ios_new, color: Colors.black), onPressed: () => Navigator.pop(context), ), title: Text( @@ -202,8 +217,8 @@ class _PlanDetailsState extends State { Column( children: [ Text(plan["customerId"], - style: - fontTextStyle(18, Colors.black, FontWeight.w600)), + style: fontTextStyle( + 18, Colors.black, FontWeight.w600)), const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.center, @@ -213,7 +228,8 @@ class _PlanDetailsState extends State { const SizedBox(width: 4), Text(plan["type_of_water"], style: fontTextStyle( - 14, const Color(0xFF8270DB), + 14, + const Color(0xFF8270DB), FontWeight.w500)), ], ), @@ -230,7 +246,8 @@ class _PlanDetailsState extends State { // INFO ROWS Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: + const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ _buildInfoCard(plan["capacity"], "Quantity"), @@ -247,14 +264,17 @@ class _PlanDetailsState extends State { const SizedBox(height: 16), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: + const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ - _buildInfoCard("${plan["weekly_count"]}/week", "Schedule"), + _buildInfoCard( + "${plan["weekly_count"]}/week", "Schedule"), const SizedBox(width: 12), _buildInfoCard("$pendingCount", "Pending"), const SizedBox(width: 12), - _buildInfoCard("0", "Rescheduled"), + _buildInfoCard( + "$rescheduledCount", "Rescheduled"), ], ), ), @@ -268,7 +288,8 @@ class _PlanDetailsState extends State { // BOTTOM BUTTONS Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: + const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ Expanded( @@ -278,14 +299,17 @@ class _PlanDetailsState extends State { side: const BorderSide( color: Color(0xFF8270DB)), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(24), + borderRadius: + BorderRadius.circular(24), ), padding: - const EdgeInsets.symmetric(vertical: 14), + const EdgeInsets.symmetric( + vertical: 14), ), child: Text( "Edit Plan", - style: fontTextStyle(14, + style: fontTextStyle( + 14, const Color(0xFF8270DB), FontWeight.w600), ), @@ -296,17 +320,22 @@ class _PlanDetailsState extends State { child: ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFFE2483D), + backgroundColor: + const Color(0xFFE2483D), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(24), + borderRadius: + BorderRadius.circular(24), ), padding: - const EdgeInsets.symmetric(vertical: 14), + const EdgeInsets.symmetric( + vertical: 14), ), child: Text( "Discontinue", style: fontTextStyle( - 14, Colors.white, FontWeight.w600), + 14, + Colors.white, + FontWeight.w600), ), ), ),