parent
dfc47308d6
commit
8ebdc2b505
|
After Width: | Height: | Size: 1.5 KiB |
@ -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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue