You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
906 lines
29 KiB
906 lines
29 KiB
// ------------- FULL FILE STARTS HERE ---------------
|
|
|
|
import 'dart:convert';
|
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:bookatanker/common/settings.dart';
|
|
|
|
import '../models/tanksview_model.dart';
|
|
|
|
class ArrivalScreen extends StatefulWidget {
|
|
var orderDetails;
|
|
|
|
ArrivalScreen({
|
|
required this.orderDetails,
|
|
});
|
|
|
|
@override
|
|
State<ArrivalScreen> createState() => _ArrivalScreenState();
|
|
}
|
|
|
|
class _ArrivalScreenState extends State<ArrivalScreen> {
|
|
bool isLoading = false;
|
|
List<GetTanksDetailsModel> tankLevelsList = [];
|
|
List<GetTanksDetailsModel> sumpTanks = [];
|
|
GetTanksDetailsModel? selectedTank;
|
|
|
|
String otp = '';
|
|
String unload_complete_otp = '';
|
|
String? selectedTankId;
|
|
|
|
bool _showOrderSummary = false;
|
|
int currentStep = 0;
|
|
bool allowTankChange = true;
|
|
|
|
// -------------------------------------------
|
|
// FETCH TANK DATA
|
|
// -------------------------------------------
|
|
Future<void> getAllTanksData() async {
|
|
isLoading = true;
|
|
var response1 = await AppSettings.getTankLevels();
|
|
setState(() {
|
|
tankLevelsList =
|
|
((jsonDecode(response1)['data']) as List).map((dynamic model) {
|
|
return GetTanksDetailsModel.fromJson(model);
|
|
}).toList();
|
|
|
|
sumpTanks = tankLevelsList
|
|
.where((product) =>
|
|
product.tank_location.toString().toUpperCase() == 'SUMP')
|
|
.toList();
|
|
|
|
isLoading = false;
|
|
});
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
getAllTanksData();
|
|
super.initState();
|
|
|
|
otp = widget.orderDetails.tank_otp ?? '';
|
|
unload_complete_otp = widget.orderDetails.stop_otp ?? '';
|
|
|
|
_setChecklistStepFromStatus();
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// DETERMINE CHECKLIST STEP + LOCK TANK CHANGE
|
|
// -------------------------------------------
|
|
void _setChecklistStepFromStatus() {
|
|
String status = (widget.orderDetails.orderStatus ?? "").toLowerCase().trim();
|
|
|
|
if (status == "unloading_started" || status == "in_progress") {
|
|
currentStep = 1; // Step 1 active
|
|
allowTankChange = false;
|
|
}
|
|
else if (status == "unloading_stopped" || status == "unloading_completed") {
|
|
currentStep = 2; // Step 2 active → View Bill ENABLED
|
|
allowTankChange = false;
|
|
}
|
|
else if (status == "payment_pending" || status == "payment_waiting") {
|
|
currentStep = 2; // Still show Step 2
|
|
allowTankChange = false;
|
|
}
|
|
else {
|
|
currentStep = 0; // Initial stage
|
|
allowTankChange = true; // Only here tank change is allowed
|
|
}
|
|
|
|
setState(() {});
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// REFRESH ALL DATA
|
|
// -------------------------------------------
|
|
Future<void> _refreshAllData() async {
|
|
try {
|
|
var response =
|
|
await AppSettings.updateBookingDetailsById(widget.orderDetails.dbId);
|
|
|
|
if (response != '') {
|
|
final data = jsonDecode(response)['data'] ?? {};
|
|
|
|
widget.orderDetails.orderStatus =
|
|
data["orderStatus"] ?? widget.orderDetails.orderStatus;
|
|
|
|
widget.orderDetails.tank_otp =
|
|
data["tank_otp"] ?? widget.orderDetails.tank_otp;
|
|
|
|
widget.orderDetails.stop_otp =
|
|
data["stop_otp"] ?? widget.orderDetails.stop_otp;
|
|
|
|
widget.orderDetails.tankName =
|
|
data["tankName"] ?? widget.orderDetails.tankName;
|
|
|
|
otp = widget.orderDetails.tank_otp ?? '';
|
|
unload_complete_otp = widget.orderDetails.stop_otp ?? '';
|
|
selectedTankId = widget.orderDetails.tankName ?? '';
|
|
}
|
|
|
|
await getAllTanksData();
|
|
|
|
_setChecklistStepFromStatus();
|
|
} catch (e) {
|
|
print("Refresh failed: $e");
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// UPDATE TANK NAME TO SERVER
|
|
// -------------------------------------------
|
|
Future<void> _updateTankName(String tankName) async {
|
|
var payload = {"tankName": tankName};
|
|
|
|
var updateTankStatus = await AppSettings.updateTankNameWhileDelivery(
|
|
widget.orderDetails.dbId, payload);
|
|
|
|
if (updateTankStatus != '') {
|
|
AppSettings.longSuccessToast('Updated successfully');
|
|
|
|
final updatedData = jsonDecode(updateTankStatus)['data'] ?? {};
|
|
final updatedTankName = updatedData["tankName"]?.toString() ?? tankName;
|
|
final updatedOtp = updatedData["tank_otp"]?.toString() ?? "";
|
|
|
|
setState(() {
|
|
selectedTankId = updatedTankName;
|
|
otp = updatedOtp;
|
|
|
|
try {
|
|
widget.orderDetails.tankName = updatedTankName;
|
|
widget.orderDetails.tank_otp = updatedOtp;
|
|
} catch (_) {}
|
|
});
|
|
|
|
/*Navigator.of(context).pop(true);*/
|
|
} else {
|
|
AppSettings.longFailedToast('Update failed');
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// BUILD MAIN UI
|
|
// -------------------------------------------
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final bool hasTankAlready =
|
|
widget.orderDetails.tankName != null &&
|
|
widget.orderDetails.tankName!.isNotEmpty;
|
|
|
|
GetTanksDetailsModel? preSelectedTank;
|
|
|
|
if (hasTankAlready) {
|
|
try {
|
|
preSelectedTank = sumpTanks.firstWhere(
|
|
(t) => t.tank_name == widget.orderDetails.tankName);
|
|
} catch (e) {
|
|
preSelectedTank = null;
|
|
}
|
|
}
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.white,
|
|
appBar: AppSettings.supplierAppBarWithoutActions(
|
|
'Order#${widget.orderDetails.bookingid}', context),
|
|
body: WillPopScope(
|
|
onWillPop: () async {
|
|
Navigator.pop(context, true);
|
|
return false;
|
|
},
|
|
child: SafeArea(
|
|
child: RefreshIndicator(
|
|
onRefresh: _refreshAllData,
|
|
displacement: 60,
|
|
strokeWidth: 3,
|
|
color: Color(0xFF1D7AFC),
|
|
backgroundColor: Colors.white,
|
|
triggerMode: RefreshIndicatorTriggerMode.onEdge,
|
|
child: CustomScrollView(
|
|
physics: AlwaysScrollableScrollPhysics(),
|
|
slivers: [
|
|
SliverToBoxAdapter(
|
|
child: buildMainBody(
|
|
context, hasTankAlready, preSelectedTank),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// YOUR ENTIRE UI BODY
|
|
// -------------------------------------------
|
|
Widget buildMainBody(context, hasTankAlready, preSelectedTank) {
|
|
return SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
// ------------ BANNER -----------------
|
|
Container(
|
|
padding: EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFFFF4D9),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Text(
|
|
"Arrived at your location!",
|
|
style: fontTextStyle(20, Color(0xFF232527), FontWeight.w800),
|
|
),
|
|
SizedBox(height: 4),
|
|
RichText(
|
|
text: TextSpan(
|
|
children: [
|
|
TextSpan(
|
|
text: "HOME",
|
|
style: fontTextStyle(
|
|
11, Color(0xFF343637), FontWeight.w500),
|
|
),
|
|
TextSpan(
|
|
text: " - ${AppSettings.userAddress}",
|
|
style: fontTextStyle(
|
|
11, Color(0xFF343637), FontWeight.w400),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 16),
|
|
|
|
// ------------ PROFILE -----------------
|
|
Row(
|
|
children: [
|
|
CircleAvatar(
|
|
radius: 20,
|
|
backgroundColor: Color(0XFFE8F2FF),
|
|
child: Image.asset('images/profile_user.png',
|
|
width: 50, height: 50),
|
|
),
|
|
SizedBox(width: 8),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
widget.orderDetails.delivery_agent,
|
|
style: fontTextStyle(
|
|
12, Color(0xFF343637), FontWeight.w500),
|
|
),
|
|
SizedBox(height: 4),
|
|
Text(
|
|
"TS J8 8905",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF646566), FontWeight.w500),
|
|
),
|
|
],
|
|
),
|
|
Spacer(),
|
|
Row(children: [
|
|
Image.asset('images/message.png', width: 24, height: 24),
|
|
SizedBox(width: 16),
|
|
Image.asset('images/phone.png', width: 24, height: 24),
|
|
])
|
|
],
|
|
),
|
|
|
|
SizedBox(height: 16),
|
|
|
|
// ------------ TANK DROPDOWN -----------------
|
|
buildTankDropdown(hasTankAlready, preSelectedTank),
|
|
|
|
SizedBox(height: 16),
|
|
|
|
// ------------ OTP Boxes -----------------
|
|
if (selectedTankId != null || hasTankAlready)
|
|
buildStartOtp(),
|
|
|
|
SizedBox(height: 16),
|
|
|
|
if (unload_complete_otp != '') buildStopOtp(),
|
|
|
|
SizedBox(height: 16),
|
|
|
|
// ------------ ORDER SUMMARY -----------------
|
|
buildOrderSummary(),
|
|
|
|
SizedBox(height: 16),
|
|
|
|
// ------------ CHECKLIST -----------------
|
|
buildChecklist(),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// DROPDOWN WITH BLOCKED LOGIC
|
|
// -------------------------------------------
|
|
Widget buildTankDropdown(hasTankAlready, preSelectedTank) {
|
|
return Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Colors.grey.shade400),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Column(children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
hasTankAlready
|
|
? "Change tank to unload water to generate OTP"
|
|
: "Choose a tank to unload water to generate OTP",
|
|
style: fontTextStyle(12, Color(0xFF444444), FontWeight.w600),
|
|
),
|
|
),
|
|
SizedBox(width: 8),
|
|
Expanded(
|
|
child: isLoading
|
|
? Center(
|
|
child: CircularProgressIndicator(
|
|
color: primaryColor,
|
|
strokeWidth: 5,
|
|
),
|
|
)
|
|
: _buildDropdownField(
|
|
hint: hasTankAlready
|
|
? widget.orderDetails.tankName
|
|
: "Select Tank",
|
|
value: selectedTank ?? preSelectedTank,
|
|
items: sumpTanks,
|
|
|
|
// 🔥 OPTION B — TANK CHANGE BLOCKED HERE
|
|
onChanged: (GetTanksDetailsModel? tank) {
|
|
if (tank == null) return;
|
|
|
|
// ❌ BLOCK AFTER UNLOADING STARTED
|
|
if (!allowTankChange) {
|
|
AppSettings.longFailedToast(
|
|
"Tank cannot be changed after unloading has started.");
|
|
return;
|
|
}
|
|
|
|
// MOTOR CHECK
|
|
bool motorOn = false;
|
|
|
|
if (tank.inConnections.isNotEmpty) {
|
|
motorOn = tank.inConnections.any(
|
|
(conn) => conn['motor_status']?.toString() == '2');
|
|
}
|
|
|
|
if (!motorOn && tank.outConnections.isNotEmpty) {
|
|
motorOn = tank.outConnections.any(
|
|
(conn) => conn['motor_status']?.toString() == '2');
|
|
}
|
|
|
|
if (motorOn) {
|
|
showMotorOnAlert(tank);
|
|
return;
|
|
}
|
|
|
|
showTankConfirmDialog(tank);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
)
|
|
]),
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// ALERT WHEN MOTOR ON
|
|
// -------------------------------------------
|
|
void showMotorOnAlert(GetTanksDetailsModel tank) {
|
|
showDialog(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (_) => AlertDialog(
|
|
backgroundColor: Colors.white,
|
|
shape:
|
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
|
title: Center(
|
|
child: Text(
|
|
"The motor of \"${tank.tank_name}\" is turned on. Please turn it off to start unloading.",
|
|
style: fontTextStyle(14, Colors.black, FontWeight.w500),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
actions: [
|
|
Center(
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: GestureDetector(
|
|
onTap: () => Navigator.pop(context),
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
padding: EdgeInsets.symmetric(vertical: 12),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Color(0xFF1D7AFC)),
|
|
borderRadius: BorderRadius.circular(24),
|
|
),
|
|
child: Text("Cancel",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF1D7AFC), FontWeight.w600)),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(width: 12),
|
|
Expanded(
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
setState(() => selectedTank = tank);
|
|
},
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
padding: EdgeInsets.symmetric(vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFC03D34),
|
|
borderRadius: BorderRadius.circular(24),
|
|
),
|
|
child: Text(
|
|
"Stop Motor",
|
|
style: fontTextStyle(
|
|
12, Colors.white, FontWeight.w600),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// CONFIRM TANK CHANGE
|
|
// -------------------------------------------
|
|
void showTankConfirmDialog(GetTanksDetailsModel tank) {
|
|
showDialog(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (_) => AlertDialog(
|
|
backgroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
|
title: Center(
|
|
child: Text(
|
|
"You have selected \"${tank.tank_name}\" for water unloading. Do you confirm?",
|
|
style: fontTextStyle(14, Colors.black, FontWeight.w500),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
actions: [
|
|
Center(
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: GestureDetector(
|
|
onTap: () => Navigator.pop(context),
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
padding: EdgeInsets.symmetric(vertical: 12),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Color(0xFF1D7AFC)),
|
|
borderRadius: BorderRadius.circular(24),
|
|
),
|
|
child: Text(
|
|
"Cancel",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF1D7AFC), FontWeight.w600),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(width: 12),
|
|
Expanded(
|
|
child: GestureDetector(
|
|
onTap: () async {
|
|
await _updateTankName(tank.tank_name);
|
|
setState(() {
|
|
selectedTank = tank;
|
|
selectedTankId = tank.tank_name;
|
|
});
|
|
Navigator.pop(context);
|
|
},
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
padding: EdgeInsets.symmetric(vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFF1D7AFC),
|
|
borderRadius: BorderRadius.circular(24),
|
|
),
|
|
child: Text(
|
|
"Confirm",
|
|
style: fontTextStyle(
|
|
12, Colors.white, FontWeight.w600),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// OTP BOXES
|
|
// -------------------------------------------
|
|
Widget buildStartOtp() {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFE8F2FF),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
padding: EdgeInsets.all(8),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text("Share the OTP to start unloading",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF444444), FontWeight.w600))),
|
|
Expanded(child: buildOtpBoxes(otp)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget buildStopOtp() {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFE8F2FF),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
padding: EdgeInsets.all(8),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text("Share the OTP to stop unloading",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF444444), FontWeight.w600))),
|
|
Expanded(child: buildOtpBoxes(unload_complete_otp)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Row buildOtpBoxes(String otp) {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: (otp.isNotEmpty ? otp : "----")
|
|
.split('')
|
|
.map((digit) {
|
|
return Container(
|
|
width: 28,
|
|
height: 28,
|
|
alignment: Alignment.center,
|
|
margin: EdgeInsets.symmetric(horizontal: 1),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFF4692FD),
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
child: Text(
|
|
digit,
|
|
style: fontTextStyle(12, Colors.white, FontWeight.w500),
|
|
),
|
|
);
|
|
}).toList(),
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// ORDER SUMMARY
|
|
// -------------------------------------------
|
|
Widget buildOrderSummary() {
|
|
return Column(
|
|
children: [
|
|
InkWell(
|
|
onTap: () => setState(() => _showOrderSummary = !_showOrderSummary),
|
|
child: Row(
|
|
children: [
|
|
Text("View Order Summary",
|
|
style: fontTextStyle(
|
|
14, Color(0xFF1D7AFC), FontWeight.w600)),
|
|
Spacer(),
|
|
Image.asset(
|
|
_showOrderSummary
|
|
? 'images/arrow-up.png'
|
|
: 'images/arrow-down.png',
|
|
width: 24,
|
|
height: 24,
|
|
color: Color(0xFF1D7AFC),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
if (_showOrderSummary)
|
|
AnimatedContainer(
|
|
duration: Duration(milliseconds: 300),
|
|
child: Card(
|
|
color: Colors.white,
|
|
child: Padding(
|
|
padding: EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text("ITEMS",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF444444), FontWeight.w700)),
|
|
SizedBox(height: 8),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text("10,000 L Drinking water x 1",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF515253), FontWeight.w400)),
|
|
Text("₹2,500",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF515253), FontWeight.w400)),
|
|
],
|
|
),
|
|
Divider(),
|
|
_priceRow("Item Total", "₹2,346.00"),
|
|
_priceRow("Delivery Charges", "₹150.00"),
|
|
_priceRow("Platform Fee", "₹6.00"),
|
|
_priceRow("Taxes", "₹12.49"),
|
|
Divider(),
|
|
_priceRow("Total Bill", "₹2,514", isBold: true),
|
|
Divider(),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text("Mode of Payment",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF444444), FontWeight.w500)),
|
|
Row(
|
|
children: [
|
|
Image.asset('images/success-toast.png',
|
|
width: 12, height: 12),
|
|
SizedBox(width: 4),
|
|
Text("Cash on delivery",
|
|
style: fontTextStyle(
|
|
12, Color(0xFF444444), FontWeight.w500)),
|
|
],
|
|
)
|
|
],
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// CHECKLIST
|
|
// -------------------------------------------
|
|
Widget buildChecklist() {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text("Arrival Checklist",
|
|
style:
|
|
TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
|
SizedBox(height: 16),
|
|
|
|
_buildChecklistItem(
|
|
icon: Icons.play_circle_fill,
|
|
title: "Start unloading water",
|
|
subtitle:
|
|
"The status will be updated once the delivery agent starts unloading water.",
|
|
stepIndex: 0,
|
|
currentStep: currentStep,
|
|
selectedTankId: selectedTankId,
|
|
onTap: () {},
|
|
),
|
|
|
|
_buildChecklistItem(
|
|
icon: Icons.check_circle,
|
|
title: "Complete unloading",
|
|
subtitle:
|
|
"The status will be updated after you confirm that unloading is complete.",
|
|
stepIndex: 1,
|
|
currentStep: currentStep,
|
|
selectedTankId: selectedTankId,
|
|
onTap: () {},
|
|
),
|
|
|
|
_buildChecklistItem(
|
|
icon: Icons.receipt_long,
|
|
title: "View your bill",
|
|
subtitle:
|
|
"The bill will be calculated after unloading is complete.",
|
|
stepIndex: 2,
|
|
currentStep: currentStep,
|
|
selectedTankId: selectedTankId,
|
|
onTap: () {},
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// HELPERS
|
|
// -------------------------------------------
|
|
Widget _buildDropdownField({
|
|
required String hint,
|
|
required GetTanksDetailsModel? value,
|
|
required List<GetTanksDetailsModel> items,
|
|
String? path,
|
|
required ValueChanged<GetTanksDetailsModel?> onChanged,
|
|
}) {
|
|
return DropdownButtonHideUnderline(
|
|
child: DropdownButton2<GetTanksDetailsModel>(
|
|
isExpanded: true,
|
|
hint: Row(
|
|
children: [
|
|
if (path != null && path.isNotEmpty)
|
|
Image.asset(path, width: 16, height: 16),
|
|
SizedBox(width: 6),
|
|
Text(hint,
|
|
style: fontTextStyle(
|
|
14, Color(0XFF939495), FontWeight.w400)),
|
|
],
|
|
),
|
|
value: value,
|
|
items: items.map((tank) {
|
|
return DropdownMenuItem(
|
|
value: tank,
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 4),
|
|
child: Text(tank.tank_name,
|
|
style: fontTextStyle(
|
|
14, Color(0xFF2D2E30), FontWeight.w400)),
|
|
),
|
|
);
|
|
}).toList(),
|
|
onChanged: onChanged,
|
|
buttonStyleData: ButtonStyleData(
|
|
height: 48,
|
|
padding: EdgeInsets.only(left: 0, right: 12),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Color(0XFF939495)),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
),
|
|
iconStyleData: IconStyleData(
|
|
icon: Padding(
|
|
padding: EdgeInsets.only(right: 4),
|
|
child: Image.asset('images/arrow_down.png',
|
|
width: 16, height: 16, color: Color(0XFF939495)),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Widget _buildChecklistItem({
|
|
required IconData icon,
|
|
required String title,
|
|
required String subtitle,
|
|
required int stepIndex,
|
|
required int currentStep,
|
|
required VoidCallback onTap,
|
|
required String? selectedTankId,
|
|
}) {
|
|
bool isCompleted = currentStep > stepIndex;
|
|
bool isActive = currentStep == stepIndex;
|
|
|
|
// 🔥 Only allow clicking when this is the ACTIVE step AND it is step 2
|
|
bool isClickable = (stepIndex == 2 && isActive);
|
|
|
|
return GestureDetector(
|
|
onTap: isClickable ? onTap : null,
|
|
child: Opacity(
|
|
opacity: 1,
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(bottom: 16),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Column(
|
|
children: [
|
|
Icon(
|
|
(isActive || isCompleted)
|
|
? Icons.radio_button_checked
|
|
: Icons.radio_button_unchecked,
|
|
color: (isActive || isCompleted) ? Colors.blue : Colors.grey,
|
|
),
|
|
if (stepIndex < 2)
|
|
Container(
|
|
width: 2,
|
|
height: 50,
|
|
color: isCompleted ? Colors.blue : Colors.grey[300],
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(width: 12),
|
|
|
|
Expanded(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFF5F7FA),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
icon,
|
|
color: isCompleted ? Colors.blue : Colors.grey,
|
|
),
|
|
const SizedBox(width: 10),
|
|
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title,
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14,
|
|
color: isCompleted ? Colors.black : Colors.grey,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
subtitle,
|
|
style: const TextStyle(fontSize: 12, color: Colors.black54),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _priceRow(String label, String amount, {bool isBold = false}) {
|
|
return Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 4),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(label,
|
|
style: fontTextStyle(
|
|
12,
|
|
Color(0xFF444444),
|
|
isBold ? FontWeight.w600 : FontWeight.w400)),
|
|
Text(amount,
|
|
style: fontTextStyle(
|
|
12,
|
|
Color(0xFF444444),
|
|
isBold ? FontWeight.w600 : FontWeight.w400)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// ------------- FULL FILE ENDS HERE ---------------
|