login and signup

master
gitadmin 5 hours ago
parent 9dc86047ed
commit 331fb02cd2

@ -150,6 +150,7 @@ class AppSettings{
static String loginUrl = host + 'supplierlogin';
static String signUpUrl = host + 'suppliers';
static String forgotPasswordUrl = host + 'forgotpassword';
static String sendSmsUrl = host + 'sendSms';
static String resetTokenUrl = host + 'reset_token';
static String verifyPhnUrl = host + 'phone';
static String uploadPicUrl = host + 'uploads-user';
@ -363,7 +364,7 @@ class AppSettings{
}
static Future<bool> getOtp(payload) async {
var uri = Uri.parse(forgotPasswordUrl);
var uri = Uri.parse(sendSmsUrl);
var response = await http.post(uri,
body: json.encode(payload), headers: await buildRequestHeaders());

@ -411,9 +411,15 @@ class _FleetEmployeesState extends State<FleetEmployees> {
_LabeledField(
label: "Years of Experience *",
child: TextFormField(
controller: _experienceController, // create controller
controller: _experienceController,
keyboardType: TextInputType.number,
autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly, // Only numbers
LengthLimitingTextInputFormatter(2), // Max 2 digits
],
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Years",
@ -425,9 +431,15 @@ class _FleetEmployeesState extends State<FleetEmployees> {
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;
},
),

@ -1,5 +1,6 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/profile/service_locations_radius.dart';
@ -19,12 +20,13 @@ class _ServiceLocationState extends State<ServiceLocation> {
final _formKey = GlobalKey<FormState>();
String _deliveryFrom = 'business';
final TextEditingController _radiusController =
TextEditingController(text: "10");
TextEditingController(text: "10");
bool _customizeEachSource = false;
bool isLoading = false;
int currentStep = 3;
List<SourceLocationsModel> sourceLocationsList = [];
Map<int, TextEditingController> radiusControllers = {};
Map<int, ValueNotifier<double>> radiusNotifiers = {};
// 🔹 Notifier for dynamic map radius
late final ValueNotifier<double> _radiusKmNotifier;
@ -64,25 +66,48 @@ class _ServiceLocationState extends State<ServiceLocation> {
Future<void> _fetchSources() async {
setState(() => isLoading = true);
try {
final response = await AppSettings.getSourceLoctaions();
final data = (jsonDecode(response)['data'] as List)
.map((e) => SourceLocationsModel.fromJson(e))
.toList();
if (!mounted) return;
setState(() {
sourceLocationsList = data;
isLoading = false;
for (var i = 0; i < data.length; i++) {
_expandedMap[i] = false;
// CREATE CONTROLLERS FOR EACH LOCATION
radiusControllers[i] = TextEditingController(text: "10");
radiusNotifiers[i] = ValueNotifier<double>(10);
// 🔁 update map when radius changes
radiusControllers[i]!.addListener(() {
final value = double.tryParse(radiusControllers[i]!.text);
radiusNotifiers[i]!.value =
(value == null || value <= 0) ? 10 : value;
});
}
});
} catch (e) {
debugPrint("⚠️ Error fetching source locations: $e");
setState(() => isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -184,6 +209,13 @@ class _ServiceLocationState extends State<ServiceLocation> {
TextFormField(
controller: _radiusController,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
FilteringTextInputFormatter.deny(RegExp(r'^0')),
LengthLimitingTextInputFormatter(3), // optional (max 999 km)
],
decoration: InputDecoration(
hintText: "Enter radius in kms",
hintStyle: fontTextStyle(
@ -194,6 +226,19 @@ class _ServiceLocationState extends State<ServiceLocation> {
contentPadding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 12),
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Enter radius";
}
if (int.tryParse(value)! <= 0) {
return "Radius must be greater than 0";
}
return null;
},
),
const SizedBox(height: 16),
Container(
@ -325,58 +370,66 @@ class _ServiceLocationState extends State<ServiceLocation> {
border: Border.all(
color: const Color(0xFFE5E5E5)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Delivery Radius (in Kms) *",
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Delivery Radius (in Kms) *",
style: fontTextStyle(
12,
const Color(0xFF2F3036),
FontWeight.w600)),
const SizedBox(height: 16),
TextFormField(
controller: _radiusController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: "Enter radius in kms",
hintStyle: fontTextStyle(
14,
const Color(0xFF939495),
FontWeight.w400),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8),
),
contentPadding:
const EdgeInsets.symmetric(
horizontal: 12, vertical: 12),
12, const Color(0xFF2F3036), FontWeight.w600),
),
),
const SizedBox(height: 16),
Container(
width: double.infinity,
height: 180,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(8),
border: Border.all(
color: const Color(0xFFE6E6E6)),
const SizedBox(height: 16),
TextFormField(
controller: radiusControllers[index],
keyboardType: TextInputType.number,
onChanged: (value) {
double radius = double.tryParse(value) ?? 0;
radiusNotifiers[index]!.value = radius;
},
decoration: InputDecoration(
hintText: "Enter radius in kms",
hintStyle: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
contentPadding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
),
),
child: ClipRRect(
borderRadius:
BorderRadius.circular(8),
child: ServiceLocationsRadiusScreen(
initialPosition: LatLng(
d.latitude ?? 17.3850,
d.longitude ?? 78.4867,
const SizedBox(height: 16),
Container(
width: double.infinity,
height: 180,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(color: const Color(0xFFE6E6E6)),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: ServiceLocationsRadiusScreen(
initialPosition: LatLng(
d.latitude ?? 17.3850,
d.longitude ?? 78.4867,
),
radiusKmListenable: radiusNotifiers[index]!,
),
radiusKmListenable:
_radiusKmNotifier,
),
),
),
],
),
],
)
),
],
),
@ -391,15 +444,17 @@ class _ServiceLocationState extends State<ServiceLocation> {
const SizedBox(height: 16),
Container(
width: double.infinity,
height: 250,
height: 220, // 👈 small map fits neatly
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFFE6E6E6)),
border:
Border.all(color: const Color(0xFFE6E6E6)),
borderRadius: BorderRadius.circular(8),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: ServiceLocationsRadiusScreen(
initialPosition: const LatLng(20.5937, 78.9629),
initialPosition:
const LatLng(17.381597, 78.481791),
radiusKmListenable: _radiusKmNotifier,
),
),

@ -299,9 +299,15 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
_LabeledField(
label: "Years of Experience *",
child: TextFormField(
controller: _experienceController, // create controller
controller: _experienceController,
keyboardType: TextInputType.number,
autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly, // Only numbers
LengthLimitingTextInputFormatter(2), // Max 2 digits
],
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Years",
@ -313,9 +319,15 @@ class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
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;
},
),

@ -292,21 +292,58 @@ class _ResourcesSourceScreenState extends State<ResourcesSourceScreen> {
),
_LabeledField(
label: "Mobile Number *",
label: "Phone Number *",
child: TextFormField(
controller: _mobileCtrl,
validator: (v) => _validatePhone(v, label: "Mobile Number"),
keyboardType: TextInputType.phone,
autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(10),
// Restrict first digit 6-9
TextInputFormatter.withFunction(
(oldValue, newValue) {
if (newValue.text.isEmpty) {
return newValue;
}
// First digit must be 6-9
if (!RegExp(r'^[6-9]').hasMatch(newValue.text)) {
return oldValue;
}
return newValue;
},
),
],
validator: (value) {
if (value == null || value.isEmpty) {
return "Phone Number required";
}
if (!RegExp(r'^[6-9]').hasMatch(value)) {
return "Enter digits starting 6,7,8,9";
}
if (value.length != 10) {
return "Enter valid 10 digit number";
}
return null;
},
decoration: InputDecoration(
hintText: "Mobile Number",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
hintStyle: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
textInputAction: TextInputAction.next,
),
),

@ -1,6 +1,7 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:supplier_new/common/settings.dart';
import '../resources/tankers_model.dart';
@ -122,46 +123,61 @@ class _SetRatesScreenState extends State<SetRatesScreen>
super.dispose();
}
Widget buildTextField(String label, TextEditingController controller) {
Widget buildTextField(String hint, TextEditingController controller) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: TextField(
controller: controller,
cursorColor: primaryColor,
readOnly: false,
keyboardType: TextInputType.number,
decoration: InputDecoration(
counterText: '',
filled: false,
fillColor: Colors.white,
prefixIconConstraints: BoxConstraints(
minWidth: 24,
minHeight: 24,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(
color: Color(0XFFC3C4C4),
width: 1,
)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(
color: Color(0XFF8270DB),
width: 1,
),
padding: const EdgeInsets.symmetric(vertical: 8),
child: TextFormField(
controller: controller,
cursorColor: primaryColor,
keyboardType: TextInputType.number,
// blocks -, +, . and all special chars (only digits)
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(5), // adjust if needed
],
decoration: InputDecoration(
counterText: '',
filled: false,
fillColor: Colors.white,
prefixIconConstraints: const BoxConstraints(
minWidth: 24,
minHeight: 24,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(
color: Color(0XFFC3C4C4),
width: 1,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(color: Color(0XFFC3C4C4)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(
color: Color(0XFF8270DB),
width: 1,
),
hintText: label,
hintStyle: fontTextStyle(14, Color(0XFF939495), FontWeight.w400),
/* TextStyle(color: greyColor, fontWeight: FontWeight.bold //<-- SEE HERE
),*/
),
style: fontTextStyle(14, Color(0XFF515253), FontWeight.w500),
));
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(color: Color(0XFFC3C4C4)),
),
hintText: hint,
hintStyle: fontTextStyle(14, const Color(0XFF939495), FontWeight.w400),
),
style: fontTextStyle(14, const Color(0XFF515253), FontWeight.w500),
// optional: if you later wrap with Form and call validate()
validator: (value) {
final v = (value ?? "").trim();
if (v.isEmpty) return "Enter price";
final n = int.tryParse(v) ?? 0;
if (n <= 0) return "Enter positive value";
return null;
},
),
);
}
Widget labelText(String label) {
@ -544,3 +560,5 @@ class _SetRatesScreenState extends State<SetRatesScreen>
);
}
}

@ -134,7 +134,7 @@ class _SignUpMobileNumberScreenState extends State<SignUpMobileNumberScreen> {
if(isOnline){
var payload = {
"phone":
"mobileNumbers":
mobileNumberController.text.trim()
};

Loading…
Cancel
Save