Flutter: How to call a Future http.Post from my Login button - flutter

So far I have created my app with the pages I need and a login screen. At the moment the login screen just simply opens the first page in the app when the login button is touched (no authentication is done). I have written a small test app to get the login with http authentication working. Now I need to move the working authentication code into my app, but I'm not sure how to call the Future from the login button.
the Future is as follows: (just running local at the moment)
Future<Staff> fetchStaff() async {
final response = await http.post(
Uri.encodeFull('http://10.0.2.2:8080/modules/rmo_daMLogin'),
headers: {'Content-Type': 'text/plain'},
body: 'rmoService=User_Login\n'
'UserId=fred\n'
'Password=abc123');
if (response.statusCode == 200) {
// If the server did return a 200 OK response, then parse the JSON.
return Staff.fromJson(json.decode(response.body));
} else {
// If the server did not return a 200 OK response, then throw an exception.
throw Exception('User or Password was incorrect.');
}
}
Staff is defined as a class and just contains all the fields returned by the web service.
My login page contains the following. How do I call the Future from the Login button press and if Staff data is returned ok, how do I then use the pushReplacement of the Navigator to change pages?
Thanks for any help,
Paul
class RmoLogin extends StatelessWidget {
final TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
TextEditingController usernameController = new TextEditingController();
TextEditingController passwordController = new TextEditingController();
Future<Staff> futureStaff;
#override
Widget build(BuildContext context) {
final futureStaff = fetchStaff();
final userField = TextField(
obscureText: false,
style: style,
controller: usernameController,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
hintText: "User Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
),
),
);
final passwordField = TextField(
obscureText: true,
style: style,
controller: passwordController,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
hintText: "Password",
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(12.0))),
);
final loginButton = Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(12.0),
color: Color(0xff01A0C7),
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width,
padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
child: Text(
"Login",
textAlign: TextAlign.center,
style:
style.copyWith(color: Colors.white, fontWeight: FontWeight.bold),
),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (BuildContext context) => MyJobsPage(),
),
);
},
),
);
return Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: Color(0xff01A0C7),
title: Column(children: [
Text('Jobs Organiser'),
Text('Login', style: TextStyle(fontSize: 14)),
]),
),
body: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.fromLTRB(36, 20, 36, 36),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 75.0,
child: Image.asset(
"assets/Users.png",
fit: BoxFit.contain,
),
),
SizedBox(height: 45.0),
userField,
SizedBox(height: 25.0),
passwordField,
SizedBox(height: 35.0),
loginButton,
SizedBox(height: 15.0),
],
),
),
),
);
}
}

Related

search by username function in my flutter application using firebase returns a Future<dynamic> instance

i have a chatting application and i want to do a search function where the user can enter into a textfield another users username and to show the searched users username and name so the user can message them,
the problem i have is that when i retrieved from my firebase the user with the same username entered it returned a Future<dynamic> instance which then results in an error in using docs: "The getter 'docs' isn't defined for the type 'Future<dynamic>' "
here is my code
class _search extends State<search> {
TextEditingController searchController = new TextEditingController();
late Future<dynamic> searchResult;
bool haveUserSearched =false;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("search for user"),
centerTitle: true,
),
body: Container(
child: Column(
children: [
Container(
color: Color(0xfffffefa),
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
// GestureDetector(
// onTap: (){
// print(getUserByUsername(searchController.text));
// },
// child:
Expanded(child: TextField(
controller: searchController,
style: TextStyle(color: Color(0xffBFBBB7)),
onSubmitted: (value){
print(getUserByUsername(searchController.text));
},
decoration: InputDecoration(
hintText: "search by username",
hintStyle: TextStyle(color: Color(0xffBFBBB7)),
border: InputBorder.none,
prefixIcon: Icon(Icons.search,color: Color(0xffBFBBB7),),
),
),
),
//),
],
),
),
],
),
),
);
}
//-------methods and widgets-------
getUserByUsername(String username) async {
return await FirebaseFirestore.instance.collection('users').where('name',isEqualTo: username).get();
}
Widget userTile(String name,String username){
return Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
color: Colors.white,
fontSize: 16
),
),
Text(
username,
style: TextStyle(
color: Colors.white,
fontSize: 16
),
)
],
),
Spacer(),
GestureDetector(
onTap: (){
//sendMessage(userName);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12,vertical: 8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(24)
),
child: Text("Message",
style: TextStyle(
color: Colors.white,
fontSize: 16
),),
),
)
],
),
);
}
Widget userList(){
return haveUserSearched ? ListView.builder(
shrinkWrap: true,
itemCount: 1, ///?
itemBuilder: (context, index){
return userTile(
searchResult.docs[index].data['name'], //the error here is in docs "The getter 'docs' isn't defined for the type 'Future<dynamic>' "
searchResult.docs[index].data["username"],
);
}) : Container();
}
}
searchResult is a Future, a representation of an eventual result (or error) from an asynchronous operation. You need to wait for the result, which you can do in various ways, such as await or FutureBuilder. In this circumstance, you may opt to choose the latter.
Please see Asynchronous programming: futures, async, await for more.
Use futureBuilder inside Column and pass fetched data like Widget userList(users) {
It can be like
class _search extends State<search> {
TextEditingController searchController = new TextEditingController();
bool haveUserSearched = false;
late Future<dynamic> searchResult = getUserByUsername(searchController.text);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("search for user"),
centerTitle: true,
),
body: Container(
child: Column(
children: [
Container(
color: Color(0xfffffefa),
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Expanded(
child: TextField(
controller: searchController,
style: TextStyle(color: Color(0xffBFBBB7)),
onSubmitted: (value) {
searchResult = getUserByUsername(searchController.text);
setState(() {});
},
decoration: InputDecoration(
hintText: "search by username",
hintStyle: TextStyle(color: Color(0xffBFBBB7)),
border: InputBorder.none,
prefixIcon: Icon(
Icons.search,
color: Color(0xffBFBBB7),
),
),
),
),
],
),
),
FutureBuilder(
future: searchResult,
builder: (context, snapshot) {
if (snapshot.hasData) {
return userList(snapshot.data);
}
return Text("handle other state");
},
),
],
),
),
);
}
//-------methods and widgets-------
getUserByUsername(String username) async {
final result = await FirebaseFirestore.instance
.collection('users')
.where('name', isEqualTo: username)
.get();
User myUser = User(name: result['name'] .....) //get user from Map.. it cant be..
return myUser;
}
Widget userTile(String name, String username) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(color: Colors.white, fontSize: 16),
),
Text(
username,
style: TextStyle(color: Colors.white, fontSize: 16),
)
],
),
Spacer(),
GestureDetector(
onTap: () {
//sendMessage(userName);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: Colors.blue, borderRadius: BorderRadius.circular(24)),
child: Text(
"Message",
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
)
],
),
);
}
Widget userList(user) {
return haveUserSearched
? userTile(
user.name,
user.username,
)
: Container();
}
}

SingleChildScrollView not working for password textfield in Flutter

I am currently creating my first flutter application. So, when I was testing the login and sign up page. I encountered a problem.
The SingleChildScrollView() is not working in my Flutter login and Signin page for the password textfield only. The SingleChildScrollView() works perfectly for the email textfield. Can someone help me .
Code of Login page :
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:secure_pass/constants/routes.dart';
import 'package:secure_pass/services/auth/auth_exceptions.dart';
import 'package:secure_pass/services/auth/auth_service.dart';
import 'package:secure_pass/utilities/dialogs/error_dialog.dart';
class LoginView extends StatefulWidget {
const LoginView({Key? key}) : super(key: key);
#override
State<LoginView> createState() => _LoginViewState();
}
class _LoginViewState extends State<LoginView> {
late final TextEditingController _email;
late final TextEditingController _password;
#override
void initState() {
_email = TextEditingController();
_password = TextEditingController();
super.initState();
}
#override
void dispose() {
_email.dispose();
_password.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[300],
body: SafeArea(
child: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:[
//App icon
Icon(
Icons.android,
size: 100,
),
SizedBox(height: 25),
//Hello Again
Text(
'Hello Again!',
style: GoogleFonts.bebasNeue(
fontSize: 52,
),
),
SizedBox(height: 10),
Text(
'Welcome back, you\'ve been missed!',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(height: 50),
//email textfield
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
border: Border.all(color: Colors.white),
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.only(left: 20.0),
child: TextField(
controller: _email,
enableSuggestions: false,
autocorrect: false,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
hintText: 'Enter your email here',
border: InputBorder.none
),
),
),
),
),
SizedBox(height: 10),
//Password textfield
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
border: Border.all(color: Colors.white),
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.only(left: 20.0),
child: TextField(
controller: _password,
obscureText: true,
enableSuggestions: false,
autocorrect: false,
decoration: const InputDecoration(
hintText: 'Enter your password here',
border: InputBorder.none
),
),
),
),
),
SizedBox(height: 10),
TextButton(
onPressed: () async {
final email = _email.text;
final password = _password.text;
try {
await AuthService.firebase().logIn(
email: email,
password: password,
);
final user = AuthService.firebase().currentUser;
if (user?.isEmailVerified ?? false) {
// user's email is verified
Navigator.of(context).pushNamedAndRemoveUntil(
passwordsRoute,
(route) => false,
);
} else {
// user's email is NOT verified
Navigator.of(context).pushNamedAndRemoveUntil(
verifyEmailRoute,
(route) => false,
);
}
} on UserNotFoundAuthException {
await showErrorDialog(
context,
'User not found',
);
} on WrongPasswordAuthException {
await showErrorDialog(
context,
'Wrong credentials',
);
} on GenericAuthException {
await showErrorDialog(
context,
'Authentication error',
);
}
},
//log in button
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: const Text(
'Login',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
),
),
),
SizedBox(height: 25),
TextButton(
onPressed: () {
Navigator.of(context).pushNamedAndRemoveUntil(
registerRoute,
(route) => false,
);
},
//Not Registered yet ?
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const[
Text(
'Not registered yet?',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
Text(
' Register now',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
),
),
],
),
)
],
),
),
),
),
);
}
}
You can add bottom padding to the email text field.
Padding(
padding: const EdgeInsets.only(
left: 25,
right: 25,
bottom: MediaQuery.of(context).viewInsets.bottom + 32.0,
),
I assume you want both the email and the password textfield to come up, when the user is entering his data in the respective text fields.
In order to achieve in your scaffold set resizeToAvoidBottomInset property to true and it will work fine
Just Add reverse: true on SingleChildScrollView.
child: Center(
child: SingleChildScrollView(
reverse: true,
child: Column(
I was able to solve the problem by removing the "Center" widget.

Flutter Failed assertion: 'initialValue == null || controller == null': is not true

I am trying to fetch data entered in firestore to my TextFormField in order to make it as a profile updating section but while doing so I am facing this error Failed assertion: line 150 pos 15: 'initialValue == null || controller == null': is not true. I am unfamiliar with it can anyone please guide me where I am making mistake how can I resolve it? Also is its the correct approach I am making profile updating section. User will first enter the data, it will be empty by default and when the user will again come back to this screen the user should be shown the previous saved data that's exactly what I want.
Here's my code:
final TextEditingController _peopletohangoutwithController =
TextEditingController();// Controller
// rest of the code
FutureBuilder<DocumentSnapshot>(
future: FirebaseFirestore.instance
.collection("userpreferences")
.doc(FirebaseAuth.instance.currentUser!.uid)
.get(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
print(snapshot.hasData);
print(snapshot.data!["peopletohangoutwith"]);
}
return Column(
children: [
const SizedBox(
height: 50,
),
Row(
children: [
Align(
alignment: Alignment.topLeft,
child: DelayedDisplay(
delay: const Duration(seconds: 1),
child: Padding(
padding: const EdgeInsets.only(left: 10),
child: IconButton(
icon: const Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onPressed: () {
Navigator.of(context).pop();
},
),
)),
),
const Align(
alignment: Alignment.topCenter,
child: DelayedDisplay(
delay: Duration(seconds: 1),
child: Text(
"Hang out with",
style: TextStyle(
fontSize: 26,
color: Colors.white,
fontFamily: "ProductSans",
fontWeight: FontWeight.bold),
),
),
),
],
),
const SizedBox(
height: 50,
),
const DelayedDisplay(
delay: Duration(seconds: 2),
child: Center(
child: Padding(
padding: EdgeInsets.only(left: 10, right: 10),
child: Text(
"What type of people you want to hang out with",
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontFamily: "ProductSans",
fontWeight: FontWeight.bold),
),
),
),
),
const SizedBox(
height: 50,
),
DelayedDisplay(
delay: const Duration(seconds: 2),
child: Padding(
padding: const EdgeInsets.only(left: 30, right: 30),
child: TextFormField(
initialValue: snapshot.data!["peopletohangoutwith"],
controller: _peopletohangoutwithController,
maxLines: 10,
decoration: InputDecoration(
hintText: "Write in as detail as possible",
fillColor: Colors.white,
filled: true,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.white,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.white,
width: 2.0,
),
),
)),
),
),
const SizedBox(
height: 100,
),
DelayedDisplay(
delay: const Duration(seconds: 2),
child: Center(
child: FloatingActionButton.extended(
label: const Text('Save'),
backgroundColor: const Color(0xFF2A3B6A),
icon: const Icon(
Icons.save_as_outlined,
size: 24.0,
),
onPressed: () async {
if (_peopletohangoutwithController.text.isEmpty) {
Get.snackbar(
"Error",
"Please explain your preference",
colorText: Colors.white,
);
} else {
FirebaseFirestore.instance
.collection("userpreferences")
.doc(FirebaseAuth.instance.currentUser!.uid)
.set({
"peopletohangoutwith":
_peopletohangoutwithController.text,
});
}
},
),
),
),
],
);
},
),
How bout you fetch the user data before going to the edit page.. Pass the data to the page in a constructor and enter the data in the text editing controller in init state.
EDIT: Sorry. Didn't knoqw you were a beginner.
Let's assume you're getting your data from some database eg Firebase. Ensure you have a usermodel. Models make data so much easier to manage.
Soo,,
class UserModel{
String _userName;
String _tikTok;
String get userName => _userName;
String get tiktok => _tikTok;
UserModel.fromSnapshot(DocumentSnapshot snapshot){
_userName = snapshot.data()["userName"];
_tikTok = snapshot.data()["tikTok"];
}
}
This userModel can be used to propagate the profile page. Eg, if you got the data from firestore using streamBuilder, the builder would be sth like
(context, snapshot){
if(!snapshot.hasData}{
return LoadingWidget();
}else{
UserModel userModel = UserModel.fromSnapshot(snapshot.data);
return Scaffold(body: blah blah Text(userModel.userName) `and so forth`
I lost track of my brackets there, but you get the point.
Send the userModel to the next page via constructors, and initiate the data in initstate. Coz init state is the first function executed the moment the page loads. Even before it starts building widgets.
This is the code for the edit page.
class EditProfilePage extends StatefulWidget {
final UserModel userModel;
EditProfilePage({
Key key,
#required this.userModel,
}) : super(key: key);
#override
State<EditProfilePage> createState() => _EditProfilePageState();
}
class _EditProfilePageState extends State<EditProfilePage> {
TextEditingController nameController;
TextEditingController tiktokAccountController;
#override
void initState() {
super.initState();
if (widget.userModel != null) {
nameController = TextEditingController(
text: widget.userModel.userName,
);
tiktokAccountController = TextEditingController(
text: widget.userModel.tiktok,
);
}
}
#override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: nameController,
decoration: InputDecoration(
hintText: "Username",
),
),
SizedBox(
height: 10,
),
TextField(
controller: tiktokAccountController,
decoration: InputDecoration(
hintText: "Tik Tok Username",
),
),
],
);
}
}
So, when you're going to the edit page from the profile page, you would call Navigator.of(context).push(EditBlahBlah(userModel: userModel,),)
Where userModel is the userModel you're viewing on the profile page. I hope that helps.
Only one of the TextFormField's initialValue or controller can be used.
Use TextEditingController with initial value:
final controller = TextEditingController('the initial value');

Flutter Text field not updating after writing something more than or less than the initial value

I have 2 TextFormFields and for each of them i have an initial value, but when i type something on the text field and add or remove something from the initial value and press enter or done on the keyboard the text editing controller doesnt update. i tried looking for some ways to fix it with using Form and then the key but it didnt work for me maybe i didnt know how to implement it. Any help would be highly appreciated.
TextEditingController editedFirstName =
TextEditingController()..text = data3.firstName;
TextEditingController editedLastName =
TextEditingController()..text = data3.lastName;
Future<void> putAccountData() async {
SharedPreferences prefs =
await SharedPreferences.getInstance();
String? authorization =
prefs.getString('authorization');
var url =
'https://dev.api.wurk.skyver.co/api/v1/employees/account';
Map payload = {
"firstName": editedFirstName.text,
"lastName": editedLastName.text,
};
try {
final response = await http.put(Uri.parse(url),
headers: <String, String>{
'authorization':
authorization ?? basicAuth.toString(),
"Content-Type": "application/json"
},
body: jsonEncode(payload));
} catch (er) {}
}
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: width,
height: height / 1.9,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
width: 3,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
children: [
const Padding(
padding: EdgeInsets.all(30),
child: Text(
"First Name:",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.all(30),
child: SizedBox(
width: width / 2.5,
child: Center(
child: TextFormField(
textAlignVertical:
TextAlignVertical.center,
controller: editedFirstName
..selection =
TextSelection.collapsed(
offset: data3
.firstName.length),
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 10.0),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.red,
width: 1),
),
),
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
),
// inputFormatters: [
// LengthLimitingTextInputFormatter(15)
// ],
validator: (value) {
if (value == null ||
value.isEmpty) {
return 'Name is required';
}
return null;
},
),
),
),
),
],
),
Row(
children: [
const Padding(
padding: EdgeInsets.all(30),
child: Text(
'Last Name:',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.all(30),
child: SizedBox(
width: width / 2.5,
child: TextFormField(
controller: editedLastName
..selection =
TextSelection.collapsed(
offset:
data3.lastName.length),
It looks like the flutter docs on TextEditingController say
A TextEditingController can also be used to provide an initial value for a text field. If you build a text field with a controller that already has text, the text field will use that text as its initial value.
To set the initial value for a text input in Flutter set it in the controller on initialization:
TextEditingController textControllerWithDefault = TextEditingController(text: 'hello world');
In your case that should look like:
TextEditingController editedFirstName = TextEditingController(text: data.firstName).

Login is not working in flutter with REST API

Hi in the below code when I enter my mobile number, password and then click on the login button nothing is happening. My API working in Postman is not working here.
When I press the button it is not working, Entering a valid mobile number and password are not working.
Can anyone help me to find where I did any mistakes?
Login_screen.dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:sample_live/home_screen.dart';
import 'package:sample_live/model/login_model.dart';
import 'package:sample_live/splash_screen.dart';
import 'package:sample_live/login_otp.dart';
import 'ProgressHUD.dart';
import 'api/api_service.dart';
class LoginScreen extends StatefulWidget {
String name;
LoginScreen({this.name});
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final mobileController = TextEditingController();
final passwordController = TextEditingController();
LoginRequestModel requestModel;
bool isApiCallProcess = false;
GlobalKey<FormState> globalFormKey = GlobalKey<FormState>();
LoginRequestModel loginRequestModel;
final scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState(){
super.initState();
requestModel=new LoginRequestModel();
}
#override
Widget build(BuildContext context) {
return ProgressHUD(
child: _uiSetup(context),
inAsyncCall: isApiCallProcess,
opacity: 0.3,
);
}
Widget _uiSetup(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Login", style: TextStyle(color: Colors.white)),
centerTitle: true,
),
body:
Stack(
children: [
Padding(
padding: EdgeInsets.all(30),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/hand.png',),
Padding(
padding: EdgeInsets.all(10),
child: Text("Welcome Doctor! ",
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold
),),
),
Padding(
padding: EdgeInsets.all(10),
),
Text("Let's treat everyone great",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),),
Padding(
padding: EdgeInsets.all(10),
),
TextFormField(
minLines: 1,
keyboardType: TextInputType.number,
onSaved: (input) => loginRequestModel.Mobile = input,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
labelText: "Enter Mobile No.",
hintText: "Enter Mobile No.",
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(16.0)))),
),
SizedBox(
height: 10,
),
TextFormField(
onSaved: (input) =>
loginRequestModel.Password = input,
validator: (input) =>
input.length < 3
? "Password should be more than 3 characters"
: null,
minLines: 1,
obscureText: true,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
labelText: "Password",
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(16.0)))),
),
SizedBox(
height: 10,
),
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30)
),
child: RaisedButton(
color: Color(0xFF0769AA),
onPressed: () {
if (validateAndSave()) {
print(loginRequestModel.toJson());
setState(() {
isApiCallProcess = true;
});
APIService apiService = new APIService();
apiService.login(loginRequestModel).then((value) {
if (value != null) {
setState(() {
isApiCallProcess = false;
});
if (value.Status.isNotEmpty) {
final snackBar = SnackBar(
content: Text("Login Successful"));
scaffoldKey.currentState
.showSnackBar(snackBar);
} else {
final snackBar =
SnackBar(content: Text(value.Message));
scaffoldKey.currentState
// ignore: deprecated_member_use
.showSnackBar(snackBar);
}
}
});
}
},
child: Text(
"Login",
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(
height: 10,
),
Text("Or",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),),
Container(
width: double.infinity,
child: FlatButton(
color: Color(0xFF0769AA),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => LoginOtp("Welcome")),
(route) => false);
},
child: Text(
"Login With OTP",
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
// write your function
Navigator.push(
context,
MaterialPageRoute(
builder: (contex) => SplashScreen()));
},
child: Text(
"Forgot Password",
style: TextStyle(
color: Colors.blue,
fontSize: 16,
fontWeight: FontWeight.bold,
)
)),
],
),
],
),
),
Container(
alignment: Alignment.bottomCenter,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"By logging in or signing up, you agree to the",
textAlign: TextAlign.end,
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
),
Text(
"Privacy Policy & Terms and Condition",
textAlign: TextAlign.end,
style: TextStyle(
color: Colors.blue,
fontSize: 12,
),
),
],
)
)
]),
);
}
bool validateAndSave() {
final form = globalFormKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
}