This chapter will consists of 4 parts.
First we will create the register screen and connect it to the register api.
Second we will create the login screen and connect it to our login API
Third we will store login information in shared preferences.
In dashboard screen, we will at first check the login data from the shared preferences, if it is already present then the user will be able to access the dashboard screen, else the user will be thrown out to the login page again.
In order to make the register screen at first, import the necessary packages in pubspec.yaml files
dio: ^5.2.1+1
http: ^1.2.1
motion_toast: ^2.10.0
Once done import to register screen
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
import 'package:motion_toast/motion_toast.dart';
Then Make The Full Register Screen
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:rongmon/login/loginScreen.dart';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
import 'package:motion_toast/motion_toast.dart';
import '../config.dart';
class RegisterScreen extends StatefulWidget {
const RegisterScreen({super.key});
@override
State<RegisterScreen> createState() => _RegisterScreenState();
}
class _RegisterScreenState extends State<RegisterScreen> {
TextEditingController userNameController = TextEditingController();
TextEditingController userMobileController = TextEditingController();
TextEditingController userEmailController = TextEditingController();
TextEditingController userPasswordController = TextEditingController();
bool visibleLoading = false;
Future register({
required TextEditingController username,
required TextEditingController usermobile,
required TextEditingController useremail,
required TextEditingController userpassword,
required BuildContext context,
required Widget widget,
}) async {
String getUsername = username.text;
String getUserPassword = userpassword.text;
String getUserEmail = useremail.text;
String getUserMobile = usermobile.text;
setState(() {
visibleLoading = true;
});
var data = {
'username': getUsername,
'usermobile': getUserMobile,
'useremail': getUserEmail,
'userpassword': getUserPassword,
};
var apiCall = await Dio().post('$WebApiIndex/register.php', data: data);
var decode = jsonDecode(apiCall.data);
print((decode[8]));
if (decode[8] == 'Registered Successfully') {
setState(() {
visibleLoading = false;
});
//store data to sharedpreference
//prefLogin(id: decode[0], user_name: decode[1], user_phone: decode[2], user_reseller: decode[3], user_agent: decode[4], user_geek: decode[5], user_collaborator: decode[6],user_student: decode[7], );
MotionToast.success(
title: Text("Registration Successful"),
description: Text("You can now login"))
.show(context);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => LoginScreen()),
(Route<dynamic> route) => false);
}
if (decode[8] == 'Loggedin Successfully') {
setState(() {
visibleLoading = false;
});
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Oops! Error..'),
content: Text(
'Mobile Number or Email Id Already Exists. Please Login or Reset Your Password'),
actions: [
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RegisterScreen()));
},
child: Text('Close X'),
)
],
);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
padding: EdgeInsets.only(top: 100),
alignment: Alignment.center,
child: Text(
'Register For Free',
style: TextStyle(fontSize: 20),
),
),
Container(
padding: EdgeInsets.all(8),
child: TextField(
controller: userNameController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Full Name',
hintText: 'Your Full Name',
labelStyle: TextStyle(
color: Colors.black), // Set the color of the label text
hintStyle: TextStyle(
color:
Colors.black), // Set the color of the placeholder text
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when focused
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when not focused
),
),
style: TextStyle(
color: Colors.black), // Set the color of the entered text
),
),
Container(
padding: EdgeInsets.all(8),
child: TextField(
controller: userMobileController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Mobile Number',
hintText: 'Your 10 Digit Mobile Number',
labelStyle: TextStyle(
color: Colors.black), // Set the color of the label text
hintStyle: TextStyle(
color:
Colors.black), // Set the color of the placeholder text
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when focused
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when not focused
),
),
style: TextStyle(
color: Colors.black), // Set the color of the entered text
),
),
Container(
padding: EdgeInsets.all(8),
child: TextField(
controller: userEmailController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email Address',
hintText: 'Your Email Address',
labelStyle: TextStyle(
color: Colors.black), // Set the color of the label text
hintStyle: TextStyle(
color:
Colors.black), // Set the color of the placeholder text
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when focused
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when not focused
),
),
style: TextStyle(
color: Colors.black), // Set the color of the entered text
),
),
Container(
padding: EdgeInsets.all(8),
child: TextField(
controller: userPasswordController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
hintText: 'Enter A Password',
labelStyle: TextStyle(
color: Colors.black), // Set the color of the label text
hintStyle: TextStyle(
color:
Colors.black), // Set the color of the placeholder text
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when focused
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when not focused
),
),
style: TextStyle(
color: Colors.black), // Set the color of the entered text
),
),
Container(
padding: EdgeInsets.all(8),
child: GestureDetector(
onTap: () {
register(
username: userNameController,
usermobile: userMobileController,
useremail: userEmailController,
userpassword: userPasswordController,
context: context,
widget: widget,
);
},
child: Container(
margin: EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0),
padding:
EdgeInsets.only(top: 15, bottom: 15, right: 40, left: 40),
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: !visibleLoading
? Container(
width: 150,
child: Text(
'Register Now',
style: TextStyle(
color: Colors.white,
),
textAlign: TextAlign.center,
),
)
: Visibility(
visible: visibleLoading,
child: Container(
width: 100,
child: Center(
child: Container(
width: 10,
height: 10,
child: CircularProgressIndicator(
strokeWidth: 1.8,
color: Colors.white,
),
)),
))),
),
),
Container(
margin: EdgeInsets.only(top: 20, bottom: 10),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginScreen()),
);
},
child: Text('Already Have An Account? Login!',
style: TextStyle(fontSize: 15, color: Colors.white))),
)
],
),
);
}
}
Register API full source code
<?php
include('../../database.php');
//require_once("../session.php");
$table_name = 'users';
$redirection_page = "index.php?action=$page_name";
$action_name = "action=$page_name";
$type = $_REQUEST['type'];
$edit_id = $_REQUEST['edit_id'];
$delete_id = $_REQUEST['delete_id'];
date_default_timezone_set("Asia/Kolkata");
$today = date("Y-m-d");
$day = date("l");
$time = date("H:i:s");
$data = file_get_contents('php://input');
$dataDecode = json_decode($data, true);
$field1 = $dataDecode['username'];
$field2 = $dataDecode['usermobile'];
$field3 = $dataDecode['useremail'];
$field4 = $dataDecode['userpassword'];
$field5 = $_POST['field5'];
$field6 = $_POST['field6'];
$field7 = $_POST['field7'];
$field8 = $_POST['field8'];
$field9 = $_POST['field9'];
$field10 = $_POST['field10'];
$password = md5($field4);
$allow = array("jpg", "JPG", "jpeg", "JPEG", "gif", "GIF", "png", "PNG", "pdf", "PDF");
//1st File
if($_FILES['photo']['name'] == "") {
//echo "No Image"
} else {
$photo=basename($_FILES['photo']['name']);
$extension = pathinfo($photo, PATHINFO_EXTENSION);
if(in_array($extension,$allow)){
$target_path = "../../../uploads/users/";
$photo = md5(rand() * time()).'.'.$extension;
$target_path = $target_path . $photo;
move_uploaded_file($_FILES['photo']['tmp_name'], $target_path);
$sql = ($photo!='')?" user_photo='$photo' ". ',':'';
}
}
//Check if user already exists
$select = "select id,user_name,user_phone,user_reseller,user_agent,user_geek,user_collaborator,user_student from `users` WHERE user_phone = '".$field2."' ";
$sql=$dbconn->prepare($select);
$sql->execute();
if($sql->rowCount() > 0){
$message = 'Loggedin Successfully';
$array = [
$wlvd['id'],
$wlvd['user_name'],
$wlvd['user_phone'],
$wlvd['user_reseller'],
$wlvd['user_agent'],
$wlvd['user_geek'],
$wlvd['user_collaborator'],
$wlvd['user_student'],
$message,
];
echo json_encode($array);
} else {
$insert_bookings = "INSERT `$table_name` SET
user_name = '".addslashes($field1)."',
user_phone = '".addslashes($field2)."',
user_email = '".addslashes($field3)."',
user_password = '".addslashes($password)."',
status = 'Active'";
$sql_insert = $dbconn->prepare($insert_bookings);
$sql_insert->execute();
$myid = $dbconn->lastInsertId();
$message="Details successfully updated.";
$status="success";
$select = "select id,user_name,user_phone,user_reseller,user_agent,user_geek,user_collaborator,user_student from `users` WHERE user_phone = '$field2' and user_password = '$password' ";
$sql=$dbconn->prepare($select);
$sql->execute();
//$wlvd=$sql->fetch(PDO::FETCH_OBJ);
$wlvd=$sql->fetch(PDO::FETCH_ASSOC);
if($sql->rowCount() > 0){
$message = 'Registered Successfully';
$array = [
$wlvd['id'],
$wlvd['user_name'],
$wlvd['user_phone'],
$wlvd['user_reseller'],
$wlvd['user_agent'],
$wlvd['user_geek'],
$wlvd['user_collaborator'],
$wlvd['user_student'],
$message,
];
echo json_encode($array);
}
}
?>
Config file full source code
<?php
error_reporting(1);
session_start();
$host_name = "localhost";
$database = "username"; // Change your database name
$dbusername = "dbname"; // Your database user id
$dbpassword = "password"; // Your password
$dbh = null;
//$project_name = "Pioneer Syndicate";
//define('APP_URL', 'http://localhost/erp_final');
require 'classes/DB.php';
require 'classes/AUTH.php';
require 'classes/ROLE.php';
DB::connect();
?>
SQL code to create the database with one user
-- phpMyAdmin SQL Dump
-- version 5.1.1
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1:3306
-- Generation Time: Jul 13, 2024 at 12:16 PM
-- Server version: 10.11.8-MariaDB-cll-lve
-- PHP Version: 7.2.34
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `u621169360_rongmon`
--
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`user_company_name` varchar(255) DEFAULT NULL,
`user_name` varchar(255) DEFAULT NULL,
`user_gender` varchar(255) DEFAULT NULL,
`user_phone` varchar(13) DEFAULT NULL,
`user_email` varchar(255) DEFAULT NULL,
`user_password` varchar(255) DEFAULT NULL,
`user_role` varchar(255) NOT NULL DEFAULT 'CUSTOMER',
`user_class` text DEFAULT NULL,
`user_advisor_role` varchar(255) DEFAULT NULL,
`user_photo` text DEFAULT NULL,
`user_reseller` varchar(10) NOT NULL DEFAULT 'NO',
`user_agent` varchar(10) NOT NULL DEFAULT 'NO',
`user_geek` varchar(10) NOT NULL DEFAULT 'NO',
`user_collaborator` varchar(10) NOT NULL DEFAULT 'NO',
`user_student` varchar(255) NOT NULL DEFAULT 'NO',
`status` varchar(255) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `user_company_name`, `user_name`, `user_gender`, `user_phone`, `user_email`, `user_password`, `user_role`, `user_class`, `user_advisor_role`, `user_photo`, `user_reseller`, `user_agent`, `user_geek`, `user_collaborator`, `user_student`, `status`, `created_at`) VALUES
(1, NULL, 'Paban Bhuyan', 'f', 'admin', 'sales@indiawebdesigns.in', '21232f297a57a5a743894a0e4a801fc3', 'Admin', 'Class 8', 'Yes', NULL, 'NO', 'NO', 'NO', 'NO', 'NO', 'Active', '2020-07-16 00:00:00');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `user_phone` (`user_phone`),
ADD UNIQUE KEY `user_email` (`user_email`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=902;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Make the login screen
Import shared preferences in pub file at first
shared_preferences: ^2.0.13
Complete Login Screen Code
import 'package:flutter/cupertino.dart';
import 'package:rongmon/Dashboard/dashboard.dart';
import 'package:rongmon/Register/register.dart';
import 'package:rongmon/config.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:motion_toast/motion_toast.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final TextEditingController usernameController = TextEditingController();
final TextEditingController userpasswordController = TextEditingController();
Future<void> _loginUser() async {
String getUsername = usernameController.text;
String getUserpassword = userpasswordController.text;
String apiUrl = ('$WebApiIndex/login.php');
try {
var response = await http.post(Uri.parse(apiUrl), body: {
'username': getUsername,
'password': getUserpassword,
});
var responseData = json.decode(response.body);
if (responseData['success']) {
String userEmail = responseData['user_email'];
String userMobile = responseData['user_phone'];
print('User Email: $userEmail'); // Print user email
print('User Mobile: $userMobile'); // Print user email
_saveCredentials(
responseData['user_email'],
responseData['user_name'],
responseData['id'],
responseData['user_phone'],
responseData['user_student']);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Dashboard(),
),
);
// Handle navigation or any other action
print('Login successful=======');
} else {
// Login failed, show error message
print('Login failed: ${responseData['message']}');
//Fluttertoast.showToast(msg: 'Username or Password is Wrong');
MotionToast.error(
title: Text("Login Failed"),
description: Text("Username and Password Not Matched"))
.show(context);
}
} catch (e) {
print('Error logging in: $e');
}
}
Future<void> _saveCredentials(String userEmail, String userName, int userId,
String userMobile, String userStudent) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('email', userEmail);
await prefs.setString('password', userpasswordController.text);
await prefs.setString('userName', userName);
await prefs.setInt('userId', userId);
await prefs.setString('userMobile', userMobile);
await prefs.setString('userStudent', userStudent);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.only(top: 200, bottom: 0),
),
Container(
margin: EdgeInsets.only(left: 20, right: 20, top: 0, bottom: 5),
child: Text(
'Login to your Account',
style: TextStyle(fontSize: 25, color: Colors.black),
)),
Container(
margin: EdgeInsets.only(left: 20, right: 20, top: 5, bottom: 5),
child: TextField(
controller: usernameController,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '10 Digit Mobile Number',
hintStyle: TextStyle(
color: Colors
.black), // Set the color of the placeholder text
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when focused
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when not focused
),
),
style: TextStyle(
color: Colors.black), // Set the color of the entered text
),
),
Container(
margin: EdgeInsets.only(left: 20, right: 20, top: 5, bottom: 5),
child: TextField(
controller: userpasswordController,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'User Password',
hintStyle: TextStyle(
color: Colors
.black), // Set the color of the placeholder text
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when focused
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors
.black), // Set the color of the border when not focused
),
),
style: TextStyle(
color: Colors.black), // Set the color of the entered text
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 50),
// Add left and right margin here
child: ElevatedButton(
onPressed: () {
_loginUser();
},
child: Text(
'Login Now',
style: TextStyle(fontSize: 18, color: Colors.white),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.deepPurple,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
minimumSize: Size(double.infinity, 40),
padding: EdgeInsets.symmetric(
horizontal: 20), // Add padding here if needed
),
),
),
Container(
margin: EdgeInsets.only(top: 20, bottom: 5),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const RegisterScreen()),
);
},
child: Text('No Account? Sign Up Now!',
style: TextStyle(fontSize: 15, color: Colors.black))),
),
/*
Container(
child: Text('Or Login With'),
),
SizedBox(
height: 10,
),
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SMSlogin()),
);
},
child: Icon(Icons.sms),
),
SizedBox(
width: 20,
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const Register()),
);
},
child: Icon(Icons.facebook),
),
SizedBox(
width: 20,
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const GoogleLogin()),
);
},
child: Icon(Icons.g_translate),
),
],
),
)
*/
],
),
),
);
}
}
Complete Login HTTP API
<?php
// Enable CORS headers
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST");
header("Access-Control-Allow-Headers: Content-Type");
ob_start();
require_once('../../database.php');
// Retrieve the username and password from the POST request
$username = $_POST['username'];
$password = $_POST['password'];
// Encrypt the password using MD5
$encryptedPassword = md5($password);
// Query the database to check if credentials match
$query = "SELECT * FROM users WHERE user_phone = :username AND user_password = :password AND status = 'Active'";
$stmt = $dbconn->prepare($query);
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $encryptedPassword);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
// Valid credentials
$response = [
'success' => true,
'message' => 'Login successful',
'user_phone' => $user['user_phone'],
'user_name' => $user['user_name'],
'user_email' => $user['user_email'],
'user_district' => $user['user_district'],
'user_student' => $user['user_student'],
'id' => $user['id'],
];
} else {
// Invalid credentials
$response = [
'success' => false,
'message' => 'Invalid username or password',
];
}
// Send the response as JSON
header('Content-Type: application/json');
echo json_encode($response);
In Your Dashboard Screen Import Shared Preferences and Check if the user is logged in or not.
Future<void> _getUserInfo() async {
await Future.delayed(Duration(seconds: 2));
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
String usermobile = prefs.getString('userMobile') ?? ''; // Get user email
String userStudent = prefs.getString('userStudent') ?? ''; // Get user email
String userNameValue = prefs.getString('userName') ?? ''; // Get user email
String userEmail = prefs.getString('email') ?? ''; // Get user email
print('Email is ============ $userEmail');
_showListView = true;
if (usermobile.isEmpty) {
Navigator.push(context, MaterialPageRoute(builder: (context) => Register()));
} else {
setState(() {
userMobile = usermobile;
userName = userNameValue;
});
}
if (userStudent == 'NO') {
WidgetsBinding.instance.addPostFrameCallback((_) => _showPopup(context));
}
} catch (error) {
print('Error retrieving user info: $error');
}
}