second commit
This commit is contained in:
281
lib/View/Authentication/Logiview.dart
Normal file
281
lib/View/Authentication/Logiview.dart
Normal file
@@ -0,0 +1,281 @@
|
||||
import 'package:country_currency_pickers/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:rounded_loading_button_plus/rounded_loading_button.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../Controller/Authentication/Authcontroller.dart';
|
||||
import '../../Globalwidgets/textwidget.dart';
|
||||
import '../../Globalwidgets/web_view.dart';
|
||||
import '../../Helper/Constants/Assetconstants.dart';
|
||||
import '../../Helper/Constants/Colorconstants.dart';
|
||||
import '../../Helper/custombutton.dart';
|
||||
import '../More/Faqview/privacy.dart';
|
||||
|
||||
class LoginView extends StatelessWidget {
|
||||
LoginView({super.key});
|
||||
|
||||
final AuthController authController = Get.put(AuthController());
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
SystemNavigator.pop();
|
||||
return Future.value(true);
|
||||
},
|
||||
child: GetBuilder<AuthController>(
|
||||
initState: (_) {
|
||||
authController.getHintPhoneNumber(context);
|
||||
},
|
||||
builder: (controller) {
|
||||
return SafeArea(
|
||||
top: false,
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(left: 15, right: 15),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Image.asset(
|
||||
AssetConstants.nearledailyImage,
|
||||
height: 300,
|
||||
width: 300,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: TextWidget(
|
||||
text: "Enter Your Phone Number",
|
||||
color: ColorConstants.primaryColor,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Center(
|
||||
child: TextWidget(
|
||||
text: "We will send you the 6 digit verification code",
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
TextWidget(
|
||||
text: "Let's Get Started",
|
||||
color: ColorConstants.primaryColor,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 18,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
contactNo(context),
|
||||
const SizedBox(height: 20),
|
||||
// const SizedBox(height: 0),
|
||||
// SizedBox(
|
||||
// height: 100,
|
||||
// child: submit(context),
|
||||
// ),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
terms();
|
||||
},
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: controller.termsChecking
|
||||
? Colors.green
|
||||
: Colors.white,
|
||||
border: Border.all(
|
||||
color: controller.termsChecking
|
||||
? Colors.green
|
||||
: Colors.grey[400]!,
|
||||
),
|
||||
),
|
||||
child: controller.termsChecking
|
||||
? const Icon(
|
||||
Icons.check,
|
||||
color: Colors.white,
|
||||
size: 19,
|
||||
)
|
||||
: const SizedBox(),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
"I agree to the Terms and &",
|
||||
style: TextStyle(
|
||||
color: ColorConstants.darkGreyColor,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 3),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => const WebViewApp(
|
||||
url: 'https://nearle.in/privacy',
|
||||
appBarText: 'Privacy Policy',
|
||||
));
|
||||
},
|
||||
child: Text(
|
||||
"Privacy Policy",
|
||||
style: TextStyle(
|
||||
color: ColorConstants.darkGreyColor,
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 80), // Space so button doesn't overlap
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: SizedBox(
|
||||
height: 100,
|
||||
child: submit(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget contactNo(context) {
|
||||
return TextFormField(
|
||||
buildCounter: (BuildContext context,
|
||||
{int? currentLength, int? maxLength, bool? isFocused}) =>
|
||||
null,
|
||||
maxLength: 10,
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(signed: true, decimal: true),
|
||||
controller: authController.loginPhoneNumberController,
|
||||
onChanged: (value){
|
||||
if(value.length==10){
|
||||
FocusScope.of(context).unfocus();
|
||||
|
||||
}
|
||||
},
|
||||
onTap: () async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString('Code_Currency',
|
||||
authController.selectedDialogCountry.currencyCode!);
|
||||
prefs.setString('Currency_Code',
|
||||
authController.selectedDialogCountry.currencyCode!);
|
||||
prefs.setString('Country_Code',
|
||||
authController.selectedDialogCountry.isoCode!);
|
||||
prefs.setString('dialCode',
|
||||
'+${authController.selectedDialogCountry.phoneCode!}');
|
||||
prefs.setString('location_Country',
|
||||
authController.selectedDialogCountry.isoCode!);
|
||||
authController.currency();
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Mobile Number',
|
||||
labelStyle: const TextStyle(color: Colors.grey),
|
||||
prefixIcon: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: Get.width * 0.3,
|
||||
height: Get.height * 0.04,
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 25,
|
||||
),
|
||||
InkWell(
|
||||
child: CountryPickerUtils.getDefaultFlagImage(
|
||||
authController.selectedDialogCountry),
|
||||
// onTap: _openCountryPickerDialog,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Text(
|
||||
"+${authController.selectedDialogCountry.phoneCode}"),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(7.0),
|
||||
borderSide: const BorderSide(
|
||||
color: Color.fromRGBO(220, 220, 220, 0.6),
|
||||
width: 2.0,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(7.0),
|
||||
borderSide: const BorderSide(
|
||||
color: Color.fromRGBO(220, 220, 220, 0.6),
|
||||
width: 2.0,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(7.0),
|
||||
borderSide: const BorderSide(
|
||||
color: ColorConstants.primaryColor,
|
||||
width: 1.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool terms() {
|
||||
authController.update();
|
||||
authController.termsChecking = !authController.termsChecking;
|
||||
return authController.termsChecking;
|
||||
}
|
||||
|
||||
Widget submit(context) {
|
||||
return GetBuilder<AuthController>(
|
||||
builder: (controller) {
|
||||
return RoundedLoadingButton(
|
||||
color: ColorConstants.primaryColor,
|
||||
width: Get.width,
|
||||
controller: controller.loginController,
|
||||
onPressed: () {
|
||||
controller.loginTenant(context);
|
||||
},
|
||||
child: TextWidget(
|
||||
text: 'Next',
|
||||
fontSize: 18,
|
||||
color: ColorConstants.secondaryColor,
|
||||
fontWeight: FontWeight.w700,
|
||||
)
|
||||
);
|
||||
// RoundedButton(
|
||||
// height: Get.height*0.06,
|
||||
// width: Get.width,
|
||||
// onPressed: () {
|
||||
// controller.loginTenant(context);
|
||||
// },
|
||||
// color: ColorConstants.primaryColor,
|
||||
// title: 'Next',
|
||||
// controller: controller.btnController,
|
||||
// textStyle: const TextStyle(
|
||||
// fontSize: 18,
|
||||
// fontFamily: "Lato",
|
||||
// color: Colors.white,
|
||||
// fontWeight: FontWeight.bold),
|
||||
// );
|
||||
});
|
||||
}
|
||||
}
|
||||
334
lib/View/Authentication/Otpverification.dart
Normal file
334
lib/View/Authentication/Otpverification.dart
Normal file
@@ -0,0 +1,334 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:otp_timer_button/otp_timer_button.dart';
|
||||
import 'package:pinput/pinput.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:sms_autofill/sms_autofill.dart';
|
||||
import '../../Controller/Authentication/Authcontroller.dart';
|
||||
import '../../Helper/Constants/Colorconstants.dart';
|
||||
import '../../Helper/Logger.dart';
|
||||
import '../../Helper/toast.dart';
|
||||
import '../Home/Homeview.dart';
|
||||
import 'Usercreate/Usercreateview.dart';
|
||||
|
||||
class OTPVerification extends StatelessWidget {
|
||||
final String otp;
|
||||
final int authmode;
|
||||
final bool? logInStatus;
|
||||
// final int? activeStatus;
|
||||
|
||||
OTPVerification({super.key, this.otp="",this.authmode=0, this.logInStatus});
|
||||
|
||||
final AuthController authController = AuthController();
|
||||
|
||||
final defaultPinTheme = PinTheme(
|
||||
width: 60,
|
||||
height: 56,
|
||||
textStyle: const TextStyle(fontSize: 20, color: Colors.black, fontWeight: FontWeight.w600),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: ColorConstants.primaryColor),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetBuilder<AuthController>(
|
||||
initState: (_) {
|
||||
// authController.loginController.reset();
|
||||
},
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: ColorConstants.secondaryColor,
|
||||
body: Column(
|
||||
children: [
|
||||
SizedBox(height: 20,),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.elliptical(40, 40),
|
||||
topRight: Radius.elliptical(40, 40)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20, vertical: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
|
||||
},
|
||||
child: Icon(Icons.arrow_back, color: Colors.grey[700],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10,),
|
||||
Text("Verification",
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontFamily: "Lato",
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.grey[700])),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text("Please enter your 6 digit One-Time-Password",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Lato",
|
||||
color: Colors.grey[600])),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20),
|
||||
child: SizedBox(
|
||||
width: 400,
|
||||
child: PinFieldAutoFill(
|
||||
controller: TextEditingController(text: controller.otpController.text), // Correct usage
|
||||
textInputAction: TextInputAction.done,
|
||||
onCodeChanged: (code) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
if (controller.resendOtp == code) {
|
||||
if (authmode == 1) {
|
||||
code = controller.resendOtp ?? '';
|
||||
}
|
||||
if (logInStatus == true) {
|
||||
logger.i('Login status : $logInStatus');
|
||||
prefs.setString('tenantContactNo', controller.contactNo ?? '');
|
||||
prefs.setString('userFcmToken', controller.userFcmToken ?? '');
|
||||
Get.to(() => HomeView(selectedIndex: 0));
|
||||
} else {
|
||||
if (code == controller.resendOtp) {
|
||||
Get.to(() => CreateUserView(
|
||||
phNumber: controller.loginPhoneNumberController.text,),
|
||||
);
|
||||
}
|
||||
else{
|
||||
controller.otpController.clear();
|
||||
Toast.showToast('Please Enter Valid Otp');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
keyboardType:TextInputType.number ,
|
||||
autoFocus: true,
|
||||
onCodeSubmitted: (code){
|
||||
if(code != controller.resendOtp){
|
||||
controller.otpController.clear();
|
||||
logger.i('otpCompleted ${controller.resendOtp}');
|
||||
Toast.showToast('Please Enter Valid Otp');
|
||||
}
|
||||
},
|
||||
decoration: BoxLooseDecoration(
|
||||
textStyle: const TextStyle(fontSize: 20, color: Colors.black),
|
||||
radius: const Radius. circular(8.0),
|
||||
strokeColorBuilder: FixedColorBuilder(Colors.black.withOpacity(0.3)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(left: 20, right: 20),
|
||||
// child: Pinput(
|
||||
// defaultPinTheme: defaultPinTheme,
|
||||
// pinContentAlignment: Alignment.center,
|
||||
//
|
||||
// length: 6,
|
||||
// autofocus: true,
|
||||
// keyboardType: TextInputType.number,
|
||||
// androidSmsAutofillMethod: AndroidSmsAutofillMethod.smsUserConsentApi,
|
||||
// pinAnimationType: PinAnimationType.fade,
|
||||
// controller: controller.otpController,
|
||||
// pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
|
||||
// animationDuration: const Duration(milliseconds: 300),
|
||||
// // Pass it here
|
||||
// onChanged: (text) async{
|
||||
// SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// // controller.smsOtp = text;
|
||||
// // Check if the entered text is a valid phone number
|
||||
// if (controller.resendOtp == text) {
|
||||
// if(authmode == 1){
|
||||
// text = controller.resendOtp??'';
|
||||
// }
|
||||
// if(logInStatus == true){
|
||||
// prefs.setString('tenantContactNo',controller.contactNo ?? '');
|
||||
// prefs.setString('tenantFcmToken', controller.userFcmToken ?? '');
|
||||
// logger.i('Inside the login true status');
|
||||
// Get.to(()=>HomeView(selectedIndex: 0));
|
||||
// }else{
|
||||
// logger.i('Inside the login false status');
|
||||
// Get.to(() => CreateUserView(phNumber: controller.loginPhoneNumberController.text,));
|
||||
// // showModalBottomSheet(
|
||||
// // context: Get.context!,
|
||||
// // isDismissible: true,
|
||||
// // backgroundColor: ColorConstants.secondaryColor,
|
||||
// // shape: const RoundedRectangleBorder(
|
||||
// // borderRadius: BorderRadius.only(
|
||||
// // topLeft: Radius.circular(20.0), topRight: Radius.circular(20)),
|
||||
// // ),
|
||||
// // builder: (context) {
|
||||
// // return Column(
|
||||
// // mainAxisAlignment: MainAxisAlignment.start,
|
||||
// // crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// // children: [
|
||||
// // SizedBox(
|
||||
// // height: Get.height * 0.3,
|
||||
// // // width: Get.width * 0.10,
|
||||
// // child: Padding(
|
||||
// // padding: const EdgeInsets.only(bottom: 0),
|
||||
// // child: Center(child: Lottie.asset('assets/images/nodatafound.json',)),
|
||||
// // ),
|
||||
// // ),
|
||||
// // const SizedBox(height: 15,),
|
||||
// // SizedBox(
|
||||
// // width: Get.width*0.85,
|
||||
// // child: Center(
|
||||
// // child: Text(
|
||||
// // "Oops, we couldn't find your account. Instead, would you like to create a new one?",
|
||||
// // style: TextStyle(
|
||||
// // fontSize: 18,
|
||||
// // fontFamily: "Inter",
|
||||
// // fontWeight: FontWeight.normal,
|
||||
// // color: ColorConstants.blackColor),
|
||||
// // maxLines: 3,
|
||||
// // textAlign: TextAlign.center,
|
||||
// //
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// // const Spacer(),
|
||||
// // Row(
|
||||
// // mainAxisAlignment: MainAxisAlignment.center,
|
||||
// // crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// // children: [
|
||||
// // InkWell(
|
||||
// // onTap: (){
|
||||
// // Get.to(CreateUserView(phNumber: controller.loginPhoneNumberController.text,));
|
||||
// // },
|
||||
// // child: Container(
|
||||
// // height: Get.height*0.06,
|
||||
// // width: Get.width*0.4,
|
||||
// // decoration: BoxDecoration(color: ColorConstants.primaryColor,borderRadius: BorderRadius.circular(10),),
|
||||
// // child: Center(child: Text('Create Account',style: TextStyle(color: ColorConstants.secondaryColor,fontSize: 16,))),
|
||||
// // ),
|
||||
// // ),
|
||||
// // const SizedBox(width: 10,),
|
||||
// // InkWell(
|
||||
// // onTap: (){
|
||||
// // Get.back();
|
||||
// // },
|
||||
// // child: Container(
|
||||
// // height: Get.height*0.06,
|
||||
// // width: Get.width*0.4,
|
||||
// // decoration: BoxDecoration(color: ColorConstants.primaryColor,borderRadius: BorderRadius.circular(10),),
|
||||
// // child: Center(child: Text('Cancel',style: TextStyle(color: ColorConstants.secondaryColor,fontSize: 16,))),
|
||||
// // ),
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // const SizedBox(height: 20,)
|
||||
// //
|
||||
// //
|
||||
// // ],
|
||||
// // );
|
||||
// // }
|
||||
// // );
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// onCompleted:(text){
|
||||
// if( text != controller.resendOtp){
|
||||
// controller.otpController.clear();
|
||||
// print('textonCompleted $text');
|
||||
// print('otpCompleted ${controller.resendOtp}');
|
||||
// Toast.showToast('Please Enter Valid Otp');
|
||||
// }
|
||||
//
|
||||
// },
|
||||
//
|
||||
//
|
||||
// ),
|
||||
// ),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
controller.authmode == 1 ?Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container()
|
||||
],
|
||||
):Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text("Didn't receive the code? ",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontFamily: "Lato",
|
||||
color: Colors.grey[600])),
|
||||
OtpTimerButton(
|
||||
controller: controller.otpTimerController,
|
||||
onPressed: () {
|
||||
controller.otpTimerController.startTimer();
|
||||
controller.textEditingController.clear();
|
||||
controller.codeSent = true;
|
||||
controller.sendSmsOtp(controller.loginPhoneNumberController.text.trim());
|
||||
controller.update();
|
||||
},
|
||||
text: Text('Resend Again',style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontFamily: "Lato",
|
||||
color: ColorConstants.primaryColor
|
||||
),),
|
||||
duration: 60,
|
||||
buttonType: ButtonType.text_button,
|
||||
textColor: ColorConstants.primaryColor,
|
||||
// backgroundColor: ColorConstants.primaryColor,
|
||||
)
|
||||
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
|
||||
//submit(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// const Spacer(),
|
||||
// Container(
|
||||
// height: Get.height * 0.1,
|
||||
// width: Get.width,
|
||||
// decoration: const BoxDecoration(
|
||||
// image: DecorationImage(
|
||||
// image: AssetImage(
|
||||
// AssetConstants.nearleAppbarBottom,
|
||||
// ),
|
||||
// fit: BoxFit.fill),
|
||||
// // color: ColorConstants.primaryColor,
|
||||
// borderRadius: BorderRadius.only(
|
||||
// bottomLeft: Radius.elliptical(2, 2),
|
||||
// bottomRight: Radius.elliptical(2, 2))),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
446
lib/View/Authentication/Usercreate/Usercreateview.dart
Normal file
446
lib/View/Authentication/Usercreate/Usercreateview.dart
Normal file
@@ -0,0 +1,446 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../Controller/Authentication/Createtenantusercontroller.dart';
|
||||
import '../../../Globalwidgets/textwidget.dart';
|
||||
import '../../../Helper/Constants/AssetConstants.dart';
|
||||
import '../../../Helper/Constants/Colorconstants.dart';
|
||||
import '../../../Helper/Logger.dart';
|
||||
import '../../../Helper/custombutton.dart';
|
||||
import '../../../Helper/customederaction.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../Logiview.dart';
|
||||
|
||||
class CreateUserView extends StatelessWidget {
|
||||
final String? phNumber;
|
||||
CreateUserView({super.key, this.phNumber});
|
||||
|
||||
final CreateUserController controller = Get.put(CreateUserController());
|
||||
final ScrollController listScrollController = ScrollController();
|
||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
top: false,
|
||||
child: Scaffold(
|
||||
key: scaffoldKey,
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: true,
|
||||
leading: InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => LoginView());
|
||||
},
|
||||
child: Icon(
|
||||
Icons.arrow_back,
|
||||
color: ColorConstants.blackColor,
|
||||
),
|
||||
),
|
||||
title: TextWidget(
|
||||
text: 'Create Account',
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
body: GetBuilder<CreateUserController>(
|
||||
initState: (_) {
|
||||
controller.contactNoController.text = phNumber ?? '';
|
||||
logger.i('Phone Number: ${controller.contactNoController.text}');
|
||||
controller.getAppLocations();
|
||||
controller.getCurrentLocation();
|
||||
controller.getAppCategory();
|
||||
|
||||
logger.i('Cat Name Is empty : ${controller.catName}');
|
||||
},
|
||||
builder: (controller) => Column(
|
||||
children: [
|
||||
// _buildHeader(),
|
||||
// const SizedBox(height: 10,),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
controller: listScrollController,
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||
children: [
|
||||
SizedBox(height: 10,),
|
||||
Center(
|
||||
child: Stack(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
controller.getProfileImage();
|
||||
},
|
||||
child: Container(
|
||||
width: 100,
|
||||
// Set the size to match the CircleAvatar's diameter
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: ColorConstants.primaryColor, // Border color
|
||||
width: 2.0, // Border width
|
||||
),
|
||||
),
|
||||
child: CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundColor: ColorConstants.secondaryColor,
|
||||
child: ClipOval(
|
||||
child: controller.profileImage == null
|
||||
? Image.asset(
|
||||
AssetConstants.noProfile,
|
||||
width: 70,
|
||||
height: 70,
|
||||
color: ColorConstants.primaryColor,
|
||||
)
|
||||
: Image.file(
|
||||
width: 100,
|
||||
height: 100,
|
||||
File(controller.profileImage?.path ?? ''),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: CircleAvatar(
|
||||
radius: 15,
|
||||
backgroundColor: ColorConstants.primaryColor,
|
||||
child: Icon(
|
||||
Icons.camera_alt_outlined,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Center(
|
||||
child: TextWidget(
|
||||
text: 'Upload Company Logo',
|
||||
)),
|
||||
const SizedBox(height: 30,),
|
||||
_buildTextField(
|
||||
controller: controller.firstnameController,
|
||||
label: 'Contact Name',
|
||||
icon: Icons.person,
|
||||
formatters: [UpperCaseTextFormatter()],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildTextField(
|
||||
controller: controller.companyNameController,
|
||||
label: 'Company Name',
|
||||
icon: Icons.business,
|
||||
formatters: [UpperCaseTextFormatter()],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildTextField(
|
||||
controller: controller.emailController,
|
||||
label: 'Email',
|
||||
icon: Icons.email_outlined,
|
||||
validator: _validateEmail,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildSelectionField(
|
||||
context: context,
|
||||
label: controller.selectedCategoryName.isEmpty ? 'Select Category' : controller.selectedCategoryName,
|
||||
icon: Icons.category,
|
||||
onTap: () async {
|
||||
var result = await SubCategoryService().fetchSubCategories();
|
||||
if (result != null && result.details != null) {
|
||||
final categories = result.details!
|
||||
.map((e) => e.catgeoryname ?? '')
|
||||
.toSet()
|
||||
.toList();
|
||||
|
||||
if (context.mounted) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||
),
|
||||
builder: (context) {
|
||||
return ListView.builder(
|
||||
itemCount: categories.length,
|
||||
itemBuilder: (context, index) {
|
||||
final categoryName = categories[index];
|
||||
return ListTile(
|
||||
title: Text(categoryName),
|
||||
trailing: controller.selectedCategoryName == categoryName
|
||||
? Icon(Icons.check, color: ColorConstants.primaryColor)
|
||||
: null,
|
||||
onTap: () {
|
||||
// Update controller
|
||||
controller.selectedCategoryName = categoryName;
|
||||
controller.update(); // Trigger UI rebuild
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
const SizedBox(height: 20),
|
||||
_buildTextField(
|
||||
controller: controller.gstinNumberController,
|
||||
label: 'GSTIN',
|
||||
icon: Icons.verified_user,
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
_buildAddressSection(context, controller),
|
||||
const SizedBox(height: 20),
|
||||
if (controller.isEnterAddress) ...[
|
||||
_buildTextField(controller: controller.suburbController, label: 'Suburb', icon: Icons.location_on),
|
||||
const SizedBox(height: 15),
|
||||
_buildTextField(controller: controller.cityController, label: 'City', icon: Icons.location_on),
|
||||
const SizedBox(height: 15),
|
||||
_buildTextField(controller: controller.stateController, label: 'State', icon: Icons.location_on),
|
||||
const SizedBox(height: 15),
|
||||
],
|
||||
_buildTextField(controller: controller.postcodeController, label: 'Pincode', icon: Icons.location_on),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: _buildBottomBar(controller),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTextField({
|
||||
required TextEditingController controller,
|
||||
required String label,
|
||||
required IconData icon,
|
||||
List<TextInputFormatter>? formatters,
|
||||
String? Function(String?)? validator,
|
||||
}) {
|
||||
return Container(
|
||||
height: Get.height * 0.07,
|
||||
decoration: BoxDecoration(color: ColorConstants.secondaryColor),
|
||||
child: TextFormField(
|
||||
controller: controller,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
inputFormatters: formatters,
|
||||
validator: validator,
|
||||
onFieldSubmitted: (_) {
|
||||
FocusManager.instance.primaryFocus?.unfocus(); // Removes focus and hides keyboard
|
||||
},
|
||||
style: const TextStyle(fontFamily: 'Inter'),
|
||||
decoration: CustomDecoration.textFieldStyle(labelTextStr: label, prefixIcon: Icon(icon, color: ColorConstants.darkGreyColor)),
|
||||
onEditingComplete: () => FocusScope.of(Get.context!).requestFocus(FocusNode()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSelectionField({
|
||||
required BuildContext context,
|
||||
required String label,
|
||||
required IconData icon,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
border: Border.all(color: Colors.grey[200]!, width: 2),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, color: ColorConstants.darkGreyColor),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: Text(label, style: TextStyle(fontSize: 17, color: Colors.grey[500]))),
|
||||
Icon(Icons.arrow_drop_down, color: Colors.grey[600], size: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Widget _buildAddressSection(BuildContext context, CreateUserController controller) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.location_on, color: ColorConstants.darkGreyColor, size: 23),
|
||||
const SizedBox(width: 5),
|
||||
const Text('Address', style: TextStyle(color: Colors.black54, fontSize: 16)),
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// Toggle the isEnterAddress state if needed for other UI logic
|
||||
controller.isEnterAddress = !controller.isEnterAddress;
|
||||
controller.update();
|
||||
},
|
||||
child: Icon(
|
||||
controller.isEnterAddress ? Icons.check : Icons.keyboard_arrow_down_sharp,
|
||||
color: Colors.grey[600],
|
||||
size: 23,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
TextFormField(
|
||||
controller: controller.addressController,
|
||||
maxLines: 3,
|
||||
cursorColor: ColorConstants.textFieldColor,
|
||||
style: TextStyle(color: ColorConstants.textFieldColor),
|
||||
decoration: CustomDecoration.textFieldStyle(),
|
||||
readOnly: true, // Make it read-only to prevent direct editing
|
||||
onTap: () async {
|
||||
// Navigate to the address search screen and wait for the result
|
||||
final selectedAddress = await Get.to(() => AddressSearchScreen(controller: controller));
|
||||
if (selectedAddress != null) {
|
||||
controller.addressController.text = selectedAddress['description'];
|
||||
controller.getPlaceDetails(selectedAddress['place_id'], selectedAddress['description']);
|
||||
controller.update();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Widget _buildBottomBar(CreateUserController controller) {
|
||||
return Container(
|
||||
height: Get.height * 0.1,
|
||||
child: RoundedButton(
|
||||
height: Get.height * 0.06,
|
||||
width: Get.width * 0.9,
|
||||
onPressed: controller.doSomething,
|
||||
color: ColorConstants.primaryColor,
|
||||
title: 'Create',
|
||||
controller: controller.btnController,
|
||||
textStyle: const TextStyle(fontSize: 18, fontFamily: 'Inter', color: Colors.white, fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String? _validateEmail(String? value) {
|
||||
const simplePattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$';
|
||||
final regex = RegExp(simplePattern);
|
||||
return value!.isNotEmpty && !regex.hasMatch(value) ? 'Enter a valid email address' : null;
|
||||
}
|
||||
}
|
||||
|
||||
class UpperCaseTextFormatter extends TextInputFormatter {
|
||||
@override
|
||||
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
|
||||
return TextEditingValue(text: capitalize(newValue.text), selection: newValue.selection);
|
||||
}
|
||||
}
|
||||
|
||||
String capitalize(String value) {
|
||||
if (value.trim().isEmpty) return '';
|
||||
return '${value[0].toUpperCase()}${value.substring(1)}';
|
||||
}
|
||||
|
||||
|
||||
class AddressSearchScreen extends StatelessWidget {
|
||||
final CreateUserController controller;
|
||||
|
||||
const AddressSearchScreen({Key? key, required this.controller}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Initialize a new TextEditingController with the initial address
|
||||
final searchController = TextEditingController(text: controller.addressController.text);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: TextWidget(
|
||||
text: 'Search Address',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: ColorConstants.blackColor),
|
||||
onPressed: () => Get.back(), // Return without selecting an address
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: searchController,
|
||||
autofocus: true,
|
||||
cursorColor: ColorConstants.textFieldColor,
|
||||
style: TextStyle(color: ColorConstants.textFieldColor),
|
||||
decoration: CustomDecoration.textFieldStyle().copyWith(
|
||||
hintText: 'Enter address',
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(Icons.cancel, color: ColorConstants.blackColor),
|
||||
onPressed: () {
|
||||
searchController.clear(); // Clear the search field
|
||||
controller.predictions.clear(); // Clear predictions
|
||||
controller.update(); // Notify UI to update
|
||||
},
|
||||
),
|
||||
),
|
||||
onChanged: (text) {
|
||||
if (text.isEmpty) {
|
||||
controller.predictions.clear();
|
||||
controller.update();
|
||||
}
|
||||
controller.onSearchTextChanged(text);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Expanded(
|
||||
child: Obx(
|
||||
() => controller.predictions.isEmpty
|
||||
? const Center(child: Text('No results found'))
|
||||
: ListView.builder(
|
||||
itemCount: controller.predictions.length,
|
||||
itemBuilder: (context, index) {
|
||||
final prediction = controller.predictions[index]['description'];
|
||||
return ListTile(
|
||||
title: Text(prediction),
|
||||
onTap: () {
|
||||
final selectedAddress = controller.predictions[index];
|
||||
controller.addressController.text = selectedAddress['description'];
|
||||
controller.getPlaceDetails(selectedAddress['place_id'], selectedAddress['description']);
|
||||
Get.back(result: selectedAddress);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user