|
|
|
|
@ -1,10 +1,8 @@
|
|
|
|
|
import 'dart:convert';
|
|
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:supplier_new/common/settings.dart';
|
|
|
|
|
import 'package:supplier_new/orders/edit_order_requests.dart';
|
|
|
|
|
|
|
|
|
|
import '../resources/drivers_model.dart';
|
|
|
|
|
import '../resources/tankers_model.dart';
|
|
|
|
|
|
|
|
|
|
class ChangeDriverScreen extends StatefulWidget {
|
|
|
|
|
var order;
|
|
|
|
|
@ -20,12 +18,18 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
double amountToPayAfterDelivery = 0.0;
|
|
|
|
|
double totalFare = 0.0;
|
|
|
|
|
bool isLoading = false;
|
|
|
|
|
bool isTankersDataLoading = false;
|
|
|
|
|
List<DriversModel> driversList = [];
|
|
|
|
|
List<TankersModel> tankersList = [];
|
|
|
|
|
TankersModel? orderTanker;
|
|
|
|
|
DriversModel? orderDriver;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
// TODO: implement initState
|
|
|
|
|
super.initState();
|
|
|
|
|
_fetchTankers();
|
|
|
|
|
_fetchDrivers();
|
|
|
|
|
advance = 150;
|
|
|
|
|
advancePayable = advance;
|
|
|
|
|
@ -41,8 +45,21 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
.map((e) => DriversModel.fromJson(e))
|
|
|
|
|
.toList();
|
|
|
|
|
if (!mounted) return;
|
|
|
|
|
|
|
|
|
|
// 🔎 Match driver by name (case-insensitive, trimmed)
|
|
|
|
|
final wanted = (widget.order.delivery_agent_name ?? '').toString().trim().toLowerCase();
|
|
|
|
|
DriversModel? matched;
|
|
|
|
|
for (final d in data) {
|
|
|
|
|
final name = (d.driver_name ?? '').toString().trim().toLowerCase();
|
|
|
|
|
if (name == wanted) {
|
|
|
|
|
matched = d;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
driversList = data;
|
|
|
|
|
orderDriver = matched; // store matched driver or null
|
|
|
|
|
isLoading = false;
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
@ -51,34 +68,319 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _showAssignDriverBottomSheet() {
|
|
|
|
|
int? selectedDriverIndex; // ✅ Track selected driver
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
// 🔎 Find tanker by name (case-insensitive, trimmed)
|
|
|
|
|
final wanted = (widget.order.tanker_name ?? '').toString().trim().toLowerCase();
|
|
|
|
|
TankersModel? matched;
|
|
|
|
|
for (final t in data) {
|
|
|
|
|
final name = (t.tanker_name ?? '').toString().trim().toLowerCase();
|
|
|
|
|
if (name == wanted) {
|
|
|
|
|
matched = t;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
tankersList = data;
|
|
|
|
|
orderTanker = matched; // <- store the matched tanker (or null if not found)
|
|
|
|
|
isTankersDataLoading = false;
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
debugPrint("⚠️ Error fetching tankers: $e");
|
|
|
|
|
setState(() => isTankersDataLoading = false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _assignedTankerDetails() {
|
|
|
|
|
if (isTankersDataLoading) {
|
|
|
|
|
return const Center(child: CircularProgressIndicator());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If not found, show a simple fallback using just the name from order
|
|
|
|
|
if (orderTanker == null) {
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.all(12),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
color: const Color(0XFFFFFFFF),
|
|
|
|
|
borderRadius: BorderRadius.circular(12),
|
|
|
|
|
border: Border.all(color: const Color(0XFFFFFFFF)),
|
|
|
|
|
),
|
|
|
|
|
child: Row(
|
|
|
|
|
children: [
|
|
|
|
|
Image.asset('images/square_avatar.png', width: 24, height: 24),
|
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
|
Expanded(
|
|
|
|
|
child: Text(
|
|
|
|
|
widget.order.tanker_name ?? "Tanker",
|
|
|
|
|
style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500),
|
|
|
|
|
maxLines: 1,
|
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
// No details available
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ Found: show full details from fetched TankersModel
|
|
|
|
|
final t = orderTanker!;
|
|
|
|
|
final availability = (t.availability ?? []).cast<String>();
|
|
|
|
|
String? primaryStatus;
|
|
|
|
|
const pref = ['in-use', 'available', 'filled', 'empty', 'maintenance'];
|
|
|
|
|
for (final s in pref) {
|
|
|
|
|
if (availability.any((x) => x.toLowerCase() == s)) { primaryStatus = s; break; }
|
|
|
|
|
}
|
|
|
|
|
primaryStatus ??= availability.isNotEmpty ? availability.first : null;
|
|
|
|
|
|
|
|
|
|
Color _statusTextColor(String s) {
|
|
|
|
|
switch (s.toLowerCase()) {
|
|
|
|
|
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 const Color(0xFF2A2A2A);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _statusChip(String label) {
|
|
|
|
|
final c = _statusTextColor(label);
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
color: Colors.white, borderRadius: BorderRadius.circular(8),
|
|
|
|
|
border: Border.all(color: c, width: 1),
|
|
|
|
|
),
|
|
|
|
|
child: Text(label, style: fontTextStyle(10, c, FontWeight.w400)),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _line(String title, String value) {
|
|
|
|
|
return Padding(
|
|
|
|
|
padding: const EdgeInsets.only(top: 6),
|
|
|
|
|
child: Row(
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
|
children: [
|
|
|
|
|
Text(title, style: fontTextStyle(12, const Color(0xFF646566), FontWeight.w400)),
|
|
|
|
|
Flexible(
|
|
|
|
|
child: Text(value,
|
|
|
|
|
style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500),
|
|
|
|
|
textAlign: TextAlign.right, overflow: TextOverflow.ellipsis, maxLines: 1),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.all(0),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
color: const Color(0XFFFFFFFF),
|
|
|
|
|
borderRadius: BorderRadius.circular(12),
|
|
|
|
|
border: Border.all(color: const Color(0XFFFFFFFF)),
|
|
|
|
|
),
|
|
|
|
|
child: Column(
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
children: [
|
|
|
|
|
Row(
|
|
|
|
|
children: [
|
|
|
|
|
Image.asset('images/avatar.png', width: 24, height: 24),
|
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
|
Expanded(
|
|
|
|
|
child: Text(
|
|
|
|
|
t.tanker_name ?? "",
|
|
|
|
|
style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500),
|
|
|
|
|
maxLines: 1, overflow: TextOverflow.ellipsis,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
if (primaryStatus != null) _statusChip(primaryStatus),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
|
Visibility(
|
|
|
|
|
visible:(t.license_plate!="") ,
|
|
|
|
|
child: Text(
|
|
|
|
|
t.license_plate ?? "",
|
|
|
|
|
style: fontTextStyle(12, const Color(0XFF646566), FontWeight.w400),
|
|
|
|
|
maxLines: 1, overflow: TextOverflow.ellipsis,
|
|
|
|
|
),)
|
|
|
|
|
/* _line("License Plate", t.license_plate ?? ""),
|
|
|
|
|
_line("Water Type", t.type_of_water ?? ""),
|
|
|
|
|
_line("Capacity", t.capacity ?? ""),
|
|
|
|
|
if ((t.supplier_name ?? "").isNotEmpty) _line("Owner", t.supplier_name),*/
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _assignedDriverDetails() {
|
|
|
|
|
if (isLoading) {
|
|
|
|
|
return const Center(child: CircularProgressIndicator());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (orderDriver == null) {
|
|
|
|
|
// fallback if not found
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.all(12),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
color: const Color(0XFFFFFFFF),
|
|
|
|
|
borderRadius: BorderRadius.circular(12),
|
|
|
|
|
border: Border.all(color: const Color(0XFFC3C4C4)),
|
|
|
|
|
),
|
|
|
|
|
child: Row(
|
|
|
|
|
children: [
|
|
|
|
|
Image.asset('images/avatar.png', width: 24, height: 24),
|
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
|
Expanded(
|
|
|
|
|
child: Text(
|
|
|
|
|
widget.order.delivery_agent_name ?? "Driver",
|
|
|
|
|
style: fontTextStyle(14, const Color(0XFF2D2E30), FontWeight.w500),
|
|
|
|
|
maxLines: 1,
|
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final d = orderDriver!;
|
|
|
|
|
|
|
|
|
|
Color _statusTextColor(String s) {
|
|
|
|
|
switch (s.toLowerCase()) {
|
|
|
|
|
case 'available': return const Color(0XFF0A9E04);
|
|
|
|
|
case 'on delivery': return const Color(0XFFD0AE3C);
|
|
|
|
|
case 'offline': return const Color(0XFF939495);
|
|
|
|
|
default: return greyColor;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _statusChip(String label) {
|
|
|
|
|
final c = _statusTextColor(label);
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
color: Colors.white,
|
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
|
|
|
|
border: Border.all(color: c, width: 1),
|
|
|
|
|
),
|
|
|
|
|
child: Text(label, style: fontTextStyle(10, c, FontWeight.w400)),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _line(String title, String value) {
|
|
|
|
|
return Padding(
|
|
|
|
|
padding: const EdgeInsets.only(top: 6),
|
|
|
|
|
child: Row(
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
|
children: [
|
|
|
|
|
Text(title, style: fontTextStyle(12, const Color(0xFF646566), FontWeight.w400)),
|
|
|
|
|
Flexible(
|
|
|
|
|
child: Text(
|
|
|
|
|
value,
|
|
|
|
|
style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500),
|
|
|
|
|
textAlign: TextAlign.right,
|
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
|
maxLines: 1,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.all(0),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
color: const Color(0XFFFFFFFF),
|
|
|
|
|
borderRadius: BorderRadius.circular(12),
|
|
|
|
|
border: Border.all(color: const Color(0XFFFFFFFF)),
|
|
|
|
|
),
|
|
|
|
|
child: Column(
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
children: [
|
|
|
|
|
Row(
|
|
|
|
|
children: [
|
|
|
|
|
Image.asset('images/avatar.png', width: 24, height: 24),
|
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
|
Expanded(
|
|
|
|
|
child: Text(
|
|
|
|
|
d.driver_name ?? "",
|
|
|
|
|
style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500),
|
|
|
|
|
maxLines: 1, overflow: TextOverflow.ellipsis,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
if ((d.status ?? "").isNotEmpty) _statusChip(d.status),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
/* const SizedBox(height: 8),
|
|
|
|
|
_line("Phone", d.phone_number ?? ""),*/
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _showAssignTankerBottomSheet() {
|
|
|
|
|
// 🔸 Find default selected indexes
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 🧠 Preselect assigned tanker
|
|
|
|
|
final filteredTankers = tankersList
|
|
|
|
|
.where((t) => _capToLiters(t.capacity) == _capToLiters(widget.order.capacity))
|
|
|
|
|
.toList();
|
|
|
|
|
|
|
|
|
|
selectedTankerIndex = filteredTankers.indexWhere(
|
|
|
|
|
(t) => t.tanker_name == widget.order.tanker_name);
|
|
|
|
|
|
|
|
|
|
// 🧠 Preselect assigned driver
|
|
|
|
|
selectedDriverIndex = driversList.indexWhere(
|
|
|
|
|
(d) => d.driver_name == widget.order.delivery_agent_name);
|
|
|
|
|
|
|
|
|
|
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)),
|
|
|
|
|
),
|
|
|
|
|
builder: (context) {
|
|
|
|
|
return WillPopScope( // ✅ block Android back button
|
|
|
|
|
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) {
|
|
|
|
|
return Container(
|
|
|
|
|
return FractionallySizedBox(
|
|
|
|
|
heightFactor: 0.95,
|
|
|
|
|
child: Column(
|
|
|
|
|
children: [
|
|
|
|
|
Expanded(
|
|
|
|
|
child: SingleChildScrollView(
|
|
|
|
|
padding: const EdgeInsets.all(16),
|
|
|
|
|
decoration: const BoxDecoration(
|
|
|
|
|
color: Colors.white,
|
|
|
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
|
|
|
|
),
|
|
|
|
|
child: Column(
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
children: [
|
|
|
|
|
@ -97,73 +399,132 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
|
children: [
|
|
|
|
|
Text(
|
|
|
|
|
"Assign Driver",
|
|
|
|
|
style: fontTextStyle(16, const Color(0XFF2A2A2A), FontWeight.w600),
|
|
|
|
|
"Edit Order",
|
|
|
|
|
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),),
|
|
|
|
|
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: [
|
|
|
|
|
/// 🛻 Tanker List
|
|
|
|
|
Text(
|
|
|
|
|
widget.order.building_name,
|
|
|
|
|
style: fontTextStyle(20, const Color(0XFF2D2E30), FontWeight.w600),
|
|
|
|
|
"SELECTED TANKER",
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
10, const Color(0XFF2D2E30), FontWeight.w600),
|
|
|
|
|
),
|
|
|
|
|
Text(
|
|
|
|
|
widget.order.displayAddress,
|
|
|
|
|
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400),
|
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
|
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),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
: ListView.separated(
|
|
|
|
|
shrinkWrap: true,
|
|
|
|
|
physics:
|
|
|
|
|
const NeverScrollableScrollPhysics(),
|
|
|
|
|
padding: EdgeInsets.zero,
|
|
|
|
|
itemCount: filteredTankers.length,
|
|
|
|
|
separatorBuilder: (_, __) =>
|
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
|
itemBuilder: (context, idx) {
|
|
|
|
|
final t = filteredTankers[idx];
|
|
|
|
|
final isSelected =
|
|
|
|
|
selectedTankerIndex == idx;
|
|
|
|
|
|
|
|
|
|
return GestureDetector(
|
|
|
|
|
onTap: () {
|
|
|
|
|
setModalState(() {
|
|
|
|
|
selectedTankerIndex = idx;
|
|
|
|
|
selectedDriverIndex = null;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
child: Card(
|
|
|
|
|
elevation: 1,
|
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
|
borderRadius:
|
|
|
|
|
BorderRadius.circular(12),
|
|
|
|
|
side: BorderSide(
|
|
|
|
|
color: isSelected
|
|
|
|
|
? primaryColor
|
|
|
|
|
: const Color(0XFFC3C4C4),
|
|
|
|
|
width: 1,
|
|
|
|
|
),
|
|
|
|
|
const Spacer(),
|
|
|
|
|
Text(
|
|
|
|
|
'${widget.order.distanceInKm} Km',
|
|
|
|
|
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
child: TankersCard(
|
|
|
|
|
title: t.tanker_name,
|
|
|
|
|
subtitle: t.type_of_water,
|
|
|
|
|
capacity: t.capacity,
|
|
|
|
|
code: t.license_plate,
|
|
|
|
|
owner: t.supplier_name,
|
|
|
|
|
status: List<String>.from(
|
|
|
|
|
t.availability),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
)),
|
|
|
|
|
|
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
|
|
|
|
|
|
/// 🧍 Driver List
|
|
|
|
|
Text(
|
|
|
|
|
"SELECT DRIVER",
|
|
|
|
|
style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600),
|
|
|
|
|
"SELECTED DRIVER",
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
10, const Color(0XFF2D2E30), FontWeight.w600),
|
|
|
|
|
),
|
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
|
|
|
|
|
|
// 🧍 Driver List
|
|
|
|
|
Expanded(
|
|
|
|
|
child: isLoading
|
|
|
|
|
? const Center(child: CircularProgressIndicator())
|
|
|
|
|
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),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
: ListView.separated(
|
|
|
|
|
controller: scrollController,
|
|
|
|
|
shrinkWrap: true,
|
|
|
|
|
physics:
|
|
|
|
|
const NeverScrollableScrollPhysics(),
|
|
|
|
|
padding: EdgeInsets.zero,
|
|
|
|
|
itemCount: driversList.length,
|
|
|
|
|
separatorBuilder: (_, __) => const SizedBox(height: 12),
|
|
|
|
|
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
|
|
|
|
|
final isSelected =
|
|
|
|
|
selectedDriverIndex == idx;
|
|
|
|
|
final statusColor = d.status == "available"
|
|
|
|
|
? const Color(0XFF0A9E04)
|
|
|
|
|
: (d.status == "on delivery"
|
|
|
|
|
? const Color(0XFFD0AE3C)
|
|
|
|
|
@ -173,31 +534,23 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
|
|
|
|
|
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(
|
|
|
|
|
color: const Color(0XFFFFFFFF),
|
|
|
|
|
elevation: 1,
|
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
|
|
|
|
borderRadius:
|
|
|
|
|
BorderRadius.circular(12),
|
|
|
|
|
side: BorderSide(
|
|
|
|
|
color: isSelected
|
|
|
|
|
? const Color(0XFF8270DB)
|
|
|
|
|
? primaryColor
|
|
|
|
|
: const Color(0XFFC3C4C4),
|
|
|
|
|
width: 1,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
color: isSelected
|
|
|
|
|
? const Color(0XFFEDEBFF)
|
|
|
|
|
: Colors.white,
|
|
|
|
|
child: Padding(
|
|
|
|
|
padding: const EdgeInsets.all(12.0),
|
|
|
|
|
child: Row(
|
|
|
|
|
@ -208,64 +561,103 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
width: 20,
|
|
|
|
|
height: 20,
|
|
|
|
|
),
|
|
|
|
|
SizedBox(
|
|
|
|
|
width: MediaQuery.of(context).size.width * .016),
|
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
|
Expanded(
|
|
|
|
|
child: Text(
|
|
|
|
|
d.driver_name,
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
14,
|
|
|
|
|
const Color(0XFF2D2E30),
|
|
|
|
|
FontWeight.w500,
|
|
|
|
|
const Color(
|
|
|
|
|
0XFF2D2E30),
|
|
|
|
|
FontWeight.w500),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
SizedBox(
|
|
|
|
|
width: MediaQuery.of(context).size.width * .016),
|
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
|
Container(
|
|
|
|
|
padding: const EdgeInsets.symmetric(
|
|
|
|
|
horizontal: 6, vertical: 2),
|
|
|
|
|
padding:
|
|
|
|
|
const EdgeInsets.symmetric(
|
|
|
|
|
horizontal: 6,
|
|
|
|
|
vertical: 2),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
borderRadius: BorderRadius.circular(4),
|
|
|
|
|
border: Border.all(color: statusColor),
|
|
|
|
|
borderRadius:
|
|
|
|
|
BorderRadius.circular(4),
|
|
|
|
|
border: Border.all(
|
|
|
|
|
color: statusColor),
|
|
|
|
|
),
|
|
|
|
|
child: Text(
|
|
|
|
|
d.status,
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
10,
|
|
|
|
|
statusColor,
|
|
|
|
|
FontWeight.w400,
|
|
|
|
|
),
|
|
|
|
|
FontWeight.w400),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
|
|
|
|
|
|
// 🟣 Assign Button
|
|
|
|
|
SizedBox(
|
|
|
|
|
/// ✅ 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 (selectedDriverIndex == null) {
|
|
|
|
|
AppSettings.longFailedToast('Please select driver');
|
|
|
|
|
if (selectedTankerIndex == null) {
|
|
|
|
|
AppSettings.longFailedToast(
|
|
|
|
|
'Please select tanker');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final selectedDriver = driversList[selectedDriverIndex!];
|
|
|
|
|
final selectedTanker =
|
|
|
|
|
filteredTankers[selectedTankerIndex!];
|
|
|
|
|
final selectedDriver = selectedDriverIndex != null
|
|
|
|
|
? driversList[selectedDriverIndex!]
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
// ✅ Call your API here
|
|
|
|
|
// await _assignDriverApi(selectedDriver.driver_id);
|
|
|
|
|
AppSettings.preLoaderDialog(context);
|
|
|
|
|
bool isOnline =
|
|
|
|
|
await AppSettings.internetConnectivity();
|
|
|
|
|
|
|
|
|
|
if (context.mounted) Navigator.pop(context);
|
|
|
|
|
if (isOnline) {
|
|
|
|
|
var payload = <String, dynamic>{};
|
|
|
|
|
payload["tankerName"] =
|
|
|
|
|
selectedTanker.tanker_name;
|
|
|
|
|
payload["delivery_agent"] =
|
|
|
|
|
selectedDriver?.driver_name;
|
|
|
|
|
payload["delivery_agent_mobile"] =
|
|
|
|
|
selectedDriver?.phone_number;
|
|
|
|
|
|
|
|
|
|
bool status = await AppSettings.assignTanker(
|
|
|
|
|
payload, widget.order.dbId);
|
|
|
|
|
|
|
|
|
|
Navigator.of(context, rootNavigator: true).pop();
|
|
|
|
|
|
|
|
|
|
if (status) {
|
|
|
|
|
AppSettings.longSuccessToast(
|
|
|
|
|
"Tanker assigned successfully");
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
Navigator.pop(context, true);
|
|
|
|
|
} else {
|
|
|
|
|
AppSettings.longFailedToast(
|
|
|
|
|
"Failed to assign tanker");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Navigator.of(context, rootNavigator: true).pop();
|
|
|
|
|
AppSettings.longFailedToast(
|
|
|
|
|
"Please Check internet");
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
child: Container(
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
@ -277,7 +669,9 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
child: Text(
|
|
|
|
|
'Assign',
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
14, const Color(0XFFFFFFFF), FontWeight.w500),
|
|
|
|
|
14, Colors.white, FontWeight.w500),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
@ -286,20 +680,15 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
),);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
|
|
|
|
|
return Scaffold(
|
|
|
|
|
backgroundColor: Colors.white,
|
|
|
|
|
extendBodyBehindAppBar: true,
|
|
|
|
|
@ -523,42 +912,30 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
12, const Color(0XFF646566), FontWeight.w400),
|
|
|
|
|
),
|
|
|
|
|
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,
|
|
|
|
|
height: MediaQuery.of(context).size.height * .032,
|
|
|
|
|
),
|
|
|
|
|
Text(
|
|
|
|
|
"ASSIGNED TANKER",
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
10, const Color(0XFF646566), FontWeight.w600),
|
|
|
|
|
),
|
|
|
|
|
SizedBox(
|
|
|
|
|
height: MediaQuery.of(context).size.height * .012,
|
|
|
|
|
),
|
|
|
|
|
_assignedTankerDetails(),
|
|
|
|
|
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: Colors.green),
|
|
|
|
|
height: MediaQuery.of(context).size.height * .012,
|
|
|
|
|
),
|
|
|
|
|
child: Text(
|
|
|
|
|
'd.status',
|
|
|
|
|
Text(
|
|
|
|
|
"ASSIGNED TO",
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
10,
|
|
|
|
|
Colors.green,
|
|
|
|
|
FontWeight.w400,
|
|
|
|
|
),
|
|
|
|
|
10, const Color(0XFF646566), FontWeight.w600),
|
|
|
|
|
),
|
|
|
|
|
SizedBox(
|
|
|
|
|
height: MediaQuery.of(context).size.height * .012,
|
|
|
|
|
),
|
|
|
|
|
_assignedDriverDetails()
|
|
|
|
|
],
|
|
|
|
|
)),
|
|
|
|
|
],
|
|
|
|
|
@ -583,7 +960,7 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 10),
|
|
|
|
|
),
|
|
|
|
|
onPressed: () async {
|
|
|
|
|
AppSettings.preLoaderDialog(context);
|
|
|
|
|
/*AppSettings.preLoaderDialog(context);
|
|
|
|
|
|
|
|
|
|
bool isOnline = await AppSettings.internetConnectivity();
|
|
|
|
|
|
|
|
|
|
@ -615,7 +992,8 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
} else {
|
|
|
|
|
Navigator.of(context, rootNavigator: true).pop();
|
|
|
|
|
AppSettings.longFailedToast("Please Check internet");
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
},
|
|
|
|
|
child: Text(
|
|
|
|
|
"CANCEL",
|
|
|
|
|
@ -633,10 +1011,10 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 10),
|
|
|
|
|
),
|
|
|
|
|
onPressed: () async {
|
|
|
|
|
_showAssignDriverBottomSheet();
|
|
|
|
|
_showAssignTankerBottomSheet();
|
|
|
|
|
},
|
|
|
|
|
child: Text(
|
|
|
|
|
"Change Order",
|
|
|
|
|
"Edit Order",
|
|
|
|
|
style: fontTextStyle(
|
|
|
|
|
14, const Color(0XFFFFFFFF), FontWeight.w400),
|
|
|
|
|
),
|
|
|
|
|
@ -728,3 +1106,144 @@ class _ChangeDriverScreenState extends State<ChangeDriverScreen> {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ====== 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),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|