From 331fb02cd27675276e367da9b94f342c8d0514d6 Mon Sep 17 00:00:00 2001 From: gitadmin Date: Thu, 5 Mar 2026 15:49:14 +0530 Subject: [PATCH] login and signup --- lib/common/settings.dart | 3 +- lib/profile/employees.dart | 14 +- lib/profile/service_location.dart | 159 ++++++++++++++------- lib/resources/resources_drivers.dart | 14 +- lib/resources/resources_sources.dart | 43 +++++- lib/set_rates/set_rates.dart | 90 +++++++----- lib/signup/signup_mobilenumber_screen.dart | 2 +- 7 files changed, 230 insertions(+), 95 deletions(-) diff --git a/lib/common/settings.dart b/lib/common/settings.dart index 9a697fa..c5d9473 100644 --- a/lib/common/settings.dart +++ b/lib/common/settings.dart @@ -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 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()); diff --git a/lib/profile/employees.dart b/lib/profile/employees.dart index e1bd614..f9a717d 100644 --- a/lib/profile/employees.dart +++ b/lib/profile/employees.dart @@ -411,9 +411,15 @@ class _FleetEmployeesState extends State { _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 { 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; }, ), diff --git a/lib/profile/service_location.dart b/lib/profile/service_location.dart index a07801b..14c6644 100644 --- a/lib/profile/service_location.dart +++ b/lib/profile/service_location.dart @@ -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 { final _formKey = GlobalKey(); String _deliveryFrom = 'business'; final TextEditingController _radiusController = - TextEditingController(text: "10"); + TextEditingController(text: "10"); bool _customizeEachSource = false; bool isLoading = false; int currentStep = 3; List sourceLocationsList = []; - + Map radiusControllers = {}; + Map> radiusNotifiers = {}; // 🔹 Notifier for dynamic map radius late final ValueNotifier _radiusKmNotifier; @@ -64,25 +66,48 @@ class _ServiceLocationState extends State { Future _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(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 { 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 { 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 { 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 { 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, ), ), diff --git a/lib/resources/resources_drivers.dart b/lib/resources/resources_drivers.dart index 2f05598..3957216 100644 --- a/lib/resources/resources_drivers.dart +++ b/lib/resources/resources_drivers.dart @@ -299,9 +299,15 @@ class _ResourcesDriverScreenState extends State { _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 { 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; }, ), diff --git a/lib/resources/resources_sources.dart b/lib/resources/resources_sources.dart index f2db77f..dffc369 100644 --- a/lib/resources/resources_sources.dart +++ b/lib/resources/resources_sources.dart @@ -292,21 +292,58 @@ class _ResourcesSourceScreenState extends State { ), _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, ), ), diff --git a/lib/set_rates/set_rates.dart b/lib/set_rates/set_rates.dart index a06e851..a4e86a1 100644 --- a/lib/set_rates/set_rates.dart +++ b/lib/set_rates/set_rates.dart @@ -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 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 ); } } + + diff --git a/lib/signup/signup_mobilenumber_screen.dart b/lib/signup/signup_mobilenumber_screen.dart index d0ed280..c3d2648 100644 --- a/lib/signup/signup_mobilenumber_screen.dart +++ b/lib/signup/signup_mobilenumber_screen.dart @@ -134,7 +134,7 @@ class _SignUpMobileNumberScreenState extends State { if(isOnline){ var payload = { - "phone": + "mobileNumbers": mobileNumberController.text.trim() };