master
Sneha 5 days ago
parent e4d998cf43
commit e054f2eb92

@ -34,6 +34,8 @@ class DashboardScreen extends StatefulWidget {
}
class _DashboardScreenState extends State<DashboardScreen> {
int _currentIndex = 0;
final ImagePicker _picker = ImagePicker();
final storage = FlutterSecureStorage(
@ -45,16 +47,58 @@ class _DashboardScreenState extends State<DashboardScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController orderSearchController = TextEditingController();
final TextEditingController planSearchController = TextEditingController();
Widget _getScreen(){
switch(_currentIndex){
case 0:
return HomeScreen();
case 1:
return AllOrders(
navigationFrom: 'bottombar',
externalSearchController: orderSearchController,
);
case 2:
return AllPlans(
navigationFrom: 'bottombar',
);
case 3:
return ResourcesMainScreen();
case 4:
return FinancialMainScreen();
default:
return HomeScreen();
}
}
// Define a list of widgets for each screen
final List<Widget> _screens = [
/* final List<Widget> _screens = [
HomeScreen(),
AllOrders(navigationFrom: 'bottombar',),
AllOrders(
navigationFrom: 'bottombar',
externalSearchController: orderSearchController,
),
AllPlans(navigationFrom: 'bottombar',),
ResourcesMainScreen(),
FinancialMainScreen(),
];
];*/
late List<Widget> _screens;
// List of bottom navigation bar items
final List<BottomNavigationBarItem> _bottomNavItems = [
BottomNavigationBarItem(
@ -275,17 +319,25 @@ class _DashboardScreenState extends State<DashboardScreen> {
PreferredSizeWidget? _buildAppBar() {
// 👉 Orders tab (index 1): Custom Search AppBar
if (_currentIndex == 1) {
return SearchOrderAppBar(
return
SearchOrderAppBar(
controller: orderSearchController,
onBack: () {
setState(() {
_currentIndex = 0; // go back to Home
});
},
onHelp: () {
// handle help button action
debugPrint("Help tapped");
onHelp: () {},
onSearch: (value){
orderSearchController.text = value;
},
);
}
@ -727,7 +779,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
),
body:
_screens[_currentIndex],
_getScreen(),
/*_body(),,*/
bottomNavigationBar: Padding(
padding:EdgeInsets.fromLTRB(0, 0, 0, 0) ,
@ -795,6 +847,8 @@ class _HomeScreenState extends State<HomeScreen> {
double yesterdayRevenue = 0;
String revenueChangeText = "0% from yesterday";
Color revenueChangeColor = Colors.grey;
int orderRequestsCount = 0;
int planRequestsCount = 0;
@override
void initState() {
@ -803,6 +857,94 @@ class _HomeScreenState extends State<HomeScreen> {
_fetchTankerCounts();
_fetchTodayOrders();
_fetchTodayRevenue();
_fetchOrderRequestsCount();
_fetchPlanRequestsCount();
}
Future<void> _fetchOrderRequestsCount() async {
try{
final response =
await AppSettings.getOrderRequestsFromUsers();
final List data =
jsonDecode(response)['data'] ?? [];
int count = 0;
for(var order in data){
String status =
(order['status'] ?? "")
.toString()
.toLowerCase();
/// Only pending/new requests
if(status == "pending"){
count++;
}
}
if(!mounted) return;
setState(() {
orderRequestsCount = count;
});
}
catch(e){
debugPrint("Order requests error $e");
}
}
Future<void> _fetchPlanRequestsCount() async {
try{
final response =
await AppSettings.getPlanRequestsFromUsers();
final List data =
jsonDecode(response)['data'] ?? [];
int count = 0;
for(var plan in data){
String status =
(plan['status'] ?? "")
.toString()
.toLowerCase();
/// only pending requests
if(status == "pending"){
count++;
}
}
if(!mounted) return;
setState(() {
planRequestsCount = count;
});
}
catch(e){
debugPrint("Plan requests error $e");
}
}
@ -1106,11 +1248,16 @@ class _HomeScreenState extends State<HomeScreen> {
subtitle: revenueChangeText,
icon: Icons.currency_rupee,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FinancialMainScreen()),
);
final dashboardState =
context.findAncestorStateOfType<_DashboardScreenState>();
dashboardState?.setState(() {
dashboardState._currentIndex = 4;
});
},
),
],
@ -1241,7 +1388,9 @@ class _HomeScreenState extends State<HomeScreen> {
},
child: RequestCard(
title: "Order Requests",
subtitle: "1 new request",
subtitle: orderRequestsCount > 0
? "$orderRequestsCount new request"
: null,
),
),
),
@ -1256,7 +1405,9 @@ class _HomeScreenState extends State<HomeScreen> {
},
child: RequestCard(
title: "Plan Requests",
subtitle: "2 new request",
subtitle: planRequestsCount > 0
? "$planRequestsCount new request"
: null,
),
)
),
@ -1347,12 +1498,12 @@ class DashboardCard extends StatelessWidget {
class RequestCard extends StatelessWidget {
final String title;
final String subtitle;
final String? subtitle;
const RequestCard({
super.key,
required this.title,
required this.subtitle,
this.subtitle,
});
@override
@ -1372,17 +1523,21 @@ class RequestCard extends StatelessWidget {
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.green[50],
borderRadius: BorderRadius.circular(8),
),
child: Text(
subtitle,
style: const TextStyle(color: Colors.green, fontSize: 12),
if(subtitle != null)
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.green[50],
borderRadius: BorderRadius.circular(8),
),
child: Text(
subtitle!,
style: const TextStyle(
color: Colors.green,
fontSize: 12,
),
),
),
),
],
),
);

@ -196,6 +196,8 @@ class AppSettings{
static String connectedCustomersUrl = host + 'connectedCustomers';
static String acceptRequestUrl = host +"friend-request/accept";
static String rejectRequestUrl = host +"friend-request/reject";
static String getDriverTripsUrl = host +"getdeliveryboybookings";
static int driverAvailableCount = 0;
static int driverOnDeliveryCount = 0;
@ -1652,6 +1654,22 @@ class AppSettings{
return false;
}
}
static Future<String> getDriverTrips(
String mobile) async {
var uri = Uri.parse(getDriverTripsUrl+'/'+mobile );
var response =
await http.get(
uri,
headers:
await buildRequestHeaders()
);
return response.body;
}
/*Apis ends here*/
//save data local
@ -1884,44 +1902,107 @@ class AppSettings{
);
}
static supplierAppBarWithActionsText(String title,context) {
static supplierAppBarWithActionsText(
String title,
BuildContext context,
{dynamic result}
){
title = title ?? '';
return AppBar(
backgroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
titleSpacing: 0,
title: Text(
title,
style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600),
style: fontTextStyle(
16,
Color(0XFF2A2A2A),
FontWeight.w600),
),
iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
iconTheme:
IconThemeData(
color: Color(0XFF2A2A2A)),
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
Navigator.pop(
context,
result // IMPORTANT
);
},
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 8), // Add padding if needed
EdgeInsets.fromLTRB(
8,8,8,8),
child: Image.asset(
'images/backbutton_appbar.png', // Replace with your image path
'images/backbutton_appbar.png',
fit: BoxFit.contain,
color: Color(0XFF2A2A2A),
height: 24,
width: 24,
),
),
),
actions: [
Padding(padding: EdgeInsets.all(8),
Padding(
padding: EdgeInsets.all(8),
child: TextButton(
onPressed: () async {
},
child: Text('HELP',
style: fontTextStyle(14,primaryColor,FontWeight.w600),),
),)
onPressed: (){},
child: Text(
'HELP',
style: fontTextStyle(
14,
primaryColor,
FontWeight.w600),
),
),
)
],
);
}
static appBarWithoutActions(String title) {

@ -14,20 +14,31 @@ import 'change_driver.dart';
class AllOrders extends StatefulWidget {
final String navigationFrom;
final TextEditingController? externalSearchController;
AllOrders({
super.key,
required this.navigationFrom,
this.externalSearchController,
});
@override
State<AllOrders> createState() => _AllOrdersState();
}
class _AllOrdersState extends State<AllOrders> {
final TextEditingController searchController = TextEditingController();
late TextEditingController searchController;
bool isLoading=false;
final List<OrdersModel> orders =[];
List<OrdersModel> allOrders = [];
List<OrdersModel> ordersList = [];
bool isSearching = false;
int todaysOrdersCount = 0;
int boreWaterCount = 0;
int drinkingWaterCount = 0;
@ -38,6 +49,26 @@ class _AllOrdersState extends State<AllOrders> {
void initState() {
super.initState();
_fetchOrders();
searchController =
widget.externalSearchController ??
TextEditingController();
searchController.addListener(_searchOrders);
}
@override
void dispose(){
searchController.removeListener(_searchOrders);
if(widget.externalSearchController == null){
searchController.dispose();
}
super.dispose();
}
Future<void> _fetchOrders() async {
@ -50,7 +81,8 @@ class _AllOrdersState extends State<AllOrders> {
.toList();
if (!mounted) return;
setState(() {
ordersList = data;
allOrders = data;
ordersList = List.from(data);
ordersList.sort((a, b) {
try {
@ -91,6 +123,92 @@ class _AllOrdersState extends State<AllOrders> {
}
}
void _searchOrders() {
String query = searchController.text.trim().toLowerCase();
if(query.isEmpty){
setState(() {
ordersList = List.from(allOrders);
isSearching = false;
});
return;
}
List<OrdersModel> filtered = [];
for(var order in allOrders){
String building = order.building_name.toString().toLowerCase();
String address = order.displayAddress.toString().toLowerCase();
String water = order.type_of_water.toString().toLowerCase();
String status = order.status.toString().toLowerCase();
String capacity = order.capacity.toString().toLowerCase();
String amount = order.quoted_amount.toString().toLowerCase();
String date = order.date.toString().toLowerCase();
String time = order.time.toString().toLowerCase();
String driver = order.delivery_agent_name.toString().toLowerCase();
String tanker = order.tanker_name.toString().toLowerCase();
/// normalize status
if(status=='advance_paid' || status=='accepted'){
status='pending';
}
if(status=='deliveryboy_assigned' || status=='tanker_assigned'){
status='assigned';
}
if(status=='delivered'){
status='completed';
}
if(
building.contains(query) ||
address.contains(query) ||
water.contains(query) ||
status.contains(query) ||
capacity.contains(query) ||
amount.contains(query) ||
date.contains(query) ||
time.contains(query) ||
driver.contains(query) ||
tanker.contains(query)
){
filtered.add(order);
}
}
if(!mounted) return;
setState(() {
ordersList = filtered;
isSearching = true;
});
}
void sortOrders(String type) {
setState(() {
selectedFilter = type;
@ -133,7 +251,7 @@ class _AllOrdersState extends State<AllOrders> {
Widget build(BuildContext context) {
// Group orders by date
final Map<String, List<OrdersModel>> groupedOrders = {};
Map<String, List<OrdersModel>> groupedOrders = {};
String formatOrderDate(String? dateStr) {
if (dateStr == null || dateStr.trim().isEmpty) {
return "";
@ -157,17 +275,52 @@ class _AllOrdersState extends State<AllOrders> {
backgroundColor: Color(0XFFF2F2F2),
appBar: widget.navigationFrom.toString().toLowerCase()=='dashboard'?
SearchOrderAppBar(
controller: searchController,
onBack: () => Navigator.pop(context),
onHelp: () {},
onSearch: (value){
_searchOrders();
},
):null,
body: isLoading
? const Center(child: CircularProgressIndicator())
: ordersList.isEmpty?Center(
child: Text(
'No Data Available',
style: fontTextStyle(16,Color(0XFF000000),FontWeight.w700),
: ordersList.isEmpty ?
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:[
Icon(Icons.search_off,size:60,color:Colors.grey),
SizedBox(height:10),
Text(
isSearching?
"No matching orders found":
"No Data Available",
style: fontTextStyle(16,Color(0XFF000000),FontWeight.w700),
),
],
),
):SingleChildScrollView(
child:
Padding(

@ -1,94 +1,223 @@
import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart';
class SearchOrderAppBar extends StatelessWidget implements PreferredSizeWidget {
class SearchOrderAppBar extends StatefulWidget implements PreferredSizeWidget {
final TextEditingController controller;
final VoidCallback onBack;
final VoidCallback onHelp;
final Function(String)? onSearch;
const SearchOrderAppBar({
super.key,
required this.controller,
required this.onBack,
required this.onHelp,
required this.onSearch,
});
@override
State<SearchOrderAppBar> createState() => _SearchOrderAppBarState();
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
class _SearchOrderAppBarState extends State<SearchOrderAppBar>{
late VoidCallback _listener;
@override
void initState(){
super.initState();
_listener = (){
if(!mounted) return;
setState((){});
};
widget.controller.addListener(_listener);
}
@override
void dispose(){
widget.controller.removeListener(_listener);
super.dispose();
}
@override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: Colors.white,
scrolledUnderElevation: 0,
elevation: 0,
leading: GestureDetector(
onTap: onBack, // 👉 Controlled by parent
onTap: widget.onBack,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
'images/backbutton_appbar.png',
height: 24,
width: 24,
fit: BoxFit.contain,
),
),
),
titleSpacing: 0,
title: Container(
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(22),
border: Border.all(color: const Color(0XFF939495)),
),
child: TextField(
controller: controller,
controller: widget.controller,
onChanged: widget.onSearch,
decoration: InputDecoration(
hintText: "Search order",
hintStyle: fontTextStyle(
16,
const Color(0XFF646566),
FontWeight.w400,
),
prefixIcon: SizedBox(
height: 20,
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
'images/search.png',
fit: BoxFit.contain,
),
),
),
/// CLEAR BUTTON ADDED HERE
suffixIcon: widget.controller.text.isNotEmpty
? IconButton(
icon: const Icon(
Icons.close,
size:18,
color: Color(0XFF646566)
),
onPressed: (){
widget.controller.clear();
},
)
: null,
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(vertical: 0),
),
style: fontTextStyle(
16,
const Color(0XFF2A2A2A),
FontWeight.w400,
),
onSubmitted: (value) {
debugPrint("Search Orders: $value");
},
),
),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: onHelp, // 👉 Controlled by parent
onTap: widget.onHelp,
child: Image.asset(
'images/help_appbar.png',
height: 24,
width: 24,
fit: BoxFit.contain,
),
),
),
],
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
}

@ -1,5 +1,8 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:supplier_new/resources/driver_trips_model.dart';
import 'package:supplier_new/resources/resources_drivers.dart';
import '../common/settings.dart';
@ -24,30 +27,32 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
final _mobileCtrl = TextEditingController();
final _altMobileCtrl = TextEditingController();
final _locationCtrl = TextEditingController();
final _licenseController = TextEditingController();
final _experienceController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
// Unused in UI but kept if you later need them
final _commissionCtrl = TextEditingController();
final _joinDateCtrl = TextEditingController();
bool isLoading=false;
List<DriverTripsModel> driverTripsList = [];
bool isTripsLoading = false;
// Dropdown state
String? _status; // 'available' | 'on delivery' | 'offline'
final List<String> _statusOptions = const [
'available',
'on delivery',
'offline'
'Available',
'On delivery',
'Offline'
];
String? selectedLicense;
/*String? selectedLicense;
final List<String> licenseNumbers = const [
'DL-042019-9876543',
'DL-052020-1234567',
'DL-072021-7654321',
];
String? selectedExperience; // years as string
final List<String> yearOptions =
List<String>.generate(41, (i) => '$i'); // 0..40
*/
String? _required(String? v, {String field = "This field"}) {
if (v == null || v.trim().isEmpty) return "$field is required";
@ -60,6 +65,52 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
return null;
}
@override
void initState(){
super.initState();
_fetchDriverTrips();
}
Future<void> _fetchDriverTrips() async {
setState(() => isTripsLoading = true);
try{
String response =
await AppSettings.getDriverTrips(
widget.driverDetails.phone_number
);
final data =
(jsonDecode(response)['data'] as List)
.map((e)=>DriverTripsModel.fromJson(e))
.toList();
setState(() {
driverTripsList = data;
isTripsLoading = false;
});
}
catch(e){
print(e);
setState(() =>
isTripsLoading = false);
}
}
String? fitToOption(String? incoming, List<String> options) {
if (incoming == null) return null;
final inc = incoming.trim();
@ -106,14 +157,14 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
// Build payload (adjust keys to your API if needed)
final payload = <String, dynamic>{
"name": _nameCtrl.text.trim(),
"license_number": selectedLicense ?? "",
"license_number": _licenseController.text ?? "",
"address": _locationCtrl.text.trim().isEmpty
? AppSettings.userAddress
: _locationCtrl.text.trim(),
"supplier_name": AppSettings.userName,
"phone": _mobileCtrl.text.trim(),
"alternativeContactNumber": _altMobileCtrl.text.trim(),
"years_of_experience": selectedExperience ?? "",
"years_of_experience": _experienceController.text ?? "",
"status": _status ?? "available",
};
@ -142,8 +193,8 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
_mobileCtrl.text = widget.driverDetails.phone_number ?? '';
_altMobileCtrl.text = widget.driverDetails.alt_phone_number ?? '';
_locationCtrl.text = widget.driverDetails.address ?? '';
selectedExperience = fitToOption(widget.driverDetails.years_of_experience, yearOptions);
selectedLicense = fitToOption(widget.driverDetails.license_number, licenseNumbers);
_experienceController.text = widget.driverDetails.years_of_experience ?? '';
_licenseController.text = widget.driverDetails.license_number ?? '';
_status = fitToOption(widget.driverDetails.status, _statusOptions);
await showModalBottomSheet(
@ -209,62 +260,61 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
_LabeledField(
label: "Driver License Number *",
child: DropdownButtonFormField<String>(
value: selectedLicense,
items: licenseNumbers
.map((t) =>
DropdownMenuItem(value: t, child: Text(t)))
.toList(),
onChanged: (v) => setState(() => selectedLicense = v),
validator: (v) => v == null || v.isEmpty
? "Driver License required"
: null,
isExpanded: true,
alignment: Alignment.centerLeft,
hint: Text(
"Select License Number",
style: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400),
),
icon: Image.asset('images/downarrow.png',
width: 16, height: 16),
child: TextFormField(
controller: _licenseController, // create controller
decoration: const InputDecoration(
border: OutlineInputBorder(),
isDense: false,
contentPadding: EdgeInsets.symmetric(
horizontal: 12, vertical: 14),
hintText: "Enter License Number",
contentPadding:
EdgeInsets.symmetric(horizontal: 12, vertical: 14),
),
style: fontTextStyle(
14, const Color(0xFF2A2A2A), FontWeight.w400),
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value == null || value.trim().isEmpty) {
return "Driver License required";
}
return null;
},
),
),
_LabeledField(
label: "Years of Experience *",
child: DropdownButtonFormField<String>(
value: selectedExperience,
items: yearOptions
.map((t) =>
DropdownMenuItem(value: t, child: Text(t)))
.toList(),
onChanged: (v) =>
setState(() => selectedExperience = v),
validator: (v) => v == null || v.isEmpty
? "Experience is required"
: null,
isExpanded: true,
alignment: Alignment.centerLeft,
hint: Text(
"Years",
style: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400),
),
icon: Image.asset('images/downarrow.png',
width: 16, height: 16),
child: TextFormField(
controller: _experienceController,
keyboardType: TextInputType.number,
autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly, // Only numbers
LengthLimitingTextInputFormatter(2), // Max 2 digits
],
decoration: const InputDecoration(
border: OutlineInputBorder(),
isDense: false,
contentPadding: EdgeInsets.symmetric(
horizontal: 12, vertical: 14),
hintText: "Enter Years",
contentPadding:
EdgeInsets.symmetric(horizontal: 12, vertical: 14),
),
style: fontTextStyle(
14, const Color(0xFF2A2A2A), FontWeight.w400),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return "Experience is required";
}
if (value.length > 2) {
return "Only 2 digits allowed";
}
return null;
},
),
),
@ -525,10 +575,19 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
child:
Scaffold(
backgroundColor: Color(0XFFFFFFFF),
appBar: AppSettings.supplierAppBarWithActionsText( widget.driverDetails.driver_name.isNotEmpty
? widget.driverDetails.driver_name[0].toUpperCase() +
widget.driverDetails.driver_name.substring(1)
: '', context),
appBar: AppSettings.supplierAppBarWithActionsText(
widget.driverDetails.driver_name.isNotEmpty
? widget.driverDetails.driver_name[0].toUpperCase() +
widget.driverDetails.driver_name.substring(1)
: '',
context,
result: true // ADD THIS
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(0),
@ -687,7 +746,7 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
const SizedBox(height: 8),
// buttons row
OutlinedButton(
/* OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Color(0XFF515253),
backgroundColor: Color(0xFFF3F1FB),
@ -712,7 +771,7 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
],
),
),
const SizedBox(height: 24),
const SizedBox(height: 24),*/
// 🪪 License Card
ClipRRect(
@ -761,13 +820,13 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
),
],
),
Align(
/*Align(
alignment: Alignment.bottomRight,
child: Text(
"Expires on 29/02/2028",
style: fontTextStyle(10, const Color(0xFFFFFFFF), FontWeight.w300),
),
),
),*/
],
)
],
@ -810,25 +869,85 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
],
),
const SizedBox(height: 24),
const SizedBox(height:24),
Padding(padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"RECENT TRIPS",
style:fontTextStyle(10, const Color(0xFF343637), FontWeight.w600),
),
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.all(16),
_buildTripCard("Drinking Water - 10,000 L", "7:02 PM, 28 Jun 2025"),
const SizedBox(height: 8),
_buildTripCard("Drinking Water - 10,000 L", "7:02 PM, 28 Jun 2025"),
const SizedBox(height: 8),
_buildTripCard("Drinking Water - 10,000 L", "7:02 PM, 28 Jun 2025"),
],
),)
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"RECENT TRIPS",
style: fontTextStyle(
10,
const Color(0xFF343637),
FontWeight.w600),
),
const SizedBox(height:12),
isTripsLoading
? const Center(
child:
CircularProgressIndicator())
: driverTripsList.isEmpty
? Center(
child: Padding(
padding:
const EdgeInsets.symmetric(
vertical:12),
child: Text(
"No trips found",
style: fontTextStyle(
12,
const Color(0xFF939495),
FontWeight.w500),
),
),
)
: ListView.separated(
shrinkWrap:true,
physics:
const NeverScrollableScrollPhysics(),
itemCount:
driverTripsList.length,
separatorBuilder:
(_,__) =>
const SizedBox(height:10),
itemBuilder:(context,index){
final trip =
driverTripsList[index];
return _buildTripCard(trip);
},
)
],
),
),
],
),
@ -837,38 +956,198 @@ class _DriverDetailsPageState extends State<DriverDetailsPage> {
));
}
Widget _buildTripCard(String title, String time) {
Widget _buildTripCard(
DriverTripsModel trip){
Color statusColor =
trip.status == "delivered"
? Colors.green
: trip.status == "cancelled"
? Colors.red
: Colors.orange;
return Container(
padding: const EdgeInsets.all(12),
padding:
const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFFFFFFF),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Color(0XFFC3C4C4)),
color:
const Color(0xFFFFFFFF),
borderRadius:
BorderRadius.circular(8),
border: Border.all(
color:
const Color(0XFFC3C4C4)
),
),
child: Row(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Image.asset('images/recent_trips.png', width: 28, height: 28),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style:fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500),
Row(
children: [
Image.asset(
'images/recent_trips.png',
width:28,
height:28),
const SizedBox(width:10),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
trip.tankerName,
style: fontTextStyle(
14,
const Color(0xFF2D2E30),
FontWeight.w500),
),
Text(
trip.customerName,
style: fontTextStyle(
11,
const Color(0xFF646566),
FontWeight.w400),
),
],
),
),
Container(
padding:
const EdgeInsets.symmetric(
horizontal:6,
vertical:2),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(4),
border: Border.all(
color: statusColor
)
),
const SizedBox(height: 2),
Text(
time,
style:fontTextStyle(10, const Color(0xFF939495), FontWeight.w400),
child: Text(
trip.status,
style: fontTextStyle(
10,
statusColor,
FontWeight.w400),
),
],
),
)
],
),
const SizedBox(height:6),
Text(
"${trip.date}${trip.time}",
style: fontTextStyle(
11,
const Color(0xFF939495),
FontWeight.w400),
),
const SizedBox(height:4),
Text(
trip.address,
maxLines:2,
overflow:
TextOverflow.ellipsis,
style: fontTextStyle(
11,
const Color(0xFF646566),
FontWeight.w400),
),
const SizedBox(height:8),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
"${trip.price}",
style: fontTextStyle(
13,
const Color(0xFF2D2E30),
FontWeight.w600),
),
Text(
"Paid ₹${trip.amountPaid}",
style: fontTextStyle(
11,
Colors.green,
FontWeight.w500),
),
],
)
],
),
);
}
}

@ -0,0 +1,76 @@
class DriverTripsModel {
String id = '';
String bookingId = '';
String tankerName = '';
String buildingName = '';
String address = '';
String date = '';
String time = '';
String waterType = '';
String capacity = '';
String price = '';
String status = '';
String customerName = '';
String amountPaid = '';
String amountDue = '';
String paymentStatus = '';
DriverTripsModel();
factory DriverTripsModel.fromJson(
Map<String,dynamic> json){
DriverTripsModel d =
DriverTripsModel();
d.id =
json['_id'] ?? '';
d.bookingId =
json['bookingid'] ?? '';
d.tankerName =
json['tankerName'] ?? '';
d.buildingName =
json['buildingName'] ?? '';
d.address =
json['address'] ?? '';
d.date =
json['dateOfOrder'] ?? '';
d.time =
json['time'] ?? '';
d.waterType =
json['typeofwater'] ?? '';
d.capacity =
json['capacity'] ?? '';
d.price =
json['price'] ?? '';
d.status =
json['orderStatus'] ?? '';
d.customerName =
json['customerName'] ?? '';
d.amountPaid =
json['amount_paid'] ?? '';
d.amountDue =
json['amount_due'] ?? '';
d.paymentStatus =
json['payment_status'] ?? '';
return d;
}
}

@ -3,13 +3,14 @@ class DriversModel {
String driver_name='';
String status='';
String address='';
String deliveries='13';
String deliveries='';
String commision='';
String years_of_experience='';
List<String> availability= ['filled', 'available'];
String phone_number='';
String alt_phone_number='';
String license_number='';
String license_expiry_date='';
DriversModel();
factory DriversModel.fromJson(Map<String, dynamic> json) {
@ -23,6 +24,8 @@ class DriversModel {
rtvm.alt_phone_number = json['alternativeContactNumber'] ?? '';
rtvm.years_of_experience = json['years_of_experience'] ?? '';
rtvm.license_number = json['license_number'] ?? '';
rtvm.deliveries = json['deliveries'] ?? '';
rtvm.license_expiry_date=json['license_number'] ?? '';
return rtvm;
}
}

@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/resources/driver_details.dart';
import 'package:supplier_new/resources/drivers_model.dart';
import 'package:url_launcher/url_launcher.dart';
class FirstCharUppercaseFormatter extends TextInputFormatter {
const FirstCharUppercaseFormatter();
@ -70,9 +71,9 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
// Dropdown state
String? _status; // 'available' | 'on delivery' | 'offline'
final List<String> _statusOptions = const [
'available',
'on delivery',
'offline'
'Available',
'On delivery',
'Offline'
];
String? selectedLicense;
@ -179,14 +180,14 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
// Build payload (adjust keys to your API if needed)
final payload = <String, dynamic>{
"Name": _nameCtrl.text.trim(),
"license_number": selectedLicense ?? "",
"license_number": _licenseController.text ?? "",
"address": _locationCtrl.text.trim().isEmpty
? AppSettings.userAddress
: _locationCtrl.text.trim(),
"supplier_name": AppSettings.userName,
"phone": _mobileCtrl.text.trim(),
"alternativeContactNumber": _altMobileCtrl.text.trim(),
"years_of_experience": selectedExperience ?? "",
"years_of_experience": _experienceController.text ?? "",
"status": _status ?? "available",
};
@ -555,10 +556,10 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
Text(driversList.length.toString(),
style: fontTextStyle(
24, const Color(0xFF0D3771), FontWeight.w500)),
const SizedBox(height: 6),
/* const SizedBox(height: 6),
Text('+1 since last month',
style: fontTextStyle(
10, const Color(0xFF646566), FontWeight.w400)),
10, const Color(0xFF646566), FontWeight.w400)),*/
],
),
],
@ -692,9 +693,9 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
name: d.driver_name,
status: d.status,
location: d.address,
deliveries:
int.tryParse(d.deliveries) ?? 0,
deliveries: int.tryParse(d.deliveries) ?? 0,
commission: d.commision,
phone: d.phone_number, // ADD
),
);
},
@ -758,6 +759,7 @@ class DriverCard extends StatelessWidget {
final String location;
final int deliveries;
final String commission;
final String phone;
const DriverCard({
super.key,
@ -766,6 +768,7 @@ class DriverCard extends StatelessWidget {
required this.location,
required this.deliveries,
required this.commission,
required this.phone,
});
@override
@ -777,6 +780,19 @@ class DriverCard extends StatelessWidget {
_ => Colors.grey,
};
Future<void> _makePhoneCall(String phone) async {
final Uri url = Uri(
scheme: 'tel',
path: phone,
);
if(await canLaunchUrl(url)){
await launchUrl(url);
}
}
return Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
@ -818,15 +834,23 @@ class DriverCard extends StatelessWidget {
),
],
),
Container(
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Color(0xFFF5F6F6),
shape: BoxShape.circle,
GestureDetector(
onTap: (){
_makePhoneCall(phone);
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Color(0xFFF5F6F6),
shape: BoxShape.circle,
),
child: Image.asset(
"images/phone_icon.png",
width: 20,
height: 20,
),
),
child:
Image.asset("images/phone_icon.png", width: 20, height: 20),
),
)
],
),
const SizedBox(height: 12),
@ -882,7 +906,7 @@ class DriverCard extends StatelessWidget {
),)
],
),
const SizedBox(height: 12),
/* const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
@ -910,7 +934,7 @@ class DriverCard extends StatelessWidget {
12, const Color(0xFFFFFFFF), FontWeight.w400)),
),
],
)
)*/
],
),
);

@ -485,10 +485,10 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
tankersList.length.toString(),
style: fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500),
),
const SizedBox(height: 6),
/*const SizedBox(height: 6),
Text('+2 since last month',
style: fontTextStyle(10, const Color(0xFF646566), FontWeight.w400),
),
),*/
],
),
],

@ -517,10 +517,18 @@ class _SourceDetailsScreenState extends State<SourceDetailsScreen> {
},
child:Scaffold(
backgroundColor: Colors.white,
appBar:AppSettings.supplierAppBarWithActionsText( widget.sourceDetails.source_name.isNotEmpty
? widget.sourceDetails.source_name[0].toUpperCase() +
widget.sourceDetails.source_name.substring(1)
: '', context),
appBar: AppSettings.supplierAppBarWithActionsText(
widget.sourceDetails.source_name.isNotEmpty
? widget.sourceDetails.source_name[0].toUpperCase() +
widget.sourceDetails.source_name.substring(1)
: '',
context,
result: true // ADD THIS
),
body: SingleChildScrollView(
child:
Column(
@ -708,7 +716,7 @@ class _SourceDetailsScreenState extends State<SourceDetailsScreen> {
// Filling & Wait time cards
Padding(
/* Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
@ -810,7 +818,7 @@ class _SourceDetailsScreenState extends State<SourceDetailsScreen> {
);
},
),
const SizedBox(height: 20),
const SizedBox(height: 20),*/
],))));
}
}

@ -79,25 +79,43 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
@override
void initState() {
super.initState();
_nameCtrl.text = widget.tankerDetails.tanker_name ?? '';
_nameCtrl.text =
widget.tankerDetails.tanker_name ?? '';
/// FIX allow null availability
if (widget.tankerDetails.availability != null &&
widget.tankerDetails.availability is List &&
widget.tankerDetails.availability.length == 2) {
final a = widget.tankerDetails.availability;
currentAvailability = "${a[0]}|${a[1]}";
_fetchTankerTrips();
final a =
widget.tankerDetails.availability;
currentAvailability =
"${a[0]}|${a[1]}";
}
else{
/// default status if null
currentAvailability =
"empty|available";
}
}
/// ALWAYS FETCH TRIPS
_fetchTankerTrips();
}
Future<void> _fetchTankerTrips() async {
setState(() => isTankerTripsLoading = true);
try {
var payload = new Map<String, dynamic>();
payload["customerId"] = widget.tankerDetails.tanker_name;
payload["tankerName"] = widget.tankerDetails.tanker_name;
payload["tankerName"] =
widget.tankerDetails.tanker_name;
final response = await AppSettings.getTankerTrips(payload);
final data = (jsonDecode(response)['data'] as List)
@ -823,11 +841,17 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
child: Scaffold(
backgroundColor: Color(0XFFF1F1F1),
appBar: AppSettings.supplierAppBarWithActionsText(
widget.tankerDetails.tanker_name.isNotEmpty
? widget.tankerDetails.tanker_name[0].toUpperCase() +
widget.tankerDetails.tanker_name.substring(1)
: '',
context),
context,
result: true // ADD THIS
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(0),
@ -1128,11 +1152,11 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
),
Padding(
padding: EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"RECENT TRIPS",
style: fontTextStyle(
@ -1140,89 +1164,108 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
const Color(0xFF343637),
FontWeight.w600),
),
const SizedBox(height: 12),
_buildTripCard(
driverName: "Ramesh Krishna",
time:
"7:02 PM, 28 Jun 2025",
from:
"Bachupally Filling Station",
to: "Akriti Heights",
),
const SizedBox(height: 8),
_buildTripCard(
driverName: "Ramesh Krishna",
time:
"12:44 PM, 26 Jun 2025",
from:
"Bachupally Filling Station",
to: "Akriti Heights",
isTankerTripsLoading
? const Center(
child: CircularProgressIndicator())
: tankerTripsList.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(
itemCount: tankerTripsList.length,
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
separatorBuilder: (_, __) =>
const SizedBox(height: 10),
itemBuilder: (context, idx) {
final it = tankerTripsList[idx];
/// DRIVER NAME
String driverName =
(it.driver_name != "" &&
it.driver_name != "null")
? it.driver_name
: it.supplierName;
/// DATE + TIME
String tripTime = "";
if(it.dateOfOrder.isNotEmpty &&
it.time.isNotEmpty){
tripTime =
"${it.dateOfOrder}${it.time}";
}
else{
tripTime = "-";
}
/// PICKUP LOCATION
String pickupLocation =
(it.water_source_location.isNotEmpty &&
it.water_source_location != "null")
? it.water_source_location
: "Water Source";
/// DELIVERY LOCATION
String deliveryLocation =
(it.building_name.isNotEmpty)
? it.building_name
: it.address;
return _buildTripCard(
driverName: driverName,
time: tripTime,
from: pickupLocation,
to: deliveryLocation,
);
},
),
],
),
),
// FIX Removed Expanded (illegal inside ScrollView)
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16),
child: isTankerTripsLoading
? const Center(
child:
CircularProgressIndicator())
: tankerTripsList.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(
itemCount:
tankerTripsList
.length,
shrinkWrap: true, // Fix
physics:
NeverScrollableScrollPhysics(), // Fix
separatorBuilder:
(_, __) =>
const SizedBox(
height:
10),
itemBuilder:
(context, idx) {
final it =
tankerTripsList[
idx];
return GestureDetector(
onTap: () async {},
child: _buildTripCard(
driverName:
it.driver_name,
time:
"7:02 PM, 28 Jun 2025",
from:
"Bachupally Filling Station",
to:
"Akriti Heights",
),
);
},
),
),
],
),
),
@ -1268,7 +1311,7 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
],
),
Text(
time,
time.isEmpty ? "-" : time,
style: const TextStyle(
fontSize: 11,
color: Colors.black54,

@ -1,29 +1,78 @@
class TankerTripsModel {
class TankerTripsModel {
String tanker_name = '';
String address = '';
String dbId = '';
String driver_name = '';
String status = '';
String building_name = '';
String water_source_location='';
String deliveredDate='';
String water_source_location = '';
String deliveredDate = '';
/// ADD THESE
String dateOfOrder = '';
String time = '';
String supplierName = '';
String amount_paid = '';
String amount_due = '';
TankerTripsModel();
factory TankerTripsModel.fromJson(Map<String, dynamic> json){
TankerTripsModel rtvm = new TankerTripsModel();
rtvm.tanker_name = json['tankerName']?? '';
rtvm.dbId = json['_id']?? '';
rtvm.address = json['supplier_address']?? '';
rtvm.driver_name = json['delivery_agent']?? '';
rtvm.status = json['orderStatus']?? '';
rtvm.building_name = json['buildingName']?? '';
rtvm.water_source_location = json['water_source_location']?? '';
rtvm.deliveredDate = json['deliveredDate']?? '';
factory TankerTripsModel.fromJson(
Map<String, dynamic> json){
TankerTripsModel rtvm =
TankerTripsModel();
rtvm.tanker_name =
json['tankerName'] ?? '';
rtvm.dbId =
json['_id'] ?? '';
/// FIX (you used wrong key)
rtvm.address =
json['address'] ?? '';
rtvm.driver_name =
json['delivery_agent'] ?? '';
rtvm.status =
json['orderStatus'] ?? '';
rtvm.building_name =
json['buildingName'] ?? '';
rtvm.water_source_location =
json['water_source_location'] ?? '';
rtvm.deliveredDate =
json['deliveredDate'] ?? '';
/// ADD THESE
rtvm.dateOfOrder =
json['dateOfOrder'] ?? '';
rtvm.time =
json['time'] ?? '';
rtvm.supplierName =
json['supplierName'] ?? '';
rtvm.amount_paid =
json['amount_paid'] ?? '';
rtvm.amount_due =
json['amount_due'] ?? '';
return rtvm;
}
Map<String, dynamic> toJson() => {
"boreName":this.tanker_name,
"tankerName": tanker_name,
};
}

@ -1,180 +1,372 @@
import 'package:flutter/material.dart';
import 'package:sms_autofill/sms_autofill.dart';
import 'package:supplier_new/signup/password_textbox_screen.dart';
import '../common/settings.dart';
class Otpscreen extends StatefulWidget {
var mobileNumber;
Otpscreen({
this.mobileNumber
final String mobileNumber;
const Otpscreen({
super.key,
required this.mobileNumber
});
@override
State<Otpscreen> createState() => _OtpscreenState();
}
class _OtpscreenState extends State<Otpscreen> {
final List<TextEditingController> _controllers = List.generate(6, (index) => TextEditingController());
final FocusNode _focusNode = FocusNode();
class _OtpscreenState extends State<Otpscreen>
with CodeAutoFill {
String otpCode = "";
bool isLoading = false;
int seconds = 30;
bool canResend = false;
@override
void dispose() {
_controllers.forEach((controller) => controller.dispose());
_focusNode.dispose();
super.dispose();
void initState(){
super.initState();
listenForCode();
startTimer();
}
void startTimer(){
Future.delayed(const Duration(seconds:1),(){
if(seconds>0){
setState(()=>seconds--);
startTimer();
}
else{
setState(()=>canResend=true);
}
});
}
@override
void codeUpdated(){
setState((){
otpCode = code!;
});
if(otpCode.length==6){
verifyOtp();
}
}
Future<void> verifyOtp() async{
if(isLoading) return;
if(otpCode.length!=6){
AppSettings.longFailedToast(
"Enter 6 digit OTP");
return;
}
setState(()=>isLoading=true);
AppSettings.preLoaderDialog(context);
bool isOnline =
await AppSettings.internetConnectivity();
if(isOnline){
var payload={
"phoneVerificationCode":otpCode,
"phone":widget.mobileNumber
};
bool status =
await AppSettings.verifyPhn(payload);
Navigator.pop(context);
if(status){
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder:(_)=>
PasswordTextBoxesScreen(
mobileNumber:
widget.mobileNumber),
),
);
}
else{
AppSettings.longFailedToast(
"Invalid OTP");
}
}
else{
Navigator.pop(context);
AppSettings.longFailedToast(
"Check internet");
}
setState(()=>isLoading=false);
}
void _submitOtp() {
final otp = _controllers.map((controller) => controller.text).join();
print("Entered OTP: $otp");
// Add OTP validation or submission logic here
String maskNumber(String number){
return "*******${number.substring(7)}";
}
Future<void> resendOtp() async{
if(!canResend) return;
var payload={
"mobileNumbers":
widget.mobileNumber
};
await AppSettings.getOtp(payload);
setState((){
seconds=30;
canResend=false;
});
startTimer();
String maskMobileNumber(String number) {
if (number.length < 3) return number; // Handle invalid numbers
final stars = '*' * (number.length - 3);
final lastThree = number.substring(number.length - 3);
return '$stars$lastThree';
}
@override
void dispose(){
cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
Widget build(BuildContext context){
return Scaffold(
body: Stack(children: <Widget>[
/*Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("images/backgroundimage.png"),
fit: BoxFit.cover,
backgroundColor:Colors.white,
body:SafeArea(
child:Padding(
padding:
const EdgeInsets.all(24),
child:Column(
children:[
const Spacer(),
Text(
"Enter OTP",
style:fontTextStyle(
20,
Color(0XFF101214),
FontWeight.w700),
),
const SizedBox(height:10),
Text(
"Code sent to +91 ${maskNumber(widget.mobileNumber)}",
style:fontTextStyle(
12,
Color(0XFF7E7F80),
FontWeight.w400),
),
const SizedBox(height:40),
/// OTP BOX
PinFieldAutoFill(
codeLength:6,
currentCode:otpCode,
onCodeChanged:(code){
otpCode=code??"";
},
decoration:
BoxLooseDecoration(
radius:
const Radius.circular(8),
strokeColorBuilder:
FixedColorBuilder(
primaryColor),
textStyle:
fontTextStyle(
18,
Color(0XFF101214),
FontWeight.w600),
),
),
const SizedBox(height:30),
/// TIMER
canResend
? GestureDetector(
onTap:resendOtp,
child:Text(
"Resend OTP",
style:fontTextStyle(
14,
primaryColor,
FontWeight.w600),
),
)
: Text(
"Resend in 00:$seconds",
style:fontTextStyle(
12,
Color(0XFF7E7F80),
FontWeight.w500),
),
),
),*/
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.fromLTRB(24, 0, 24, 0),
child: Column(children: <Widget>[
SizedBox(height:MediaQuery.of(context).size.height * .2,),
Container(
child: Text(
'Enter confirmation code',
style: fontTextStyle(16,Color(0XFF101214),FontWeight.w800),
),
),
SizedBox(height:MediaQuery.of(context).size.height * .02,),
Container(
child: Text(
'A 6-digit code was sent to +91${maskMobileNumber(widget.mobileNumber)}',
style: fontTextStyle(12,Color(0XFF7E7F80),FontWeight.w400),
),
),
SizedBox(height:MediaQuery.of(context).size.height * .040,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(6, (index) {
return SizedBox(
width: 50,
child: TextFormField(
cursorColor:primaryColor,
controller: _controllers[index],
focusNode: index == 0 ? _focusNode : null,
maxLength: 1,
textAlign: TextAlign.center,
style: fontTextStyle(14,Color(0XFF101214),FontWeight.w400),
keyboardType: TextInputType.number,
decoration: textFormFieldDecoration(Icons.ice_skating, ''),
onChanged: (value) {
if (value.isNotEmpty && index < 5) {
FocusScope.of(context).nextFocus();
} else if (value.isEmpty && index > 0) {
FocusScope.of(context).previousFocus();
}
},
),
);
}),
),
SizedBox(height:MediaQuery.of(context).size.height * .08,),
GestureDetector(
onTap: (){
},
child: Text('Resend code',style:fontTextStyle(12,Color(0XFF1D7AFC),FontWeight.w600),),
),
SizedBox(height:MediaQuery.of(context).size.height * .024,),
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height * .06,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: primaryColor,
),
onPressed: () async{
AppSettings.preLoaderDialog(context);
bool isOnline = await AppSettings.internetConnectivity();
if(isOnline){
final otp = _controllers.map((controller) => controller.text).join();
if(otp.length==6){
var phoneVerifyPayload = new Map<String, dynamic>();
phoneVerifyPayload["phoneVerificationCode"] = otp.toString();
phoneVerifyPayload["phone"] = widget.mobileNumber.toString();
bool verifyPhnStatus = await AppSettings.verifyPhn(phoneVerifyPayload);
if (verifyPhnStatus) {
Navigator.of(context, rootNavigator: true).pop();
//AppSettings.longSuccessToast("User SignUp Successfully");
Navigator.push(
context,
new MaterialPageRoute(
builder: (__) => new PasswordTextBoxesScreen(mobileNumber: widget.mobileNumber,)));
/* await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const Login()),
);*/
} else {
Navigator.of(context, rootNavigator: true).pop();
AppSettings.longFailedToast("Phone verification failed");
}
}
else{
Navigator.of(context, rootNavigator: true).pop();
AppSettings.longFailedToast("Please enter 6 digit otp code");
}
}
else{
Navigator.of(context,rootNavigator: true).pop();
AppSettings.longFailedToast("Please Check internet");
}
},
child: Text('Continue',style:fontTextStyle(12,Color(0XFFFFFFFF),FontWeight.w600),),
)),
]),
)))),
]));
const SizedBox(height:40),
/// BUTTON
SizedBox(
width:double.infinity,
height:55,
child:ElevatedButton(
style:
ElevatedButton.styleFrom(
backgroundColor:
primaryColor,
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(24),
),
),
onPressed:verifyOtp,
child:isLoading
? const CircularProgressIndicator(
color:Colors.white)
:Text(
"Verify",
style:fontTextStyle(
16,
Colors.white,
FontWeight.w600),
),
),
),
const Spacer(),
],
),
),
),
);
}
}
}

@ -856,6 +856,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.15.0"
pin_input_text_field:
dependency: transitive
description:
name: pin_input_text_field
sha256: f45683032283d30b670ec343781660655e3e1953438b281a0bc6e2d358486236
url: "https://pub.dev"
source: hosted
version: "4.5.2"
platform:
dependency: transitive
description:
@ -965,6 +973,14 @@ packages:
description: flutter
source: sdk
version: "0.0.99"
sms_autofill:
dependency: "direct main"
description:
name: sms_autofill
sha256: c65836abe9c1f62ce411bb78d5546a09ece4297558070b1bd871db1db283aaf9
url: "https://pub.dev"
source: hosted
version: "2.4.1"
source_span:
dependency: transitive
description:

@ -36,6 +36,7 @@ dependencies:
table_calendar: ^3.0.2
photo_view: ^0.15.0
url_launcher: ^6.1.9
sms_autofill: ^2.4.0
dev_dependencies:
flutter_test:

Loading…
Cancel
Save