222 lines
8.7 KiB
Dart
222 lines
8.7 KiB
Dart
import 'package:flutter/material.dart'; // Import Material package for UI components
|
|
import 'gallery_screen.dart'; // Import the gallery screen we'll navigate to after login
|
|
|
|
class LoginScreen extends StatefulWidget {
|
|
// StatefulWidget since we'll update the UI during login process
|
|
const LoginScreen({super.key}); // Constructor with optional key parameter
|
|
|
|
@override
|
|
_LoginScreenState createState() => _LoginScreenState(); // Create the mutable state for this widget
|
|
}
|
|
|
|
class _LoginScreenState extends State<LoginScreen> {
|
|
final _phoneController =
|
|
TextEditingController(); // Controller to manage phone number input
|
|
final _passwordController =
|
|
TextEditingController(); // Controller to manage password input
|
|
bool _isLoading = false; // Track if login is in progress
|
|
|
|
void _login() {
|
|
// Only proceed if both fields are not empty
|
|
if (_phoneController.text.isEmpty || _passwordController.text.isEmpty) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Please enter both phone number and password.'),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
|
|
// Simulate network delay for login process
|
|
Future.delayed(const Duration(seconds: 2), () {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
|
|
// Navigate to Gallery Screen, replacing the login screen in the navigation stack
|
|
Navigator.pushReplacement(
|
|
context,
|
|
MaterialPageRoute(builder: (context) => const GalleryScreen()),
|
|
);
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
// Cleanup resources when widget is removed
|
|
_phoneController
|
|
.dispose(); // Dispose phone text controller to prevent memory leaks
|
|
_passwordController
|
|
.dispose(); // Dispose password text controller to prevent memory leaks
|
|
super.dispose(); // Call parent class dispose method
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Build method defines the login screen UI
|
|
return Scaffold(
|
|
// Scaffold provides the basic material design structure
|
|
body: Center(
|
|
// Center aligns content in the middle of the screen
|
|
child: SingleChildScrollView(
|
|
// Makes content scrollable if it overflows
|
|
padding: const EdgeInsets.all(24.0), // Add padding around all sides
|
|
child: Column(
|
|
// Column arranges children vertically
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.center, // Center content vertically
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.stretch, // Stretch content horizontally
|
|
children: [
|
|
// Logo image at the top (allow path to be changed easily)
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 24.0),
|
|
child: ConstrainedBox(
|
|
constraints: const BoxConstraints(
|
|
minWidth: 50, // Minimum width
|
|
minHeight: 50, // Minimum height
|
|
maxWidth: 150, // Optional: set a max width if needed
|
|
maxHeight: 150, // Optional: set a max height if needed
|
|
),
|
|
child: Image.asset(
|
|
'assets/icons/logo.jpg',
|
|
fit:
|
|
BoxFit.contain, // Ensures the image fits within the box
|
|
),
|
|
),
|
|
),
|
|
const Text(
|
|
// Title text
|
|
'Amazons Login', // The actual text
|
|
textAlign: TextAlign.center, // Center align the text
|
|
style: TextStyle(
|
|
// Define text style
|
|
fontSize: 24, // Set font size
|
|
fontWeight: FontWeight.bold, // Make text bold
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 40,
|
|
), // Add vertical space of 40 logical pixels
|
|
TextField(
|
|
// Text field for phone number input
|
|
controller: _phoneController, // Connect to phone controller
|
|
decoration: const InputDecoration(
|
|
// Define the appearance
|
|
labelText: 'Phone Number', // Label text
|
|
prefixIcon: Icon(Icons.phone), // Phone icon at the start
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
|
), // Outlined border style with rounded corners
|
|
),
|
|
keyboardType: TextInputType.phone, // Show phone keyboard
|
|
),
|
|
const SizedBox(
|
|
height: 16,
|
|
), // Add vertical space of 16 logical pixels
|
|
TextField(
|
|
// Text field for password input
|
|
controller:
|
|
_passwordController, // Connect to password controller
|
|
decoration: const InputDecoration(
|
|
// Define the appearance
|
|
labelText: 'Password', // Label text
|
|
prefixIcon: Icon(Icons.lock), // Lock icon at the start
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
|
), // Outlined border style with rounded corners
|
|
),
|
|
obscureText: true, // Hide password characters
|
|
),
|
|
const SizedBox(
|
|
height: 24,
|
|
), // Add vertical space of 24 logical pixels
|
|
ElevatedButton(
|
|
// Login button
|
|
onPressed:
|
|
_isLoading
|
|
? null
|
|
: _login, // Disable button when loading, otherwise call _login
|
|
style: ElevatedButton.styleFrom(
|
|
// Define button style
|
|
backgroundColor: const Color.fromARGB(
|
|
255,
|
|
43,
|
|
116,
|
|
45,
|
|
), // Set button color to green
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 16,
|
|
), // Add vertical padding
|
|
),
|
|
child:
|
|
_isLoading
|
|
? const SizedBox(
|
|
// Show loading indicator when _isLoading is true
|
|
height: 20, // Height of loading indicator
|
|
width: 20, // Width of loading indicator
|
|
child: CircularProgressIndicator(
|
|
// Circular loading indicator
|
|
strokeWidth: 2, // Thin stroke width
|
|
color: Colors.white, // White color for visibility
|
|
),
|
|
)
|
|
: const Text(
|
|
// Show "Login" text when not loading
|
|
'Login',
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.bold, // Set font size
|
|
color: Color.fromARGB(
|
|
255,
|
|
250,
|
|
247,
|
|
247,
|
|
), // Set text color to black
|
|
),
|
|
),
|
|
),
|
|
// Moved Forgot Password link below the login button
|
|
Align(
|
|
alignment: Alignment.centerRight,
|
|
child: TextButton(
|
|
onPressed: () {
|
|
showDialog(
|
|
context: context,
|
|
builder:
|
|
(context) => AlertDialog(
|
|
title: const Text('Forgot Password'),
|
|
content: const Text(
|
|
'Password reset is not implemented in this demo.\nPlease contact support.',
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
child: const Text('OK'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
child: const Text(
|
|
'Forgot Password?',
|
|
style: TextStyle(
|
|
color: Colors.red, // Changed color to red
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|