morrisamazonsdev/lib/login_screen.dart
2025-05-17 11:02:55 +03:00

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,
),
),
),
),
],
),
),
),
);
}
}