resources functionality

master
Sneha 2 months ago
parent b0fcf7d149
commit 3d564d843e

@ -771,7 +771,14 @@ class _HomeScreenState extends State<HomeScreen> {
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
), ),
TextButton( TextButton(
onPressed: () {}, onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FleetStep1Page(),
),
);
},
child: const Text( child: const Text(
"Edit Profile", "Edit Profile",
style: TextStyle(color: Colors.blue, fontSize: 14), style: TextStyle(color: Colors.blue, fontSize: 14),

@ -140,6 +140,11 @@ class AppSettings{
static String uploadPicUrl = host + 'uploads-user'; static String uploadPicUrl = host + 'uploads-user';
static String getOrderRequestsFromUsersUrl = host + 'getuserRequestbookingsforsupplier'; static String getOrderRequestsFromUsersUrl = host + 'getuserRequestbookingsforsupplier';
static String acceptOrderRequestsUrl = host + 'request-booking-with-charges'; static String acceptOrderRequestsUrl = host + 'request-booking-with-charges';
static String getAcceptedOrdersFromUsersUrl = host + 'supplier/booking/advance-paid';
static String getTankersUrl = host + 'getTankers';
static String addTankerUrl = host + 'addTankers';
static String getDriversUrl = host + 'getalldeliveryboys';
static String addDriversUrl = host + 'addDeliveryboys';
static String formDouble(dynamic s) { static String formDouble(dynamic s) {
@ -413,6 +418,140 @@ class AppSettings{
} }
} }
static Future<String> getAcceptedOrdersFromUsers() async {
var uri = Uri.parse(getAcceptedOrdersFromUsersUrl+'/'+supplierId);
//uri = uri.replace(query: 'customerId=$customerId');
var response = await http.get(uri, headers: await buildRequestHeaders());
if (response.statusCode == 200) {
return response.body;
} else if (response.statusCode == 401) {
bool status = await AppSettings.resetToken();
if (status) {
response = await http.get(uri, headers: await buildRequestHeaders());
if (response.statusCode == 200) {
return response.body;
} else {
return '';
}
} else {
return '';
}
} else {
return '';
}
}
static Future<String> getTankers() async {
var uri = Uri.parse(getTankersUrl);
uri = uri.replace(query: 'supplierId=$supplierId');
var response = await http.get(uri, headers: await buildRequestHeaders());
if (response.statusCode == 200) {
return response.body;
} else if (response.statusCode == 401) {
bool status = await AppSettings.resetToken();
if (status) {
response = await http.get(uri, headers: await buildRequestHeaders());
if (response.statusCode == 200) {
return response.body;
} else {
return '';
}
} else {
return '';
}
} else {
return '';
}
}
static Future<bool> addTankers(payload) async {
var response = await http.post(Uri.parse(addTankerUrl + '/' + supplierId),
body: json.encode(payload), headers: await buildRequestHeaders());
if (response.statusCode == 200) {
try {
var _response = json.decode(response.body);
print(_response);
return true;
} catch (e) {
// display error toast
return false;
}
} else if (response.statusCode == 401) {
bool status = await AppSettings.resetToken();
if (status) {
response = await http.post(Uri.parse(addTankerUrl + '/' + supplierId),
body: json.encode(payload), headers: await buildRequestHeaders());
if (response.statusCode == 200) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
static Future<String> getDrivers() async {
var uri = Uri.parse(getDriversUrl+'/'+supplierId);
//uri = uri.replace(query: 'supplierId=$supplierId');
var response = await http.get(uri, headers: await buildRequestHeaders());
if (response.statusCode == 200) {
return response.body;
} else if (response.statusCode == 401) {
bool status = await AppSettings.resetToken();
if (status) {
response = await http.get(uri, headers: await buildRequestHeaders());
if (response.statusCode == 200) {
return response.body;
} else {
return '';
}
} else {
return '';
}
} else {
return '';
}
}
static Future<bool> addDrivers(payload) async {
var response = await http.post(Uri.parse(addDriversUrl + '/' + supplierId),
body: json.encode(payload), headers: await buildRequestHeaders());
if (response.statusCode == 200) {
try {
var _response = json.decode(response.body);
print(_response);
return true;
} catch (e) {
// display error toast
return false;
}
} else if (response.statusCode == 401) {
bool status = await AppSettings.resetToken();
if (status) {
response = await http.post(Uri.parse(addTankerUrl + '/' + supplierId),
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*/

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/orders/order_requests.dart'; import 'package:supplier_new/orders/order_requests.dart';
@ -17,70 +19,60 @@ class AllOrders extends StatefulWidget {
class _AllOrdersState extends State<AllOrders> { class _AllOrdersState extends State<AllOrders> {
final TextEditingController searchController = TextEditingController(); final TextEditingController searchController = TextEditingController();
bool isLoading=false;
final List<OrdersModel> orders =[];
List<OrdersModel> ordersList = [];
@override
void initState() {
// TODO: implement initState
super.initState();
_fetchOrders();
}
Future<void> _fetchOrders() async {
setState(() => isLoading = true);
try {
final response = await AppSettings.getAcceptedOrdersFromUsers();
final data = (jsonDecode(response)['data'] as List)
.map((e) => OrdersModel.fromJson(e))
.toList();
if (!mounted) return;
setState(() {
ordersList = data;
isLoading = false;
});
} catch (e) {
debugPrint("⚠️ Error fetching orders: $e");
setState(() => isLoading = false);
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<OrdersModel> orders = [
OrdersModel(
date: DateTime(2025, 8, 24),
imageAsset: "images/building.png",// sample image
status: "completed",
title: "Rajpushpa Atria",
location: "Kokapet",
quantity: "15,000L - Bore Water",
time: "01:00 AM, Today",
extraInfo: "Delivered by Suresh",
),
OrdersModel(
date: DateTime(2025, 8, 24),
imageAsset: "images/building.png",// sample image
status: "in-progress",
title: "Rajpushpa Atria",
location: "Kokapet",
quantity: "15,000L - Bore Water",
time: "01:00 AM, 21/07/2025",
extraInfo: "Track Delivery",
),
OrdersModel(
date: DateTime(2025, 8, 23),
imageAsset: "images/building.png",// sample image
status: "cancelled",
title: "Lakeview Towers",
location: "Madhapur",
quantity: "8,000L - Tanker Water",
time: "09:30 PM, Yesterday",
extraInfo: "Cancelled by user",
),
OrdersModel(
date: DateTime(2025, 8, 25),
imageAsset: "images/building.png",// sample image
status: "assigned",
title: "Lakeview Towers",
location: "Madhapur",
quantity: "8,000L - Tanker Water",
time: "09:30 PM, Yesterday",
extraInfo: "Assigned to Madhav",
),
OrdersModel(
date: DateTime(2025, 8, 26),
imageAsset: "images/building.png",// sample image
status: "pending",
title: "Lakeview Towers",
location: "Madhapur",
quantity: "8,000L - Tanker Water",
time: "09:30 PM, Yesterday",
extraInfo: "",
),
];
// Group orders by date // Group orders by date
final Map<String, List<OrdersModel>> groupedOrders = {}; final Map<String, List<OrdersModel>> groupedOrders = {};
for (var order in orders) { String formatOrderDate(String? dateStr) {
final formattedDate = DateFormat("dd MMM yyyy").format(order.date); if (dateStr == null || dateStr.trim().isEmpty) {
return ""; // or return a fallback like "N/A"
}
try {
final inputFormat = DateFormat("dd-MMM-yyyy"); // matches 10-Sep-2025
final outputFormat = DateFormat("dd MMM yyyy"); // output 10 Sep 2025
final parsedDate = inputFormat.parse(dateStr);
return outputFormat.format(parsedDate);
} catch (e) {
print("Date parse error: $e");
return dateStr; // fallback to original string
}
}
for (var order in ordersList) {
final formattedDate = formatOrderDate(order.date); // "10 Sep 2025"
groupedOrders.putIfAbsent(formattedDate, () => []).add(order); groupedOrders.putIfAbsent(formattedDate, () => []).add(order);
} }
return Scaffold( return Scaffold(
@ -299,6 +291,8 @@ class OrderCard extends StatelessWidget {
return Color(0XFFF9DBC6); return Color(0XFFF9DBC6);
case "pending": case "pending":
return Color(0XFFFDF3D3); return Color(0XFFFDF3D3);
case "advance_paid":
return Color(0XFFFDF3D3);
default: default:
return Colors.grey; return Colors.grey;
} }
@ -316,6 +310,8 @@ class OrderCard extends StatelessWidget {
return Color(0XFFE56910); return Color(0XFFE56910);
case "pending": case "pending":
return Color(0XFFD0AE3C); return Color(0XFFD0AE3C);
case "advance_paid":
return Color(0XFFD0AE3C);
default: default:
return Colors.grey; return Colors.grey;
} }
@ -349,15 +345,15 @@ class OrderCard extends StatelessWidget {
topLeft: Radius.circular(12), topLeft: Radius.circular(12),
bottomLeft: Radius.circular(0), bottomLeft: Radius.circular(0),
), ),
child: order.imageAsset != null child: order.imageAsset != ''
? Image.asset( ? Image.asset(
order.imageAsset!, order.imageAsset,
height: 145, height: 145,
width: 145, width: 145,
fit: BoxFit.cover, fit: BoxFit.cover,
) )
: Image.network( : Image.network(
order.imageUrl!, order.imageAsset,
height: 100, height: 100,
width: 100, width: 100,
fit: BoxFit.cover, fit: BoxFit.cover,
@ -389,33 +385,55 @@ class OrderCard extends StatelessWidget {
const SizedBox(height: 6), const SizedBox(height: 6),
Text( Text(
order.title, order.building_name,
style:fontTextStyle(16,Color(0XFF2D2E30),FontWeight.w600) style:fontTextStyle(16,Color(0XFF2D2E30),FontWeight.w600)
), ),
Text( Text(
order.location, order.displayAddress,
style: fontTextStyle(12,Color(0XFF646566),FontWeight.w400) style: fontTextStyle(12,Color(0XFF646566),FontWeight.w400)
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
order.quantity, order.capacity+' - '+order.type_of_water,
style: fontTextStyle(14,Color(0XFF444444),FontWeight.w500) style: fontTextStyle(14,Color(0XFF444444),FontWeight.w500)
), ),
Text( Text(
order.time, order.time+' , '+order.date,
style:fontTextStyle(12,Color(0XFF939495),FontWeight.w400) style:fontTextStyle(8,Color(0XFF646566),FontWeight.w400)
), ),
const SizedBox(height: 4), const SizedBox(height: 12),
Visibility(
visible: order.status.toLowerCase().toString()=='advance_paid',
child: GestureDetector(
onTap: (){
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22),
border: Border.all(color: const Color(0XFF939495)),
),
child: Padding(
padding: EdgeInsets.fromLTRB(8,4,8,4),
child: Text(
"Assign",
style: fontTextStyle(
14, const Color(0XFF515253), FontWeight.w400),
),
)
),
),),
Text(
/*Text(
order.extraInfo, order.extraInfo,
style:fontTextStyle(12, order.status == "in-progress" style:fontTextStyle(12, order.status == "in-progress"
? Color(0XFF1D7AFC) ? Color(0XFF1D7AFC)
: Color(0XFF646566),FontWeight.w400) : Color(0XFF646566),FontWeight.w400)
), ),*/
], ],
), ),
), ),

@ -52,7 +52,7 @@ class _OrderRequestsPageState extends State<OrderRequestsPage> {
// Statuses that ignore time // Statuses that ignore time
if (dbLower == "reject") return {"status": "Rejected", "color": const Color(0XFFE2483D)}; if (dbLower == "reject") return {"status": "Rejected", "color": const Color(0XFFE2483D)};
if (dbLower == "accept") return {"status": "Accepted", "color": const Color(0XFF0A9E04)}; if (dbLower == "accept") return {"status": "Accepted", "color": const Color(0XFF0A9E04)};
if (dbLower == "delivered") return {"status": "Delivered", "color": const Color(0XFF2E7D32)}; if (dbLower == "advance_paid") return {"status": "Accepted", "color": const Color(0XFF0A9E04)};
if (dbLower == "cancelled" || dbLower == "cancelled_by_user" || dbLower == "cancelled_by_supplier") { if (dbLower == "cancelled" || dbLower == "cancelled_by_user" || dbLower == "cancelled_by_supplier") {
return {"status": "Cancelled", "color": const Color(0XFF757575)}; return {"status": "Cancelled", "color": const Color(0XFF757575)};
} }
@ -128,7 +128,7 @@ class _OrderRequestsPageState extends State<OrderRequestsPage> {
price: "${AppSettings.formDouble(order.quoted_amount) ?? ''}", price: "${AppSettings.formDouble(order.quoted_amount) ?? ''}",
); );
final noNavigateStatuses = ["expired", "rejected", "accepted", "delivered", "cancelled"]; final noNavigateStatuses = ["expired", "rejected", "accepted", "advance_paid", "cancelled"];
final disableNavigation = noNavigateStatuses.contains(status.toLowerCase()); final disableNavigation = noNavigateStatuses.contains(status.toLowerCase());
final card = OrderCard(order: cardModel); final card = OrderCard(order: cardModel);

@ -1,23 +1,70 @@
class OrdersModel {
final DateTime date;
final String? imageUrl; // Network image import 'package:supplier_new/common/settings.dart';
final String? imageAsset; import 'package:geolocator/geolocator.dart';
final String status;
final String title; class OrdersModel {
final String location; String building_name = '';
final String quantity; String address = '';
final String time; String type_of_water = '';
final String extraInfo; String capacity = '';
String quantity = '';
OrdersModel({ String time = '';
required this.date, String averageTime = '';
this.imageUrl, String quoted_amount = '';
this.imageAsset, String displayAddress='';
required this.status, double lat=0;
required this.title, double lng=0;
required this.location, double distanceInMeters=0;
required this.quantity, double distanceInKm=0.0;
required this.time, String dbId = '';
required this.extraInfo, String status='';
}); String date='';
String imageAsset='images/building.png';
OrdersModel();
factory OrdersModel.fromJson(Map<String, dynamic> json){
OrdersModel rtvm = new OrdersModel();
rtvm.building_name = json['buildingName'] ?? '';
rtvm.dbId = json['_id']?? '';
rtvm.address = json['address'] ?? '';
rtvm.type_of_water = json['typeofwater '] ?? '';
rtvm.capacity = json['capacity'] ?? '';
rtvm.quantity = json['quantity']?? '';
rtvm.time = json['time'] ?? '';
rtvm.date = json['dateOfOrder'] ?? '';
rtvm.status = json['orderStatus'] ?? '';
rtvm.quoted_amount = json['price'].toString() ?? '';
rtvm.lng=json['longitude'] ?? 0.0;
rtvm.lat=json['latitude'] ?? 0.0;
// Split and trim
List<String> parts = rtvm.address.split(',').map((e) => e.trim()).toList();
// Usually, the locality is the part before the main city (Hyderabad)displayAddress = "";
if (parts.length >= 2) {
rtvm.displayAddress = parts[parts.length -4]; // "Banjara Hills"
}
// Distance in meters
rtvm.distanceInMeters = double.parse(
Geolocator.distanceBetween(
rtvm.lat,
rtvm.lng,
AppSettings.supplierLatitude,
AppSettings.supplierLongitude,
).toStringAsFixed(2),
);
// Distance in km
rtvm.distanceInKm = double.parse(
(rtvm.distanceInMeters / 1000).toStringAsFixed(2),
);
return rtvm;
}
Map<String, dynamic> toJson() => {
"boreName":this.building_name,
};
} }

@ -0,0 +1,22 @@
class DriversModel {
String supplier_name='';
String driver_name='';
String status='';
String address='';
String deliveries='13';
String commision='';
List<String> availability= ['filled', 'available'];
DriversModel();
factory DriversModel.fromJson(Map<String, dynamic> json){
DriversModel rtvm = new DriversModel();
rtvm.supplier_name = json['supplier_name'] ?? '';
rtvm.driver_name = json['name'] ?? '';
rtvm.status = json['status'] ?? '';
rtvm.address = json['address'] ?? '';
return rtvm;
}
}

@ -5,10 +5,6 @@ import 'package:supplier_new/resources/source_location.dart';
import 'Fleet_1.dart'; import 'Fleet_1.dart';
// If you want to navigate on Continue, import your next page here.
// import 'fleet_1.dart';
void main() => runApp(const MaterialApp(home: FleetEmployees()));
class FleetEmployees extends StatefulWidget { class FleetEmployees extends StatefulWidget {
const FleetEmployees({super.key}); const FleetEmployees({super.key});
@ -81,22 +77,48 @@ class _FleetEmployeesState extends State<FleetEmployees> {
setState(() {}); setState(() {});
} }
void _addDriver() { void _addDriver() async{
final ok = _formKey.currentState?.validate() ?? false; final ok = _formKey.currentState?.validate() ?? false;
setState(() {}); // ensure error texts render setState(() {}); // ensure error texts render
if (!ok || if (!ok ||
selectedLicense == null || selectedLicense == null ||
selectedExperience == null || selectedExperience == null ||
selectedLicense!.isEmpty ||
selectedExperience!.isEmpty) { selectedExperience!.isEmpty) {
if (selectedLicense == null || selectedExperience == null) { if (selectedExperience == null) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Please select License & Experience")), const SnackBar(content: Text("Please select License & Experience")),
); );
} }
return; return;
} }
_drivers.add(_buildPayload()); var payload = new Map<String, dynamic>();
payload["tankerName"] = _nameCtrl.text.toString();
payload["Name"] = _nameCtrl.text.toString();
payload["license_number"] =selectedLicense.toString();
payload["address"] = AppSettings.userAddress;
payload["supplier_name"] = AppSettings.userName;
payload["phone"] = _mobileCtrl.text.toString();
payload["alternativeContactNumber"] ='';
payload["years_of_experience"] =selectedExperience.toString();
payload["status"] = 'string';
bool tankStatus = await AppSettings.addDrivers(payload);
try {
if (tankStatus) {
AppSettings.longSuccessToast("Tanker Created Successfully");
_nameCtrl.text = '';
Navigator.pop(context,true);
}
else {
AppSettings.longFailedToast("Tanker Creation failed");
}
} catch (exception) {
print(exception);
}
_clearForm(); _clearForm();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Driver added (${_drivers.length})")), SnackBar(content: Text("Driver added (${_drivers.length})")),

@ -2,11 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/common/settings.dart';
import 'employees.dart';
import 'fleet_1.dart';
void main() => runApp(const MaterialApp(home: FleetStep1Page()));
class FleetStep1Page extends StatefulWidget { class FleetStep1Page extends StatefulWidget {
const FleetStep1Page({super.key}); const FleetStep1Page({super.key});
@ -33,6 +28,12 @@ class _FleetStep1PageState extends State<FleetStep1Page> {
]; ];
String? selectedType; String? selectedType;
final List<String> typeOfWater = [
"Bore Water",
"Drinking Water",
];
String? selectedTypeOfWater;
final List<String> featureOptions = [ final List<String> featureOptions = [
"GPS", "GPS",
"Stainless Steel", "Stainless Steel",
@ -99,18 +100,38 @@ class _FleetStep1PageState extends State<FleetStep1Page> {
setState(() {}); setState(() {});
} }
void _addTanker() { void _addTanker() async{
final ok = _formKey.currentState?.validate() ?? false; final ok = _formKey.currentState?.validate() ?? false;
setState(() {}); // in case you show chip validation below labels setState(() {}); // in case you show chip validation below labels
if (!ok || selectedFeatures.isEmpty) { var payload = new Map<String, dynamic>();
if (selectedFeatures.isEmpty) { payload["tankerName"] = _nameCtrl.text.toString();
ScaffoldMessenger.of(context).showSnackBar( payload["capacity"] = _capacityCtrl.text.toString();
const SnackBar(content: Text("Select at least one Tanker Feature")), payload["typeofwater"] =selectedTypeOfWater.toString();
); payload["supplier_address"] = AppSettings.userAddress;
payload["supplier_name"] = AppSettings.userName;
payload["phoneNumber"] = AppSettings.phoneNumber;
payload["tanker_type"] =selectedType;
payload["license_plate"] =_plateCtrl.text.trim();
payload["manufacturing_year"] = _mfgYearCtrl.text.trim();
payload["insurance_exp_date"] = _insExpiryCtrl.text.trim();
bool tankStatus = await AppSettings.addTankers(payload);
try {
if (tankStatus) {
AppSettings.longSuccessToast("Tanker Created Successfully");
_nameCtrl.text = '';
_capacityCtrl.text = '';
Navigator.pop(context,true);
}
else {
AppSettings.longFailedToast("Tanker Creation failed");
} }
return; } catch (exception) {
print(exception);
} }
_tankers.add(_buildPayload());
_clearForm(); _clearForm();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Tanker added (${_tankers.length})")), SnackBar(content: Text("Tanker added (${_tankers.length})")),
@ -267,21 +288,21 @@ class _FleetStep1PageState extends State<FleetStep1Page> {
), ),
_LabeledField( _LabeledField(
label: "Tanker Features *", label: "Type of water *",
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(
value: selectedType, value: selectedTypeOfWater,
items: tankerTypes items: typeOfWater
.map((t) => DropdownMenuItem(value: t, child: Text(t))) .map((t) => DropdownMenuItem(value: t, child: Text(t)))
.toList(), .toList(),
onChanged: (v) => setState(() => selectedType = v), onChanged: (v) => setState(() => selectedTypeOfWater = v),
validator: (v) => validator: (v) =>
v == null || v.isEmpty ? "Tanker Type is required" : null, v == null || v.isEmpty ? "Type of water is required" : null,
isExpanded: true, isExpanded: true,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
// <-- Hint: left-aligned, vertically centered by padding // <-- Hint: left-aligned, vertically centered by padding
hint: Text( hint: Text(
"Select Features", "Select type of water",
style: fontTextStyle( style: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400), 14, const Color(0xFF939495), FontWeight.w400),
), ),
@ -374,29 +395,72 @@ class _FleetStep1PageState extends State<FleetStep1Page> {
const SizedBox(height: 12), const SizedBox(height: 12),
// Continue (primary) // Continue (primary)
SizedBox( /* SizedBox(
width: double.infinity, width: double.infinity,
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF8270DB), // purple bg backgroundColor: const Color(0xFF8270DB), // purple bg
foregroundColor: Colors.white, // ripple/icon/text color foregroundColor: Colors.white, // ripple/icon/text color
padding: const EdgeInsets.symmetric(vertical: 14), padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24)), borderRadius: BorderRadius.circular(24)),
),
onPressed: () async{
if (_nameCtrl.text != '' &&
_capacityCtrl.text != '' &&
_plateCtrl.text != '') {
var payload = new Map<String, dynamic>();
payload["tankerName"] = _nameCtrl.text.toString();
payload["capacity"] = _capacityCtrl.text.toString();
payload["typeofwater"] =selectedTypeOfWater.toString();
payload["supplier_address"] = AppSettings.userAddress;
payload["supplier_name"] = AppSettings.userName;
bool tankStatus = await AppSettings.addTankers(payload);
try {
if (tankStatus) {
AppSettings.longSuccessToast(
"Tanker Created Successfully");
_nameCtrl.text = '';
//tankerPhoneNumberController.text = '';
_capacityCtrl.text = '';
//tankerAlternativePhoneNumberController.text='';
Navigator.pop(context);
*//* await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TankersView()),
);*//*
}
else {
AppSettings.longFailedToast("Tanker Creation failed");
}
} catch (exception) {
print(exception);
}
} else {
AppSettings.longFailedToast("Please enter valid details");
}
_nameCtrl.clear();
_capacityCtrl.text = "10,000";
_plateCtrl.text = "AB 05 H 4948";
_mfgYearCtrl.clear();
_insExpiryCtrl.clear();
selectedType = null;
selectedFeatures.clear();
},
child: Text(
"Continue",
style: fontTextStyle(
14, Colors.white, FontWeight.w400), // white text
),
), ),
onPressed: () { )*/
// Navigator.push(
// context,
// MaterialPageRoute(builder: (_) => const FleetStep2Page()),
// );
},
child: Text(
"Continue",
style: fontTextStyle(
14, Colors.white, FontWeight.w400), // white text
),
),
)
], ],
) )
], ],

@ -1,5 +1,8 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/resources/drivers_model.dart';
import 'package:supplier_new/resources/resources_sources.dart'; import 'package:supplier_new/resources/resources_sources.dart';
import 'fleet.dart'; import 'fleet.dart';
import 'resources_drivers.dart'; import 'resources_drivers.dart';
@ -20,6 +23,35 @@ class ResourcesDriverScreen extends StatefulWidget {
class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> { class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
int selectedTab = 1; // default "Drivers" int selectedTab = 1; // default "Drivers"
String search = ''; String search = '';
bool isLoading = false;
List<DriversModel> driversList = [];
@override
void initState() {
// TODO: implement initState
super.initState();
_fetchDrivers();
}
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 orders: $e");
setState(() => isLoading = false);
}
}
final List<Map<String, dynamic>> drivers = [ final List<Map<String, dynamic>> drivers = [
{ {
@ -80,7 +112,7 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Text('09', Text('${driversList.length.toString()}',
style: fontTextStyle( style: fontTextStyle(
24, const Color(0xFF0D3771), FontWeight.w500)), 24, const Color(0xFF0D3771), FontWeight.w500)),
const SizedBox(height: 6), const SizedBox(height: 6),
@ -167,16 +199,16 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
// Driver list // Driver list
Expanded( Expanded(
child: ListView.separated( child: ListView.separated(
itemCount: drivers.length, itemCount: driversList.length,
separatorBuilder: (_, __) => const SizedBox(height: 12), separatorBuilder: (_, __) => const SizedBox(height: 12),
itemBuilder: (context, idx) { itemBuilder: (context, idx) {
final d = drivers[idx]; final d = driversList[idx];
return DriverCard( return DriverCard(
name: d['name'], name: d.driver_name,
status: d['status'], status: d.status,
location: d['location'], location: d.address,
deliveries: d['deliveries'], deliveries: int.parse(d.deliveries),
commission: d['commission'], commission: d.commision,
); );
}, },
), ),
@ -191,10 +223,18 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
// Floating Action Button // Floating Action Button
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: () { onPressed: () async{
// TODO: Navigate to the next step/screen final result = await Navigator.push(
// Navigator.push(context, MaterialPageRoute(builder: (_) => FleetEmployees())); context,
MaterialPageRoute(
builder: (context) => FleetEmployees(),
),
);
// If result indicates API reload
if (result == true) {
_fetchDrivers();
}
}, },
backgroundColor: Colors.black, backgroundColor: Colors.black,
shape: const CircleBorder(), shape: const CircleBorder(),

@ -1,5 +1,9 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/resources/tankers_model.dart';
import 'fleet.dart'; import 'fleet.dart';
import 'resources_drivers.dart'; import 'resources_drivers.dart';
import 'resources_sources.dart'; import 'resources_sources.dart';
@ -19,8 +23,50 @@ class ResourcesFleetScreen extends StatefulWidget {
} }
class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> { class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
final _formKey = GlobalKey<FormState>();
// Controllers
final _nameCtrl = TextEditingController();
final _capacityCtrl = TextEditingController(); // hint-like
final _plateCtrl = TextEditingController();
final _mfgYearCtrl = TextEditingController();
final _insExpiryCtrl = TextEditingController();
String? _required(String? v, {String field = "This field"}) {
if (v == null || v.trim().isEmpty) return "$field is required";
return null;
}
int selectedTab = 0; int selectedTab = 0;
String search = ''; String search = '';
bool isLoading = false;
List<TankersModel> tankersList = [];
@override
void initState() {
// TODO: implement initState
super.initState();
_fetchTankers();
}
Future<void> _fetchTankers() async {
setState(() => isLoading = 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;
isLoading = false;
});
} catch (e) {
debugPrint("⚠️ Error fetching orders: $e");
setState(() => isLoading = false);
}
}
final List<Map<String, dynamic>> items = [ final List<Map<String, dynamic>> items = [
{ {
@ -60,14 +106,179 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
}, },
]; ];
void openTankerSimpleSheet(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (context) {
return Padding(
padding: EdgeInsets.only(
left: 20,
right: 20,
top: 16,
bottom: MediaQuery.of(context).viewInsets.bottom + 20,
),
child: Form(
key: _formKey,
child: ListView(
shrinkWrap: true,
children: [
// Tanker Name
Text("Tanker Name *",
style: fontTextStyle(14, const Color(0xFF646566), FontWeight.w600)),
const SizedBox(height: 6),
TextFormField(
controller: _nameCtrl,
validator: (v) => _required(v, field: "Tanker Name"),
decoration: const InputDecoration(
hintText: "Enter Tanker Name",
border: OutlineInputBorder(),
isDense: true,
),
textInputAction: TextInputAction.next,
),
const SizedBox(height: 14),
// Capacity
Text("Tanker Capacity (in L) *",
style: fontTextStyle(14, const Color(0xFF646566), FontWeight.w600)),
const SizedBox(height: 6),
TextFormField(
controller: _capacityCtrl,
validator: (v) => _required(v, field: "Tanker Capacity"),
decoration: InputDecoration(
hintText: "10,000 L",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9,]')),
],
textInputAction: TextInputAction.next,
),
const SizedBox(height: 14),
// License Plate
Text("License Plate *",
style: fontTextStyle(14, const Color(0xFF646566), FontWeight.w600)),
const SizedBox(height: 6),
TextFormField(
controller: _plateCtrl,
validator: (v) => _required(v, field: "License Plate"),
decoration: InputDecoration(
hintText: "AB 05 H 4948",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
textCapitalization: TextCapitalization.characters,
textInputAction: TextInputAction.next,
),
const SizedBox(height: 14),
// Manufacturing Year (optional)
Text("Manufacturing Year (opt)",
style: fontTextStyle(14, const Color(0xFF646566), FontWeight.w600)),
const SizedBox(height: 6),
TextFormField(
controller: _mfgYearCtrl,
decoration: InputDecoration(
hintText: "YYYY",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(4),
],
textInputAction: TextInputAction.next,
),
const SizedBox(height: 14),
// Insurance Expiry Date (optional)
Text("Insurance Expiry Date (opt)",
style: fontTextStyle(14, const Color(0xFF646566), FontWeight.w600)),
const SizedBox(height: 6),
TextFormField(
controller: _insExpiryCtrl,
readOnly: true,
decoration: InputDecoration(
hintText: "DD-MM-YYYY",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
suffixIcon: const Icon(Icons.calendar_today_outlined, size: 18),
),
onTap: () async {
final now = DateTime.now();
final picked = await showDatePicker(
context: context,
initialDate: now,
firstDate: DateTime(now.year - 30),
lastDate: DateTime(now.year + 30),
);
if (picked != null) {
final dd = picked.day.toString().padLeft(2, '0');
final mm = picked.month.toString().padLeft(2, '0');
final yyyy = picked.year.toString();
_insExpiryCtrl.text = "$dd-$mm-$yyyy";
}
},
),
const SizedBox(height: 20),
// Save button
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF8270DB),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
),
onPressed: () async {
if (_formKey.currentState?.validate() != true) return;
// TODO: Replace with your save logic / API call
// Example:
// final ok = await saveTanker();
// if (ok) Navigator.pop(context, true);
Navigator.pop(context, true); // close sheet on success
},
child: Text(
"Save",
style: fontTextStyle(14, Colors.white, FontWeight.w600),
),
),
),
],
),
),
);
},
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final filtered = items.where((it) { final filtered = tankersList.where((it) {
final q = search.trim().toLowerCase(); final q = search.trim().toLowerCase();
if (q.isEmpty) return true; if (q.isEmpty) return true;
return it['title'].toLowerCase().contains(q) || return it.tanker_name.toLowerCase().contains(q);
it['subtitle'].toLowerCase().contains(q) ||
it['owner'].toLowerCase().contains(q);
}).toList(); }).toList();
return Scaffold( return Scaffold(
@ -120,7 +331,7 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [Text('14', style: fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500, children: [Text(tankersList.length.toString(), style: fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500,
), ),
), ),
@ -241,11 +452,12 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
itemBuilder: (context, idx) { itemBuilder: (context, idx) {
final it = filtered[idx]; final it = filtered[idx];
return TankCard( return TankCard(
title: it['title'], title: it.tanker_name,
subtitle: it['subtitle'], subtitle: it.type_of_water,
code: it['code'], capacity: it.capacity,
owner: it['owner'], code: it.license_plate,
status: List<String>.from(it['status']), owner: it.supplier_name,
status: List<String>.from(it.availability),
); );
}, },
), ),
@ -258,9 +470,19 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
], ],
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: () { onPressed: () async{
// TODO: Navigate to the next step/screen // openTankerSimpleSheet(context);
// Navigator.push(context, MaterialPageRoute(builder: (_) => const FleetStep1Page())); final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FleetStep1Page(),
),
);
// If result indicates API reload
if (result == true) {
_fetchTankers();
}
}, },
backgroundColor: const Color(0xFF000000), backgroundColor: const Color(0xFF000000),
@ -310,6 +532,7 @@ class SmallMetricBox extends StatelessWidget {
class TankCard extends StatelessWidget { class TankCard extends StatelessWidget {
final String title; final String title;
final String subtitle; final String subtitle;
final String capacity;
final String code; final String code;
final String owner; final String owner;
final List<String> status; final List<String> status;
@ -318,6 +541,7 @@ class TankCard extends StatelessWidget {
super.key, super.key,
required this.title, required this.title,
required this.subtitle, required this.subtitle,
required this.capacity,
required this.code, required this.code,
required this.owner, required this.owner,
required this.status, required this.status,
@ -392,13 +616,13 @@ class TankCard extends StatelessWidget {
}).toList(), }).toList(),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text(title, Text (title,
style: fontTextStyle( style: fontTextStyle(
14, const Color(0xFF343637), FontWeight.w600)), 14, const Color(0xFF343637), FontWeight.w600)),
const SizedBox(height: 6), const SizedBox(height: 6),
Text(subtitle, Text(subtitle+' - '+capacity+' L',
style: fontTextStyle( style: fontTextStyle(
10, const Color(0xFF515253), FontWeight.w600)), 10, const Color(0xFF343637), FontWeight.w600)),
const SizedBox(height: 10), const SizedBox(height: 10),
Row( Row(
children: [ children: [

@ -7,11 +7,6 @@ import '../common/settings.dart';
import 'employees.dart'; import 'employees.dart';
import 'fleet.dart'; import 'fleet.dart';
void main() => runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: ResourcesMainScreen(),
));
class ResourcesMainScreen extends StatefulWidget { class ResourcesMainScreen extends StatefulWidget {
const ResourcesMainScreen({super.key}); const ResourcesMainScreen({super.key});
@ -165,11 +160,11 @@ class _ResourcesMainScreenState extends State<ResourcesMainScreen>
], ],
), ),
), ),
floatingActionButton: AnimatedBuilder( /*floatingActionButton: AnimatedBuilder(
animation: _tabController.animation!, animation: _tabController.animation!,
builder: (context, _) => builder: (context, _) =>
_buildFAB(_tabController.index) ?? const SizedBox.shrink(), _buildFAB(_tabController.index) ?? const SizedBox.shrink(),
), ),*/
); );
} }
} }

@ -234,9 +234,15 @@ class _ResourcesSourceScreenState extends State<ResourcesSourceScreen> {
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: () { onPressed: () {
// TODO: Navigate to the next step/screen Navigator.push(
// Navigator.push(context, MaterialPageRoute(builder: (_) => const SourceLocation())); context,
MaterialPageRoute(
builder: (_) => const HeroMode(
enabled: false,
child: SourceLocation(),
),
),
);
}, },
backgroundColor: const Color(0xFF000000), backgroundColor: const Color(0xFF000000),
shape: const CircleBorder(), shape: const CircleBorder(),

@ -0,0 +1,29 @@
class TankersModel {
String tanker_name = '';
String address = '';
String type_of_water = '';
String capacity = '';
String dbId = '';
String status='';
String license_plate='';
String supplier_name='';
List<String> availability= ['filled', 'available'];
TankersModel();
factory TankersModel.fromJson(Map<String, dynamic> json){
TankersModel rtvm = new TankersModel();
rtvm.tanker_name = json['tankerName']?? '';
rtvm.dbId = json['_id']?? '';
rtvm.address = json['supplier_address']?? '';
rtvm.type_of_water = json['typeofwater'] ?? '';
rtvm.capacity = json['capacity'] ?? '';
rtvm.license_plate = json['license_plate'] ?? '';
rtvm.supplier_name = json['supplier_name'] ?? '';
return rtvm;
}
Map<String, dynamic> toJson() => {
"boreName":this.tanker_name,
};
}
Loading…
Cancel
Save