assign tanker functionality

master
Sneha 2 months ago
parent dfc47308d6
commit 8ebdc2b505

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -164,6 +164,8 @@ class AppSettings{
static String setRatesDailyUrl = host + 'tankers'; static String setRatesDailyUrl = host + 'tankers';
static String getSupplierDetailsUrl = host + 'suppliers'; static String getSupplierDetailsUrl = host + 'suppliers';
static String updatePumpFeeUrl = host + 'suppliers'; static String updatePumpFeeUrl = host + 'suppliers';
static String assignTankerUrl = host + 'suppliers';
static String formDouble(dynamic s) { static String formDouble(dynamic s) {
@ -738,6 +740,30 @@ class AppSettings{
} }
} }
static Future<bool> 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*/ /*Apis ends here*/

@ -70,36 +70,46 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
} }
} }
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;
void _showAssignDriverBottomSheet() { final n = double.tryParse(match.group(1)!) ?? -1;
int? selectedDriverIndex; // Track selected driver if (n < 0) return -1;
if (s.contains('kl')) return (n * 1000).round();
return n.round();
}
showModalBottomSheet( showModalBottomSheet(
backgroundColor: const Color(0XFFFFFFFF),
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
isDismissible: false, isDismissible: false,
enableDrag: false, enableDrag: true,
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)), borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
), ),
builder: (context) { builder: (context) {
return WillPopScope( // block Android back button return WillPopScope(
onWillPop: () async => false, onWillPop: () async => false,
child: StatefulBuilder( child: StatefulBuilder(
builder: (context, setModalState) { builder: (context, setModalState) {
return DraggableScrollableSheet( return FractionallySizedBox(
expand: false, heightFactor: 0.95,
initialChildSize: 0.7, child: Column(
minChildSize: 0.5, children: [
maxChildSize: 0.9, // 🔸 Scrollable Section
builder: (context, scrollController) { Expanded(
return Container( child: SingleChildScrollView(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -118,14 +128,18 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
"Assign Driver", "Assign Tanker",
style: fontTextStyle(16, const Color(0XFF2A2A2A), FontWeight.w600), style: fontTextStyle(
16, const Color(0XFF2A2A2A), FontWeight.w600),
), ),
GestureDetector( GestureDetector(
onTap: (){ onTap: () => Navigator.pop(context),
Navigator.pop(context); child: Image.asset(
}, 'images/cross.png',
child: Image.asset('images/cross.png', height: 24, width: 24,color: Color(0XFF2A2A2A),), height: 24,
width: 24,
color: const Color(0XFF2A2A2A),
),
) )
], ],
), ),
@ -137,52 +151,170 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
color: Colors.white, color: Colors.white,
border: Border.all(color: const Color(0XFFC9C2F0), width: 0.5), border: Border.all(
color: const Color(0XFFC9C2F0), width: 0.5),
), ),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
widget.order.building_name, widget.order.building_name,
style: fontTextStyle(20, const Color(0XFF2D2E30), FontWeight.w600), style: fontTextStyle(
20,
const Color(0XFF2D2E30),
FontWeight.w600),
), ),
Text( Text(
widget.order.displayAddress, widget.order.displayAddress,
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400), style: fontTextStyle(
12,
const Color(0XFF939495),
FontWeight.w400),
), ),
], ],
), ),
const Spacer(), const Spacer(),
Text( Text(
'${widget.order.distanceInKm} Km', '${widget.order.distanceInKm} Km',
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400), style: fontTextStyle(
12,
const Color(0XFF939495),
FontWeight.w400),
), ),
], ],
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// 🛻 Tanker List
Text( Text(
"SELECT DRIVER", "SELECT TANKER",
style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600), style: fontTextStyle(
10, const Color(0XFF2D2E30), FontWeight.w600),
), ),
const SizedBox(height: 12), 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<String>.from(
d.availability),
),
),
);
},
)),
const SizedBox(height: 8),
// 🧍 Driver List // 🧍 Driver List
Expanded( Text(
child: isLoading "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()) ? 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( : ListView.separated(
controller: scrollController, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
itemCount: driversList.length, itemCount: driversList.length,
separatorBuilder: (_, __) => const SizedBox(height: 12), separatorBuilder: (_, __) => const SizedBox(height: 12),
itemBuilder: (context, idx) { itemBuilder: (context, idx) {
final d = driversList[idx]; final d = driversList[idx];
final bool isSelected = selectedDriverIndex == idx; final isSelected = selectedDriverIndex == idx;
final bool isAvailable = d.status == "available"; final isAvailable = d.status == "available";
final statusColor = isAvailable final statusColor = isAvailable
? const Color(0XFF0A9E04) ? const Color(0XFF0A9E04)
@ -194,7 +326,7 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
if (isAvailable) { // only selectable if available /* if (isAvailable) {
setModalState(() { setModalState(() {
selectedDriverIndex = idx; selectedDriverIndex = idx;
}); });
@ -202,23 +334,21 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
AppSettings.longFailedToast( AppSettings.longFailedToast(
'Only available drivers can be selected', 'Only available drivers can be selected',
); );
} }*/
setModalState(() {
selectedDriverIndex = idx;
});
}, },
child: Opacity(
opacity: isAvailable ? 1 : 1, // 👈 grey out non-available
child: Card( child: Card(
color: const Color(0XFFFFFFFF),
elevation: 1,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(12),
side: BorderSide( side: BorderSide(
color: isSelected color: isSelected ? primaryColor : const Color(0XFFC3C4C4),
? const Color(0XFF8270DB)
: const Color(0XFFC3C4C4),
width: 1, width: 1,
), ),
), ),
color: isSelected
? const Color(0XFFEDEBFF)
: Colors.white,
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
child: Row( child: Row(
@ -229,296 +359,105 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
width: 20, width: 20,
height: 20, height: 20,
), ),
SizedBox( const SizedBox(width: 8),
width: MediaQuery.of(context).size.width * .016),
Expanded( Expanded(
child: Text( child: Text(
d.driver_name, d.driver_name,
style: fontTextStyle( style: fontTextStyle(
14, 14, const Color(0XFF2D2E30), FontWeight.w500),
const Color(0XFF2D2E30),
FontWeight.w500,
), ),
), ),
), const SizedBox(width: 8),
SizedBox(
width: MediaQuery.of(context).size.width * .016),
Container( Container(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
horizontal: 6, vertical: 2),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
border: Border.all(color: statusColor), border: Border.all(color: statusColor),
), ),
child: Text( child: Text(
d.status, d.status,
style: fontTextStyle( style: fontTextStyle(10, statusColor, FontWeight.w400),
10,
statusColor,
FontWeight.w400,
),
), ),
), ),
], ],
), ),
), ),
), ),
),
); );
}, },
)),
],
),
), ),
), ),
const SizedBox(height: 16), // 📌 Fixed Assign Button
SafeArea(
// 🟣 Assign Button top: false,
SizedBox( child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: SizedBox(
width: double.infinity, width: double.infinity,
child: GestureDetector( child: GestureDetector(
onTap: () async { onTap: () async {
if (selectedDriverIndex == null) { if (selectedTankerIndex == null) {
AppSettings.longFailedToast('Please select driver'); AppSettings.longFailedToast('Please select tanker');
return; return;
} }
/*if (selectedDriverIndex == null) {
AppSettings.longFailedToast('Please select driver');
return;
}*/
final selectedDriver = driversList[selectedDriverIndex!]; final filteredTankers = tankersList
.where((t) =>
// Call your API here _capToLiters(t.capacity) ==
// await _assignDriverApi(selectedDriver.driver_id); _capToLiters(widget.order.capacity))
.toList();
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
// 🔹 Helper function to normalize capacity values
int _capToLiters(dynamic cap) {
if (cap == null) return -1;
if (cap is num) return cap.round();
final s = cap.toString().toLowerCase().replaceAll(',', '').trim(); final selectedTanker = filteredTankers[selectedTankerIndex!];
final match = RegExp(r'(\d+(\.\d+)?)').firstMatch(s); final selectedDriver = driversList[selectedDriverIndex!];
if (match == null) return -1;
final n = double.tryParse(match.group(1)!) ?? -1; AppSettings.preLoaderDialog(context);
if (n < 0) return -1;
// If string contains "kl" -> convert KL to Liters bool isOnline = await AppSettings.internetConnectivity();
if (s.contains('kl')) return (n * 1000).round();
// Otherwise already in liters if (isOnline) {
return n.round(); var payload = new Map<String, dynamic>();
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;
} }
showModalBottomSheet(
context: context,
isScrollControlled: true,
isDismissible: false,
enableDrag: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (context) {
return WillPopScope(
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,
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,
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( bool status = await AppSettings.assignTanker(payload, widget.order.dbId);
"SELECT TANKER",
style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600),
),
const SizedBox(height: 12),
// 🧍 Tanker List try {
Expanded( if (status) {
child: isTankersDataLoading Navigator.of(context,rootNavigator: true).pop();
? const Center(child: CircularProgressIndicator()) AppSettings.longFailedToast("Tanker assigned successfully");
: filteredTankers.isEmpty Navigator.pop(context, true);
? Center(
child: Text(
'No data available for capacity ${widget.order.capacity}',
style: fontTextStyle(12, const Color(0xFF939495), FontWeight.w500),
),
)
: ListView.separated(
controller: scrollController,
itemCount: filteredTankers.length,
separatorBuilder: (_, __) => const SizedBox(height: 12),
itemBuilder: (context, idx) {
final d = filteredTankers[idx];
final bool 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,
),
),
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<String>.from(d.availability),
),
),
),
);
},
),
),
const SizedBox(height: 16),
// 🟣 Assign Button
SizedBox(
width: double.infinity,
child: GestureDetector(
onTap: () async {
if (selectedTankerIndex == null) {
AppSettings.longFailedToast('Please select tanker');
return;
} }
else{
if (filteredTankers.isEmpty || Navigator.of(context,rootNavigator: true).pop();
selectedTankerIndex! >= filteredTankers.length) { AppSettings.longFailedToast("Failed to assign tanker");
AppSettings.longFailedToast('Selected tanker not available'); }
return; } catch (e) {
Navigator.of(context,rootNavigator: true).pop();
print(e);
}
}
else{
Navigator.of(context,rootNavigator: true).pop();
AppSettings.longFailedToast("Please Check internet");
} }
final selectedTanker = filteredTankers[selectedTankerIndex!];
// Call your API here
// await _assignTankerApi(selectedTanker.id);
if (context.mounted) Navigator.pop(context); if (context.mounted) Navigator.pop(context);
}, },
@ -532,9 +471,8 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
child: Text( child: Text(
'Assign', 'Assign',
style: fontTextStyle( style: fontTextStyle(
14, 14, Colors.white, FontWeight.w500),
const Color(0XFFFFFFFF), ),
FontWeight.w500,
), ),
), ),
), ),
@ -544,8 +482,6 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
), ),
); );
}, },
);
},
), ),
); );
}, },
@ -801,7 +737,7 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
padding: EdgeInsets.symmetric(vertical: 10), padding: EdgeInsets.symmetric(vertical: 10),
), ),
onPressed: () async { onPressed: () async {
AppSettings.preLoaderDialog(context); /*AppSettings.preLoaderDialog(context);
bool isOnline = await AppSettings.internetConnectivity(); bool isOnline = await AppSettings.internetConnectivity();
@ -833,7 +769,8 @@ class _AssignDriverScreenState extends State<AssignDriverScreen> {
} else { } else {
Navigator.of(context, rootNavigator: true).pop(); Navigator.of(context, rootNavigator: true).pop();
AppSettings.longFailedToast("Please Check internet"); AppSettings.longFailedToast("Please Check internet");
} }*/
Navigator.pop(context);
}, },
child: Text( child: Text(
"CANCEL", "CANCEL",
@ -971,15 +908,15 @@ class TankersCard extends StatelessWidget {
case 'filled': case 'filled':
return const Color(0xFFFFFFFF); return const Color(0xFFFFFFFF);
case 'available': case 'available':
return const Color(0xFFE8F0FF); return const Color(0xFFFFFFFF);
case 'empty': case 'empty':
return const Color(0xFFFFEEEE); return const Color(0xFFFFFFFF);
case 'in-use': case 'in-use':
return const Color(0xFFFFF0E6); return const Color(0xFFFFFFFF);
case 'maintenance': case 'maintenance':
return const Color(0xFFFFF4E6); return const Color(0xFFFFFFFF);
default: default:
return const Color(0xFFECECEC); return const Color(0xFFFFFFFF);
} }
} }
@ -996,16 +933,16 @@ class TankersCard extends StatelessWidget {
case 'maintenance': case 'maintenance':
return const Color(0xFFD0AE3C); return const Color(0xFFD0AE3C);
default: default:
return Colors.black87; return Color(0xFF2A2A2A);
} }
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
ImageProvider avatarProvider = /*ImageProvider avatarProvider =
(AppSettings.profilePictureUrl != '' && AppSettings.profilePictureUrl != 'null') (AppSettings.profilePictureUrl != '' && AppSettings.profilePictureUrl != 'null')
? NetworkImage(AppSettings.profilePictureUrl) ? NetworkImage(AppSettings.profilePictureUrl)
: const AssetImage("images/profile_pic.png") as ImageProvider; : const AssetImage("images/profile_pic.png") as ImageProvider;*/
Widget _statusChip(String s) { Widget _statusChip(String s) {
final chipTextColor = _chipTextColor(s); final chipTextColor = _chipTextColor(s);
@ -1022,30 +959,39 @@ class TankersCard extends StatelessWidget {
} }
return Container( return Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: const Color(0XFFFFFFFF),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade200), border: Border.all(color: const Color(0XFFC3C4C4)),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
/// 👉 First line: Avatar + Text + Status
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
CircleAvatar( Image.asset(
radius: 12, 'images/square_avatar.png',
backgroundImage: avatarProvider, fit: BoxFit.cover,
width: 24,
height: 24,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
// Title + Chips
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded( Expanded(
child: Text( child: Text(
"$subtitle$title", "$subtitle$title",
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: fontTextStyle(12, const Color(0xFF343637), FontWeight.w600), style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500),
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
@ -1061,24 +1007,18 @@ class TankersCard extends StatelessWidget {
), ),
], ],
), ),
const SizedBox(height: 8), Text(
code,
/// 👉 Second line: Capacity + Owner + Code style: fontTextStyle(10, const Color(0xFF646566), FontWeight.w400),
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)),
], ],
), ),
),
], ],
), ),
], ],
), ),
); );
} }
} }

@ -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<ChangeOrderScreen> createState() => _ChangeOrderScreenState();
}
class _ChangeOrderScreenState extends State<ChangeOrderScreen> {
int advancePayable = 0;
int advance = 0;
double amountToPayAfterDelivery = 0.0;
double totalFare = 0.0;
bool isLoading = false;
bool isTankersDataLoading = false;
List<DriversModel> driversList = [];
List<TankersModel> 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<void> _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<void> _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<String>.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<String, dynamic>();
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<String> 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),
),
],
),
),
],
),
],
),
);
}
}

@ -6,6 +6,7 @@ class DriversModel {
String deliveries='13'; String deliveries='13';
String commision=''; String commision='';
List<String> availability= ['filled', 'available']; List<String> availability= ['filled', 'available'];
String phone_number='';
DriversModel(); DriversModel();
factory DriversModel.fromJson(Map<String, dynamic> json){ factory DriversModel.fromJson(Map<String, dynamic> json){
@ -16,7 +17,7 @@ class DriversModel {
rtvm.driver_name = json['name'] ?? ''; rtvm.driver_name = json['name'] ?? '';
rtvm.status = json['status'] ?? ''; rtvm.status = json['status'] ?? '';
rtvm.address = json['address'] ?? ''; rtvm.address = json['address'] ?? '';
rtvm.phone_number = json['phone'] ?? '';
return rtvm; return rtvm;
} }
} }

@ -589,7 +589,7 @@ class _ResourcesSourceScreenState extends State<ResourcesSourceScreen> {
const SizedBox(width: 16), const SizedBox(width: 16),
Image.asset('images/icon_tune.png', width: 24, height: 24), Image.asset('images/icon_tune.png', width: 24, height: 24),
const SizedBox(width: 16), 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), const SizedBox(height: 12),

@ -9,7 +9,7 @@ class TankersModel {
String status=''; String status='';
String license_plate=''; String license_plate='';
String supplier_name=''; String supplier_name='';
List<String> availability= ['filled', 'available']; List<dynamic> availability= [];
TankersModel(); TankersModel();
factory TankersModel.fromJson(Map<String, dynamic> json){ factory TankersModel.fromJson(Map<String, dynamic> json){
@ -24,6 +24,7 @@ class TankersModel {
rtvm.supplier_name = json['supplier_name'] ?? ''; rtvm.supplier_name = json['supplier_name'] ?? '';
rtvm.price = json['price'] ?? ''; rtvm.price = json['price'] ?? '';
rtvm.delivery_fee = json['delivery_fee'] ?? ''; rtvm.delivery_fee = json['delivery_fee'] ?? '';
rtvm.availability = json['availability'] ?? [];
return rtvm; return rtvm;
} }

Loading…
Cancel
Save