Main.dart
import 'package:flutter/material.dart';
import 'package:for_web_testing/Detailes/detailes.dart';
import 'package:for_web_testing/Pages/HomePage.dart';
import 'package:for_web_testing/Pages/LoginPage.dart';
import 'package:for_web_testing/Pages/registerPage.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isLoggedIn = prefs.getBool('isLoggedIn') ?? false;
runApp(MyApp(isLoggedIn: isLoggedIn,));
}
class MyApp extends StatelessWidget {
final bool isLoggedIn;
MyApp({required this.isLoggedIn});
// This widget is the root of your application...
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: Detailes.appName,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: isLoggedIn ? Homepage() : LoginPage()
);
}
}
LoginPage.dart
import 'package:flutter/material.dart';
import 'package:crypto/crypto.dart';
import 'dart:convert';
import 'package:for_web_testing/Database/PostGre.dart';
import 'package:for_web_testing/Pages/HomePage.dart';
import 'package:for_web_testing/Pages/registerPage.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final DatabaseConnection _databaseConnection = DatabaseConnection();
void _loginUser() async {
try {
final hashedPassword = _hashPassword(_passwordController.text);
final response = await _databaseConnection.loginUser(
email: _emailController.text,
password: hashedPassword,
);
if (response['success']) {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLoggedIn', true);
await prefs.setString('userId', response['userId'].toString()); // Save user ID
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Login successful!'),
backgroundColor: Colors.green,
));
Future.delayed(Duration(seconds: 3), () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Homepage()),
);
});
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(response['message'] ?? 'Login failed.')),
);
}
} catch (e) {
print('Error: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('An error occurred: $e')),
);
}
}
// Hash the password using SHA-256
String _hashPassword(String password) {
final bytes = utf8.encode(password); // Convert to UTF-8
final hashedPassword = sha256.convert(bytes).toString(); // Hash the password
return hashedPassword;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
SizedBox(height: 20),
Row(
children: [
ElevatedButton(
onPressed: _loginUser,
child: Text('Login'),
),
TextButton(
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>RegisterPage()));
},
child: Text('Register Page'),
)
],
),
],
),
),
);
}
}
RegisterPage
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:for_web_testing/Database/PostGre.dart';
import 'package:for_web_testing/Pages/LoginPage.dart';
import 'package:http/http.dart' as http;
import 'package:crypto/crypto.dart';
class RegisterPage extends StatefulWidget {
@override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
final TextEditingController _firstnameController = TextEditingController();
final TextEditingController _lastnameController = TextEditingController();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _phoneController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final DatabaseConnection _databaseConnection = DatabaseConnection();
void _registerUser() async {
try {
// Hash the password before sending it to the database
final hashedPassword = _hashPassword(_passwordController.text);
// Get the response from the registerUser method
final response = await _databaseConnection.registerUser(
firstname: _firstnameController.text,
lastname: _lastnameController.text,
email: _emailController.text,
phoneNumber: _phoneController.text,
password: hashedPassword,
);
// Check if the registration was successful
if (response['success'] == true) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Registration successful!'),
backgroundColor: Colors.green,
));
Future.delayed(Duration(seconds: 3),(){
//START...
Navigator.push(context, MaterialPageRoute(builder: (context)=>LoginPage()));
});
// Optionally clear input fields after successful registration...
_firstnameController.clear();
_lastnameController.clear();
_emailController.clear();
_phoneController.clear();
_passwordController.clear();
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Registration failed: ${response['message']}'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
// Handle any unexpected errors
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('An error occurred: $e'),
backgroundColor: Colors.red,
),
);
}
}
// Method to hash the password using SHA-256
String _hashPassword(String password) {
final bytes = utf8.encode(password); // Convert to UTF-8
final hashedPassword = sha256.convert(bytes).toString(); // Hash the password
return hashedPassword;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Register')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _firstnameController,
decoration: InputDecoration(labelText: 'First Name'),
),
TextField(
controller: _lastnameController,
decoration: InputDecoration(labelText: 'Last Name'),
),
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
),
TextField(
controller: _phoneController,
decoration: InputDecoration(labelText: 'Phone Number'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _registerUser,
child: Text('Register'),
),
],
),
),
);
}
}
HomePage
import 'package:flutter/material.dart';
import 'package:for_web_testing/Database/PostGre.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Homepage extends StatefulWidget {
const Homepage({super.key});
@override
State<Homepage> createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
String username = '';
String phoneNumber = '';
String email = '';
bool isLoading = true;
final DatabaseConnection _databaseConnection = DatabaseConnection();
@override
void initState() {
super.initState();
_fetchUserDetails();
}
Future<void> _fetchUserDetails() async {
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? userId = prefs.getString('userId');
if (userId == null) {
setState(() {
isLoading = false;
username = 'Unknown';
phoneNumber = 'Unknown';
email = 'Unknown';
});
return;
}
final response = await _databaseConnection.fetchUserDetails(userId: userId);
if (response['success']) {
setState(() {
username = '${response['firstname']} ${response['lastname']}';
phoneNumber = response['phonenumber'];
email = response['email'];
isLoading = false;
});
}
else {
setState(() {
username = 'Unknown';
phoneNumber = 'Unknown';
email = 'Unknown';
isLoading = false;
});
print('Failed to fetch user details: ${response['message']}');
}
} catch (e) {
print('Error: $e');
setState(() {
username = 'Unknown';
phoneNumber = 'Unknown';
email = 'Unknown';
isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Home Page"),
leading: IconButton(onPressed: () {}, icon: const Icon(Icons.menu)),
),
body: isLoading
? const Center(child: CircularProgressIndicator())
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"HOME PAGE",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
Text("User Name: $username"),
Text("Phone Number: $phoneNumber"),
Text("Email ID: $email"),
],
),
),
);
}
}
DatabaseConnection class
import 'package:http/http.dart' as http;
import 'dart:convert';
class DatabaseConnection {
final String baseUrl = 'http://localhost:3000'; // Base URL for the API
Future<Map<String, dynamic>> registerUser({required String firstname, required String lastname, required String email, required String phoneNumber, required String password,}) async {
final url = Uri.parse('$baseUrl/register');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'firstname': firstname,
'lastname': lastname,
'email': email,
'phonenumber': phoneNumber,
'password': password,
}),
);
if (response.statusCode == 201) {
return {'success': true, 'message': 'User registered successfully'};
} else {
final errorResponse = jsonDecode(response.body);
return {
'success': false,
'message': errorResponse['error'] ?? 'Unknown error occurred',
};
}
}
Future<Map<String, dynamic>> loginUser({required String email, required String password,}) async {
final url = Uri.parse('$baseUrl/login');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'email': email,
'password': password,
}),
);
if (response.statusCode == 200) {
final responseData = jsonDecode(response.body);
return {
'success': true,
'userId': responseData['user']['userid'], // Correctly accessing nested userId
};
} else {
return {'success': false, 'message': 'Login failed'};
}
}
Future<Map<String, dynamic>> fetchUserDetails({required String userId}) async {
final url = Uri.parse('$baseUrl/getUserDetails');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'userId': userId}),
);
if (response.statusCode == 200) {
final userData = jsonDecode(response.body);
return {
'success': true,
'firstname': userData['firstname'],
'lastname': userData['lastname'],
'phonenumber': userData['phonenumber'],
'email': userData['email'],
};
} else {
final errorResponse = jsonDecode(response.body);
return {
'success': false,
'message': errorResponse['error'] ?? 'Failed to fetch user details',
};
}
}
}
Sever.js file
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const { Pool } = require('pg');
const bcrypt = require('bcrypt');
const { body, validationResult } = require('express-validator');
const helmet = require('helmet');
const app = express();
app.use(bodyParser.json());
app.use(helmet());
const pool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_DATABASE,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT,
});
app.post('/register', [
body('firstname').isString().notEmpty(),
body('lastname').isString().notEmpty(),
body('email').isEmail(),
body('phonenumber').isMobilePhone(),
body('password').isLength({ min: 6 })
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { firstname, lastname, email, phonenumber, password } = req.body;
try {
const hashedPassword = await bcrypt.hash(password, 10);
const result = await pool.query(
`INSERT INTO users (firstname, lastname, email, phonenumber, password)
VALUES ($1, $2, $3, $4, $5) RETURNING *`,
[firstname, lastname, email, phonenumber, hashedPassword]
);
res.status(201).json({ message: 'User registered successfully', user: result.rows[0] });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Database error' });
}
});
app.post('/login', [
body('email').isEmail(),
body('password').isLength({ min: 6 })
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { email, password } = req.body;
try {
const result = await pool.query(
`SELECT * FROM users WHERE email = $1`,
[email]
);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'User not found' });
}
const user = result.rows[0];
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).json({ error: 'Invalid credentials' });
}
res.status(200).json({ message: 'Login successful', user: {
userid: user.userid,
firstname: user.firstname,
lastname: user.lastname,
email: user.email,
phonenumber: user.phonenumber
}});
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Database error' });
}
});
app.post('/getUserDetails', async (req, res) => {
console.log('Request received:', req.body); // Add this line
const { userId } = req.body;
if (!userId) {
console.log('No userId provided'); // Add this line
return res.status(400).json({ error: 'User ID is required' });
}
try {
const result = await pool.query(
`SELECT userid, firstname, lastname, email, phonenumber FROM users WHERE userid = $1`,
[userId]
);
if (result.rows.length === 0) {
console.log('User not found'); // Add this line
return res.status(404).json({ error: 'User not found' });
}
console.log('User details found:', result.rows[0]); // Add this line
res.status(200).json(result.rows[0]);
} catch (error) {
console.error('Database error:', error); // Add this line
res.status(500).json({ error: 'Database error' });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
.evn file
DB_USER=PostgreSQL
DB_HOST=localhost
DB_DATABASE=sagar
DB_PASSWORD=12345
DB_PORT=5432
for creating .evn file go to your root directory where store postgre and enter this command
touch .env
and click shift+command+. to show hide files