diff --git a/images/square_avatar.png b/images/square_avatar.png new file mode 100644 index 0000000..ee484f9 Binary files /dev/null and b/images/square_avatar.png differ diff --git a/lib/common/settings.dart b/lib/common/settings.dart index 6191772..c7f28d8 100644 --- a/lib/common/settings.dart +++ b/lib/common/settings.dart @@ -164,6 +164,8 @@ class AppSettings{ static String setRatesDailyUrl = host + 'tankers'; static String getSupplierDetailsUrl = host + 'suppliers'; static String updatePumpFeeUrl = host + 'suppliers'; + static String assignTankerUrl = host + 'suppliers'; + static String formDouble(dynamic s) { @@ -738,6 +740,30 @@ class AppSettings{ } } + static Future assignTanker(payload,dbId) async { + + var uri = Uri.parse(assignTankerUrl+'/'+dbId+'/supplier/assigntanker'); + + var response = await http.put(uri, body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.put(uri,body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + /*Apis ends here*/ diff --git a/lib/orders/assign_driver.dart b/lib/orders/assign_driver.dart index cfb0bb0..6ceb831 100644 --- a/lib/orders/assign_driver.dart +++ b/lib/orders/assign_driver.dart @@ -70,254 +70,10 @@ class _AssignDriverScreenState extends State { } } - - - void _showAssignDriverBottomSheet() { - int? selectedDriverIndex; // ✅ Track selected driver - - showModalBottomSheet( - context: context, - isScrollControlled: true, - isDismissible: false, - enableDrag: false, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - builder: (context) { - return WillPopScope( // ✅ block Android back button - onWillPop: () async => false, - child: StatefulBuilder( - builder: (context, setModalState) { - return DraggableScrollableSheet( - expand: false, - initialChildSize: 0.7, - minChildSize: 0.5, - maxChildSize: 0.9, - builder: (context, scrollController) { - return Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Container( - width: 60, - height: 4, - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: const Color(0xFFE0E0E0), - borderRadius: BorderRadius.circular(2), - ), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Assign Driver", - style: fontTextStyle(16, const Color(0XFF2A2A2A), FontWeight.w600), - ), - GestureDetector( - onTap: (){ - Navigator.pop(context); - }, - child: Image.asset('images/cross.png', height: 24, width: 24,color: Color(0XFF2A2A2A),), - ) - ], - ), - const SizedBox(height: 16), - - // 🏢 Order Info - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white, - border: Border.all(color: const Color(0XFFC9C2F0), width: 0.5), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.order.building_name, - style: fontTextStyle(20, const Color(0XFF2D2E30), FontWeight.w600), - ), - Text( - widget.order.displayAddress, - style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400), - ), - ], - ), - const Spacer(), - Text( - '${widget.order.distanceInKm} Km', - style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400), - ), - ], - ), - ), - const SizedBox(height: 16), - - Text( - "SELECT DRIVER", - style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600), - ), - const SizedBox(height: 12), - - // 🧍 Driver List - Expanded( - child: isLoading - ? const Center(child: CircularProgressIndicator()) - : ListView.separated( - controller: scrollController, - itemCount: driversList.length, - separatorBuilder: (_, __) => const SizedBox(height: 12), - itemBuilder: (context, idx) { - final d = driversList[idx]; - final bool isSelected = selectedDriverIndex == idx; - final bool isAvailable = d.status == "available"; - - final statusColor = isAvailable - ? const Color(0XFF0A9E04) - : (d.status == "on delivery" - ? const Color(0XFFD0AE3C) - : (d.status == "offline" - ? const Color(0XFF939495) - : Colors.grey)); - - return GestureDetector( - onTap: () { - if (isAvailable) { // ✅ only selectable if available - setModalState(() { - selectedDriverIndex = idx; - }); - } else { - AppSettings.longFailedToast( - 'Only available drivers can be selected', - ); - } - }, - child: Opacity( - opacity: isAvailable ? 1 : 1, // 👈 grey out non-available - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide( - color: isSelected - ? const Color(0XFF8270DB) - : const Color(0XFFC3C4C4), - width: 1, - ), - ), - color: isSelected - ? const Color(0XFFEDEBFF) - : Colors.white, - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - children: [ - Image.asset( - 'images/avatar.png', - fit: BoxFit.cover, - width: 20, - height: 20, - ), - SizedBox( - width: MediaQuery.of(context).size.width * .016), - Expanded( - child: Text( - d.driver_name, - style: fontTextStyle( - 14, - const Color(0XFF2D2E30), - FontWeight.w500, - ), - ), - ), - SizedBox( - width: MediaQuery.of(context).size.width * .016), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, vertical: 2), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - border: Border.all(color: statusColor), - ), - child: Text( - d.status, - style: fontTextStyle( - 10, - statusColor, - FontWeight.w400, - ), - ), - ), - ], - ), - ), - ), - ), - ); - }, - ), - ), - - const SizedBox(height: 16), - - // 🟣 Assign Button - SizedBox( - width: double.infinity, - child: GestureDetector( - onTap: () async { - if (selectedDriverIndex == null) { - AppSettings.longFailedToast('Please select driver'); - return; - } - - final selectedDriver = driversList[selectedDriverIndex!]; - - // ✅ Call your API here - // await _assignDriverApi(selectedDriver.driver_id); - - if (context.mounted) Navigator.pop(context); - }, - child: Container( - decoration: BoxDecoration( - color: const Color(0XFF8270DB), - borderRadius: BorderRadius.circular(24), - ), - alignment: Alignment.center, - padding: const EdgeInsets.symmetric(vertical: 12), - child: Text( - 'Assign', - style: fontTextStyle( - 14, const Color(0XFFFFFFFF), FontWeight.w500), - ), - ), - ), - ), - ], - ), - ); - }, - ); - }, - ),); - }, - ); - } - void _showAssignTankerBottomSheet() { - int? selectedTankerIndex; // ✅ Track selected tanker + int? selectedTankerIndex; + int? selectedDriverIndex; - // 🔹 Helper function to normalize capacity values int _capToLiters(dynamic cap) { if (cap == null) return -1; if (cap is num) return cap.round(); @@ -328,19 +84,16 @@ class _AssignDriverScreenState extends State { final n = double.tryParse(match.group(1)!) ?? -1; if (n < 0) return -1; - - // If string contains "kl" -> convert KL to Liters if (s.contains('kl')) return (n * 1000).round(); - - // Otherwise already in liters return n.round(); } showModalBottomSheet( + backgroundColor: const Color(0XFFFFFFFF), context: context, isScrollControlled: true, isDismissible: false, - enableDrag: false, + enableDrag: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), @@ -349,158 +102,302 @@ class _AssignDriverScreenState extends State { onWillPop: () async => false, child: StatefulBuilder( builder: (context, setModalState) { - return DraggableScrollableSheet( - expand: false, - initialChildSize: 0.7, - minChildSize: 0.5, - maxChildSize: 0.9, - builder: (context, scrollController) { - final requiredLiters = _capToLiters(widget.order.capacity); - final filteredTankers = (tankersList ?? []) - .where((t) => _capToLiters(t.capacity) == requiredLiters) - .toList(); - - return Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Container( - width: 60, - height: 4, - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: const Color(0xFFE0E0E0), - borderRadius: BorderRadius.circular(2), - ), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + return FractionallySizedBox( + heightFactor: 0.95, + child: Column( + children: [ + // 🔸 Scrollable Section + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Assign Tanker", - style: fontTextStyle(16, const Color(0XFF2A2A2A), FontWeight.w600), - ), - GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: Image.asset( - 'images/cross.png', - height: 24, - width: 24, - color: const Color(0XFF2A2A2A), + Center( + child: Container( + width: 60, + height: 4, + margin: const EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: const Color(0xFFE0E0E0), + borderRadius: BorderRadius.circular(2), + ), ), - ) - ], - ), - const SizedBox(height: 16), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Assign Tanker", + style: fontTextStyle( + 16, const Color(0XFF2A2A2A), FontWeight.w600), + ), + GestureDetector( + onTap: () => Navigator.pop(context), + child: Image.asset( + 'images/cross.png', + height: 24, + width: 24, + color: const Color(0XFF2A2A2A), + ), + ) + ], + ), + const SizedBox(height: 16), - // 🏢 Order Info - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white, - border: Border.all(color: const Color(0XFFC9C2F0), width: 0.5), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, + // 🏢 Order Info + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.white, + border: Border.all( + color: const Color(0XFFC9C2F0), width: 0.5), + ), + child: Row( children: [ - Text( - widget.order.building_name, - style: fontTextStyle(20, const Color(0XFF2D2E30), FontWeight.w600), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.order.building_name, + style: fontTextStyle( + 20, + const Color(0XFF2D2E30), + FontWeight.w600), + ), + Text( + widget.order.displayAddress, + style: fontTextStyle( + 12, + const Color(0XFF939495), + FontWeight.w400), + ), + ], ), + const Spacer(), Text( - widget.order.displayAddress, - style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400), + '${widget.order.distanceInKm} Km', + style: fontTextStyle( + 12, + const Color(0XFF939495), + FontWeight.w400), ), ], ), - const Spacer(), - Text( - '${widget.order.distanceInKm} Km', - style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400), - ), - ], - ), - ), - const SizedBox(height: 16), - - Text( - "SELECT TANKER", - style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600), - ), - const SizedBox(height: 12), + ), + const SizedBox(height: 16), - // 🧍 Tanker List - Expanded( - child: isTankersDataLoading - ? const Center(child: CircularProgressIndicator()) - : filteredTankers.isEmpty - ? Center( - child: Text( - 'No data available for capacity ${widget.order.capacity}', - style: fontTextStyle(12, const Color(0xFF939495), FontWeight.w500), + // 🛻 Tanker List + Text( + "SELECT TANKER", + style: fontTextStyle( + 10, const Color(0XFF2D2E30), FontWeight.w600), ), - ) - : ListView.separated( - controller: scrollController, - itemCount: filteredTankers.length, - separatorBuilder: (_, __) => const SizedBox(height: 12), - itemBuilder: (context, idx) { - final d = filteredTankers[idx]; - final bool isSelected = selectedTankerIndex == idx; + const SizedBox(height: 12), + + isTankersDataLoading + ? const Center(child: CircularProgressIndicator()) + : (tankersList.isEmpty + ? Center( + child: Text( + 'No Data Available For Capacity ${widget.order.capacity}', + style: fontTextStyle( + 12, + const Color(0xFF939495), + FontWeight.w500), + ), + ) + : ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemCount: tankersList + .where((t) => + _capToLiters(t.capacity) == + _capToLiters(widget.order.capacity)) + .length, + separatorBuilder: (_, __) => + const SizedBox(height: 12), + itemBuilder: (context, idx) { + final filteredTankers = tankersList + .where((t) => + _capToLiters(t.capacity) == + _capToLiters(widget.order.capacity)) + .toList(); + final d = filteredTankers[idx]; + final isSelected = + selectedTankerIndex == idx; - return GestureDetector( - onTap: () { - setModalState(() { - selectedTankerIndex = idx; - }); - }, - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - side: BorderSide( - color: isSelected - ? const Color(0XFF8270DB) - : const Color(0XFFC3C4C4), - width: 1, + return GestureDetector( + onTap: () { + setModalState(() { + selectedTankerIndex = idx; + selectedDriverIndex = null; // reset driver selection if tanker changes + }); + }, + child: Card( + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(12), + side: BorderSide( + color: isSelected + ? primaryColor + : const Color(0XFFC3C4C4), + width: 1, + ), ), - ), - color: isSelected - ? const Color(0XFFEDEBFF) - : Colors.white, - child: Padding( - padding: const EdgeInsets.all(0.0), child: TankersCard( title: d.tanker_name, subtitle: d.type_of_water, capacity: d.capacity, code: d.license_plate, owner: d.supplier_name, - status: List.from(d.availability), + status: List.from( + d.availability), ), ), + ); + }, + )), + const SizedBox(height: 8), + + // 🧍 Driver List + Text( + "SELECT DRIVER", + style: fontTextStyle( + 10, const Color(0XFF2D2E30), FontWeight.w600), + ), + const SizedBox(height: 4), + + // 🚨 Driver list disabled until tanker is selected + selectedTankerIndex == null + ? Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.only(top: 8), + decoration: BoxDecoration( + color: const Color(0XFFFFFFFF), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xFFC3C4C4)), + ), + child: Center( + child: Text( + 'Select a tanker to choose driver', + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w400), ), - ); - }, - ), - ), + ), + ) + : isLoading + ? const Center(child: CircularProgressIndicator()) + : (driversList.isEmpty + ? Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text( + 'No Data Available', + style: fontTextStyle( + 12, + const Color(0xFF939495), + FontWeight.w500), + ), + ), + ) + : ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemCount: driversList.length, + separatorBuilder: (_, __) => const SizedBox(height: 12), + itemBuilder: (context, idx) { + final d = driversList[idx]; + final isSelected = selectedDriverIndex == idx; + final isAvailable = d.status == "available"; - const SizedBox(height: 16), + final statusColor = isAvailable + ? const Color(0XFF0A9E04) + : (d.status == "on delivery" + ? const Color(0XFFD0AE3C) + : (d.status == "offline" + ? const Color(0XFF939495) + : Colors.grey)); - // 🟣 Assign Button - SizedBox( + return GestureDetector( + onTap: () { + /* if (isAvailable) { + setModalState(() { + selectedDriverIndex = idx; + }); + } else { + AppSettings.longFailedToast( + 'Only available drivers can be selected', + ); + }*/ + setModalState(() { + selectedDriverIndex = idx; + }); + }, + child: Card( + color: const Color(0XFFFFFFFF), + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: isSelected ? primaryColor : const Color(0XFFC3C4C4), + width: 1, + ), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + Image.asset( + 'images/avatar.png', + fit: BoxFit.cover, + width: 20, + height: 20, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + d.driver_name, + style: fontTextStyle( + 14, const Color(0XFF2D2E30), FontWeight.w500), + ), + ), + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all(color: statusColor), + ), + child: Text( + d.status, + style: fontTextStyle(10, statusColor, FontWeight.w400), + ), + ), + ], + ), + ), + ), + ); + }, + )), + ], + ), + ), + ), + + // 📌 Fixed Assign Button + SafeArea( + top: false, + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: SizedBox( width: double.infinity, child: GestureDetector( onTap: () async { @@ -508,17 +405,59 @@ class _AssignDriverScreenState extends State { AppSettings.longFailedToast('Please select tanker'); return; } - - if (filteredTankers.isEmpty || - selectedTankerIndex! >= filteredTankers.length) { - AppSettings.longFailedToast('Selected tanker not available'); + /*if (selectedDriverIndex == null) { + AppSettings.longFailedToast('Please select driver'); return; - } + }*/ + + final filteredTankers = tankersList + .where((t) => + _capToLiters(t.capacity) == + _capToLiters(widget.order.capacity)) + .toList(); final selectedTanker = filteredTankers[selectedTankerIndex!]; + final selectedDriver = driversList[selectedDriverIndex!]; + + AppSettings.preLoaderDialog(context); + + bool isOnline = await AppSettings.internetConnectivity(); + + if (isOnline) { + var payload = new Map(); + payload["tankerName"] = selectedTanker.tanker_name; + if(selectedDriverIndex != null){ + payload["delivery_agent"] = selectedDriver.driver_name; + payload["delivery_agent_mobile"] = selectedDriver.phone_number; + } + else{ + payload["delivery_agent"] =null; + payload["delivery_agent_mobile"] = null; + } + - // ✅ Call your API here - // await _assignTankerApi(selectedTanker.id); + bool status = await AppSettings.assignTanker(payload, widget.order.dbId); + + try { + if (status) { + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longFailedToast("Tanker assigned successfully"); + Navigator.pop(context, true); + + } + else{ + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longFailedToast("Failed to assign tanker"); + } + } catch (e) { + Navigator.of(context,rootNavigator: true).pop(); + print(e); + } + } + else{ + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longFailedToast("Please Check internet"); + } if (context.mounted) Navigator.pop(context); }, @@ -532,18 +471,15 @@ class _AssignDriverScreenState extends State { child: Text( 'Assign', style: fontTextStyle( - 14, - const Color(0XFFFFFFFF), - FontWeight.w500, - ), + 14, Colors.white, FontWeight.w500), ), ), ), ), - ], + ), ), - ); - }, + ], + ), ); }, ), @@ -801,7 +737,7 @@ class _AssignDriverScreenState extends State { padding: EdgeInsets.symmetric(vertical: 10), ), onPressed: () async { - AppSettings.preLoaderDialog(context); + /*AppSettings.preLoaderDialog(context); bool isOnline = await AppSettings.internetConnectivity(); @@ -833,7 +769,8 @@ class _AssignDriverScreenState extends State { } else { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longFailedToast("Please Check internet"); - } + }*/ + Navigator.pop(context); }, child: Text( "CANCEL", @@ -971,15 +908,15 @@ class TankersCard extends StatelessWidget { case 'filled': return const Color(0xFFFFFFFF); case 'available': - return const Color(0xFFE8F0FF); + return const Color(0xFFFFFFFF); case 'empty': - return const Color(0xFFFFEEEE); + return const Color(0xFFFFFFFF); case 'in-use': - return const Color(0xFFFFF0E6); + return const Color(0xFFFFFFFF); case 'maintenance': - return const Color(0xFFFFF4E6); + return const Color(0xFFFFFFFF); default: - return const Color(0xFFECECEC); + return const Color(0xFFFFFFFF); } } @@ -996,16 +933,16 @@ class TankersCard extends StatelessWidget { case 'maintenance': return const Color(0xFFD0AE3C); default: - return Colors.black87; + return Color(0xFF2A2A2A); } } @override Widget build(BuildContext context) { - ImageProvider avatarProvider = + /*ImageProvider avatarProvider = (AppSettings.profilePictureUrl != '' && AppSettings.profilePictureUrl != 'null') ? NetworkImage(AppSettings.profilePictureUrl) - : const AssetImage("images/profile_pic.png") as ImageProvider; + : const AssetImage("images/profile_pic.png") as ImageProvider;*/ Widget _statusChip(String s) { final chipTextColor = _chipTextColor(s); @@ -1022,63 +959,66 @@ class TankersCard extends StatelessWidget { } return Container( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.white, + color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(12), - border: Border.all(color: Colors.grey.shade200), + border: Border.all(color: const Color(0XFFC3C4C4)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - /// 👉 First line: Avatar + Text + Status Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - CircleAvatar( - radius: 12, - backgroundImage: avatarProvider, + Image.asset( + 'images/square_avatar.png', + fit: BoxFit.cover, + width: 24, + height: 24, ), const SizedBox(width: 8), + + // Title + Chips Expanded( - child: Text( - "$subtitle • $title", - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: fontTextStyle(12, const Color(0xFF343637), FontWeight.w600), - ), - ), - const SizedBox(width: 8), - ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 160), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - reverse: true, - child: Row( - children: status.map(_statusChip).toList(), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + "$subtitle • $title", + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), + ), + ), + const SizedBox(width: 8), + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 160), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + reverse: true, + child: Row( + children: status.map(_statusChip).toList(), + ), + ), + ), + ], + ), + Text( + code, + style: fontTextStyle(10, const Color(0xFF646566), FontWeight.w400), + ), + ], ), ), ], ), - const SizedBox(height: 8), - - /// 👉 Second line: Capacity + Owner + Code - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("$capacity L", style: fontTextStyle(10, const Color(0xFF343637), FontWeight.w600)), - Row( - children: [ - Text(owner, style: fontTextStyle(10, const Color(0xFF646566), FontWeight.w400)), - const SizedBox(width: 8), - Text(code, style: fontTextStyle(10, const Color(0xFF515253), FontWeight.w400)), - ], - ), - ], - ), ], ), ); + } } diff --git a/lib/orders/change_order.dart b/lib/orders/change_order.dart new file mode 100644 index 0000000..f1c0282 --- /dev/null +++ b/lib/orders/change_order.dart @@ -0,0 +1,985 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:supplier_new/common/settings.dart'; +import '../resources/drivers_model.dart'; +import '../resources/tankers_model.dart'; + +class ChangeOrderScreen extends StatefulWidget { + var order; + var status; + ChangeOrderScreen({this.order, this.status}); + @override + State createState() => _ChangeOrderScreenState(); +} + +class _ChangeOrderScreenState extends State { + int advancePayable = 0; + int advance = 0; + double amountToPayAfterDelivery = 0.0; + double totalFare = 0.0; + bool isLoading = false; + bool isTankersDataLoading = false; + List driversList = []; + List tankersList = []; + + @override + void initState() { + // TODO: implement initState + super.initState(); + _fetchTankers(); + _fetchDrivers(); + advance = 150; + advancePayable = advance; + totalFare = advance + double.parse(widget.order.quoted_amount); + amountToPayAfterDelivery = totalFare - advancePayable; + } + + Future _fetchDrivers() async { + setState(() => isLoading = true); + try { + final response = await AppSettings.getDrivers(); + final data = (jsonDecode(response)['data'] as List) + .map((e) => DriversModel.fromJson(e)) + .toList(); + if (!mounted) return; + setState(() { + driversList = data; + isLoading = false; + }); + } catch (e) { + debugPrint("⚠️ Error fetching drivers: $e"); + setState(() => isLoading = false); + } + } + + Future _fetchTankers() async { + setState(() => isTankersDataLoading = true); + try { + final response = await AppSettings.getTankers(); + final data = (jsonDecode(response)['data'] as List) + .map((e) => TankersModel.fromJson(e)) + .toList(); + if (!mounted) return; + setState(() { + tankersList = data; + isTankersDataLoading = false; + }); + } catch (e) { + debugPrint("⚠️ Error fetching tankers: $e"); + setState(() => isTankersDataLoading = false); + } + } + + void _showAssignTankerBottomSheet() { + int? selectedTankerIndex; + int? selectedDriverIndex; + + int _capToLiters(dynamic cap) { + if (cap == null) return -1; + if (cap is num) return cap.round(); + + final s = cap.toString().toLowerCase().replaceAll(',', '').trim(); + final match = RegExp(r'(\d+(\.\d+)?)').firstMatch(s); + if (match == null) return -1; + + final n = double.tryParse(match.group(1)!) ?? -1; + if (n < 0) return -1; + if (s.contains('kl')) return (n * 1000).round(); + return n.round(); + } + + showModalBottomSheet( + backgroundColor: const Color(0XFFFFFFFF), + context: context, + isScrollControlled: true, + isDismissible: false, + enableDrag: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + builder: (context) { + return WillPopScope( + onWillPop: () async => false, + child: StatefulBuilder( + builder: (context, setModalState) { + return FractionallySizedBox( + heightFactor: 0.95, + child: Column( + children: [ + // 🔸 Scrollable Section + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 60, + height: 4, + margin: const EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: const Color(0xFFE0E0E0), + borderRadius: BorderRadius.circular(2), + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Assign Tanker", + style: fontTextStyle( + 16, const Color(0XFF2A2A2A), FontWeight.w600), + ), + GestureDetector( + onTap: () => Navigator.pop(context), + child: Image.asset( + 'images/cross.png', + height: 24, + width: 24, + color: const Color(0XFF2A2A2A), + ), + ) + ], + ), + const SizedBox(height: 16), + + // 🏢 Order Info + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.white, + border: Border.all( + color: const Color(0XFFC9C2F0), width: 0.5), + ), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.order.building_name, + style: fontTextStyle( + 20, + const Color(0XFF2D2E30), + FontWeight.w600), + ), + Text( + widget.order.displayAddress, + style: fontTextStyle( + 12, + const Color(0XFF939495), + FontWeight.w400), + ), + ], + ), + const Spacer(), + Text( + '${widget.order.distanceInKm} Km', + style: fontTextStyle( + 12, + const Color(0XFF939495), + FontWeight.w400), + ), + ], + ), + ), + const SizedBox(height: 16), + + // 🛻 Tanker List + Text( + "SELECT TANKER", + style: fontTextStyle( + 10, const Color(0XFF2D2E30), FontWeight.w600), + ), + const SizedBox(height: 12), + + isTankersDataLoading + ? const Center(child: CircularProgressIndicator()) + : (tankersList.isEmpty + ? Center( + child: Text( + 'No Data Available For Capacity ${widget.order.capacity}', + style: fontTextStyle( + 12, + const Color(0xFF939495), + FontWeight.w500), + ), + ) + : ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemCount: tankersList + .where((t) => + _capToLiters(t.capacity) == + _capToLiters(widget.order.capacity)) + .length, + separatorBuilder: (_, __) => + const SizedBox(height: 12), + itemBuilder: (context, idx) { + final filteredTankers = tankersList + .where((t) => + _capToLiters(t.capacity) == + _capToLiters(widget.order.capacity)) + .toList(); + final d = filteredTankers[idx]; + final isSelected = + selectedTankerIndex == idx; + + return GestureDetector( + onTap: () { + setModalState(() { + selectedTankerIndex = idx; + selectedDriverIndex = null; // reset driver selection if tanker changes + }); + }, + child: Card( + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(12), + side: BorderSide( + color: isSelected + ? primaryColor + : const Color(0XFFC3C4C4), + width: 1, + ), + ), + child: TankersCard( + title: d.tanker_name, + subtitle: d.type_of_water, + capacity: d.capacity, + code: d.license_plate, + owner: d.supplier_name, + status: List.from( + d.availability), + ), + ), + ); + }, + )), + const SizedBox(height: 8), + + // 🧍 Driver List + Text( + "SELECT DRIVER", + style: fontTextStyle( + 10, const Color(0XFF2D2E30), FontWeight.w600), + ), + const SizedBox(height: 4), + + // 🚨 Driver list disabled until tanker is selected + selectedTankerIndex == null + ? Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.only(top: 8), + decoration: BoxDecoration( + color: const Color(0XFFFFFFFF), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xFFC3C4C4)), + ), + child: Center( + child: Text( + 'Select a tanker to choose driver', + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w400), + ), + ), + ) + : isLoading + ? const Center(child: CircularProgressIndicator()) + : (driversList.isEmpty + ? Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text( + 'No Data Available', + style: fontTextStyle( + 12, + const Color(0xFF939495), + FontWeight.w500), + ), + ), + ) + : ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemCount: driversList.length, + separatorBuilder: (_, __) => const SizedBox(height: 12), + itemBuilder: (context, idx) { + final d = driversList[idx]; + final isSelected = selectedDriverIndex == idx; + final isAvailable = d.status == "available"; + + final statusColor = isAvailable + ? const Color(0XFF0A9E04) + : (d.status == "on delivery" + ? const Color(0XFFD0AE3C) + : (d.status == "offline" + ? const Color(0XFF939495) + : Colors.grey)); + + return GestureDetector( + onTap: () { + /* if (isAvailable) { + setModalState(() { + selectedDriverIndex = idx; + }); + } else { + AppSettings.longFailedToast( + 'Only available drivers can be selected', + ); + }*/ + setModalState(() { + selectedDriverIndex = idx; + }); + }, + child: Card( + color: const Color(0XFFFFFFFF), + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: isSelected ? primaryColor : const Color(0XFFC3C4C4), + width: 1, + ), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + Image.asset( + 'images/avatar.png', + fit: BoxFit.cover, + width: 20, + height: 20, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + d.driver_name, + style: fontTextStyle( + 14, const Color(0XFF2D2E30), FontWeight.w500), + ), + ), + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all(color: statusColor), + ), + child: Text( + d.status, + style: fontTextStyle(10, statusColor, FontWeight.w400), + ), + ), + ], + ), + ), + ), + ); + }, + )), + ], + ), + ), + ), + + // 📌 Fixed Assign Button + SafeArea( + top: false, + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: SizedBox( + width: double.infinity, + child: GestureDetector( + onTap: () async { + if (selectedTankerIndex == null) { + AppSettings.longFailedToast('Please select tanker'); + return; + } + if (selectedDriverIndex == null) { + AppSettings.longFailedToast('Please select driver'); + return; + } + + final filteredTankers = tankersList + .where((t) => + _capToLiters(t.capacity) == + _capToLiters(widget.order.capacity)) + .toList(); + final selectedTanker = + filteredTankers[selectedTankerIndex!]; + final selectedDriver = + driversList[selectedDriverIndex!]; + + if (context.mounted) Navigator.pop(context); + }, + child: Container( + decoration: BoxDecoration( + color: const Color(0XFF8270DB), + borderRadius: BorderRadius.circular(24), + ), + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text( + 'Assign', + style: fontTextStyle( + 14, Colors.white, FontWeight.w500), + ), + ), + ), + ), + ), + ), + ], + ), + ); + }, + ), + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + scrolledUnderElevation: 0, + title: Text( + '', + style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600), + ), + iconTheme: IconThemeData(color: Color(0XFF2A2A2A)), + actions: [ + Row( + children: [ + Padding( + padding: EdgeInsets.fromLTRB(0, 10, 10, 10), + child: IconButton( + icon: Image.asset( + 'images/help_appbar.png', + height: 20, + width: 20, + color: Color(0XFFFFFFFF), + ), + onPressed: () {}, + ), + ) + ], + ) + ], + leading: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 8), // Add padding if needed + child: Image.asset( + 'images/backbutton_appbar.png', // Replace with your image path + fit: BoxFit.contain, + color: Color(0XFFFFFFFF), + height: 24, + width: 24, + ), + ), + ), + ), + + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + /// 🔹 Top Card with Image + Stack( + clipBehavior: Clip.none, + children: [ + /// 🔹 Background Image + ClipRRect( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0), + bottomRight: Radius.circular(0), + ), + child: Image.asset( + "images/building.png", + height: 220, + width: double.infinity, + fit: BoxFit.cover, + ), + ), + + /// 🔹 Floating Info Card (half on image, half below) + Positioned( + bottom: -40, // pulls the card out by 40px + left: 12, + right: 12, + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black12, + blurRadius: 6, + offset: Offset(0, 3), + ), + ], + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + /*Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: Color(0XFFFFFFFF), + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: widget.status.statusColor, + width: 0.5, + ), + ), + child: Text(widget.status.status, + style: fontTextStyle( + 12, + widget.status.statusColor, + FontWeight.w500)), + ),*/ + Text( + widget.order.building_name, + style: fontTextStyle( + 20, const Color(0XFF2D2E30), FontWeight.w600), + ), + SizedBox(height: 4), + Text( + widget.order.displayAddress, + style: fontTextStyle( + 12, const Color(0XFF939495), FontWeight.w400), + ), + ], + ), + const Spacer(), + Text( + widget.order.distanceInKm.toString() + 'Km', + style: fontTextStyle( + 12, const Color(0XFF939495), FontWeight.w400), + ), + ], + ), + ), + ), + ], + ), + SizedBox( + height: MediaQuery.of(context).size.height * .08, + ), + + /// 🔹 Order Details + Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "ORDER DETAILS", + style: fontTextStyle( + 10, const Color(0XFF2D2E30), FontWeight.w600), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .011, + ), + _detailTwoRow( + "Tanker Price", + "₹${AppSettings.formDouble(widget.order.quoted_amount) ?? ''}", + "images/financialsBottomIcon.png", + "", + "", + ""), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + _detailTwoRow( + "Water Type", + "${widget.order.type_of_water}", + "images/water.png", + "Date of Delivery", + "${widget.order.date}", + "images/calendar_appbar.png", + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + _detailTwoRow( + "Capacity", + "${widget.order.capacity}", + "images/capacity.png", + "Time of Delivery", + "${widget.order.time}", + "images/time.png", + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + _detailTwoRow( + "Quantity", + "${widget.order.quantity}", + "images/quantity.png", + "Booking Charges", + advance.toString(), + "images/advance.png", + ), + ], + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .008, + ), + + /// 🔹 Additional Details + Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "ADDITIONAL DETAILS", + style: fontTextStyle( + 10, const Color(0XFF2D2E30), FontWeight.w600), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .011, + ), + Text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " + "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + "aliquip ex ea commodo consequat.", + style: fontTextStyle( + 12, const Color(0XFF646566), FontWeight.w400), + ), + ], + )), + ], + ), + ), + + /// 🔹 Bottom Action Buttons + bottomNavigationBar: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: Color(0XFFFFFFFF), + border: Border(top: BorderSide(color: Color(0XFFF5F6F6))), + ), + child: Row( + children: [ + Expanded( + child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: Color(0XFFFFFFFF), + backgroundColor: Colors.white, + side: BorderSide(color: Color(0XFFFFFFFF)), + padding: EdgeInsets.symmetric(vertical: 10), + ), + onPressed: () async { + /* AppSettings.preLoaderDialog(context); + + bool isOnline = await AppSettings.internetConnectivity(); + + if (isOnline) { + var payload = new Map(); + payload["supplierId"] = AppSettings.supplierId; + payload["amount"] = int.parse(widget.order.quoted_amount); + payload["delivery_charges"] = advance; + payload["action"] = 'reject'; + + bool status = await AppSettings.acceptOrderRequests( + payload, widget.order.dbId); + + try { + if (status) { + Navigator.of(context, rootNavigator: true).pop(); + AppSettings.longSuccessToast( + "Order request rejected Successfully"); + Navigator.pop(context, true); + } else { + Navigator.of(context, rootNavigator: true).pop(); + AppSettings.longFailedToast( + "reject of order request Failed"); + } + } catch (e) { + Navigator.of(context, rootNavigator: true).pop(); + print(e); + } + } else { + Navigator.of(context, rootNavigator: true).pop(); + AppSettings.longFailedToast("Please Check internet"); + }*/ + Navigator.pop(context); + }, + child: Text( + "CANCEL", + style: fontTextStyle( + 14, const Color(0XFFE2483D), FontWeight.w400), + ), + ), + ), + SizedBox(width: 8), + Expanded( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0XFF8270DB), + foregroundColor: Color(0XFFFFFFFF), + padding: EdgeInsets.symmetric(vertical: 10), + ), + onPressed: () async { + _showAssignTankerBottomSheet(); + }, + child: Text( + "Assign Tanker", + style: fontTextStyle( + 14, const Color(0XFFFFFFFF), FontWeight.w400), + ), + ), + ), + ], + )), + ); + } + + /// 🔹 Helper widget for rows + Widget _detailRow(String title, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + title, + style: fontTextStyle(12, const Color(0XFF646566), FontWeight.w400), + ), + Text( + value, + style: fontTextStyle(12, const Color(0XFF2D2E30), FontWeight.w500), + ), + ], + ), + ); + } + + Widget _detailTwoRow( + String title1, + String value1, + String path1, + String title2, + String value2, + String path2, { + EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 6), + }) { + final titleStyle = fontTextStyle(12, Color(0XFF646566), FontWeight.w400); + final valueStyle = fontTextStyle(12, Color(0XFF343637), FontWeight.w500); + + Widget _col(String t, String v, String path) { + return Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (path.isNotEmpty) + Image.asset( + path, + fit: BoxFit.contain, + height: 20, + width: 20, + color: const Color(0XFFC3C4C4), + ), + if (path.isNotEmpty) const SizedBox(width: 6), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(t, + style: titleStyle, + maxLines: 1, + overflow: TextOverflow.ellipsis), + Text(v, + style: valueStyle, + maxLines: 1, + overflow: TextOverflow.ellipsis), + ], + ), + ) + ], + ), + ), + ); + } + + return Padding( + padding: padding, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _col(title1, value1, path1), + _col(title2, value2, path2), + ], + ), + ); + } +} + +// ====== TankersCard ====== +class TankersCard extends StatelessWidget { + final String title; + final String subtitle; + final String capacity; + final String code; + final String owner; + final List status; + + const TankersCard({ + super.key, + required this.title, + required this.subtitle, + required this.capacity, + required this.code, + required this.owner, + required this.status, + }); + + Color _chipColor(String s) { + switch (s) { + case 'filled': + return const Color(0xFFFFFFFF); + case 'available': + return const Color(0xFFFFFFFF); + case 'empty': + return const Color(0xFFFFFFFF); + case 'in-use': + return const Color(0xFFFFFFFF); + case 'maintenance': + return const Color(0xFFFFFFFF); + default: + return const Color(0xFFFFFFFF); + } + } + + Color _chipTextColor(String s) { + switch (s) { + case 'filled': + return const Color(0xFF1D7AFC); + case 'available': + return const Color(0xFF0A9E04); + case 'empty': + return const Color(0xFFE2483D); + case 'in-use': + return const Color(0xFFEA843B); + case 'maintenance': + return const Color(0xFFD0AE3C); + default: + return Color(0xFF2A2A2A); + } + } + + @override + Widget build(BuildContext context) { + /*ImageProvider avatarProvider = + (AppSettings.profilePictureUrl != '' && AppSettings.profilePictureUrl != 'null') + ? NetworkImage(AppSettings.profilePictureUrl) + : const AssetImage("images/profile_pic.png") as ImageProvider;*/ + + Widget _statusChip(String s) { + final chipTextColor = _chipTextColor(s); + return Container( + margin: const EdgeInsets.only(left: 6), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: _chipColor(s), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: chipTextColor, width: 1), + ), + child: Text(s, style: fontTextStyle(10, chipTextColor, FontWeight.w400)), + ); + } + + return Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: const Color(0XFFFFFFFF), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0XFFC3C4C4)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + 'images/square_avatar.png', + fit: BoxFit.cover, + width: 24, + height: 24, + ), + const SizedBox(width: 8), + + // Title + Chips + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + "$subtitle • $title", + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), + ), + ), + const SizedBox(width: 8), + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 160), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + reverse: true, + child: Row( + children: status.map(_statusChip).toList(), + ), + ), + ), + ], + ), + Text( + code, + style: fontTextStyle(10, const Color(0xFF646566), FontWeight.w400), + ), + ], + ), + ), + ], + ), + ], + ), + ); + + } +} diff --git a/lib/resources/drivers_model.dart b/lib/resources/drivers_model.dart index f01b2d2..7d16278 100644 --- a/lib/resources/drivers_model.dart +++ b/lib/resources/drivers_model.dart @@ -6,6 +6,7 @@ class DriversModel { String deliveries='13'; String commision=''; List availability= ['filled', 'available']; + String phone_number=''; DriversModel(); factory DriversModel.fromJson(Map json){ @@ -16,7 +17,7 @@ class DriversModel { rtvm.driver_name = json['name'] ?? ''; rtvm.status = json['status'] ?? ''; rtvm.address = json['address'] ?? ''; - + rtvm.phone_number = json['phone'] ?? ''; return rtvm; } } \ No newline at end of file diff --git a/lib/resources/resources_sources.dart b/lib/resources/resources_sources.dart index c810aa7..4d17fa2 100644 --- a/lib/resources/resources_sources.dart +++ b/lib/resources/resources_sources.dart @@ -589,7 +589,7 @@ class _ResourcesSourceScreenState extends State { const SizedBox(width: 16), Image.asset('images/icon_tune.png', width: 24, height: 24), const SizedBox(width: 16), - Image.asset('images/up_down arrow.png', width: 24, height: 24), + Image.asset('images/up_down_arrow.png', width: 24, height: 24), ], ), const SizedBox(height: 12), diff --git a/lib/resources/tankers_model.dart b/lib/resources/tankers_model.dart index 0b9a9ef..f8261e7 100644 --- a/lib/resources/tankers_model.dart +++ b/lib/resources/tankers_model.dart @@ -9,7 +9,7 @@ class TankersModel { String status=''; String license_plate=''; String supplier_name=''; - List availability= ['filled', 'available']; + List availability= []; TankersModel(); factory TankersModel.fromJson(Map json){ @@ -24,6 +24,7 @@ class TankersModel { rtvm.supplier_name = json['supplier_name'] ?? ''; rtvm.price = json['price'] ?? ''; rtvm.delivery_fee = json['delivery_fee'] ?? ''; + rtvm.availability = json['availability'] ?? []; return rtvm; }