login-page/lib/login_signup_page.dart
2025-05-17 11:13:16 +03:00

271 lines
9.2 KiB
Dart

import 'package:flutter/material.dart';
class LoginSignupPage extends StatefulWidget {
const LoginSignupPage({super.key});
@override
State<LoginSignupPage> createState() => _LoginSignupPageState();
}
class _LoginSignupPageState extends State<LoginSignupPage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _phoneController = TextEditingController();
String? _errorMessage;
bool _isLoading = false;
bool _isLoginMode = true;
// ... (rest of your validation methods, _toggleMode, _submitForm, dispose) ...
// No changes needed in the methods above for this step
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
_phoneController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
appBar: AppBar(
title: Text(_isLoginMode ? 'Amazons Login' : 'Amazons Sign Up'),
centerTitle: true,
actions: [
IconButton(
icon: const Icon(Icons.wifi),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Wi-Fi status: Connected (mock)')),
);
},
),
],
),
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(25.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
// --- YOUR IMAGE LOGO ---
Image.asset(
'images/logo.png', // <-- REPLACE 'your_logo.png' WITH YOUR ACTUAL FILENAME
height: 80, // Adjust height as needed
width: 150, // You can also set width
fit: BoxFit.contain, // How the image should be inscribed into the space
),
const SizedBox(height: 20), // Spacing after logo
Text(
_isLoginMode ? 'Welcome Back!' : 'Create Account',
textAlign: TextAlign.center,
style: theme.textTheme.displayLarge?.copyWith(
color: theme.primaryColor,
),
),
const SizedBox(height: 10),
Text(
_isLoginMode ? 'Login to continue' : 'Fill in the details to join',
textAlign: TextAlign.center,
style: theme.textTheme.titleMedium,
),
const SizedBox(height: 40),
// ... (rest of your form fields and buttons) ...
// No changes needed below for this step
// --- Email Text Field ---
TextFormField(
controller: _emailController,
decoration: const InputDecoration(
hintText: 'Email Address',
prefixIcon: Icon(Icons.email_outlined),
),
keyboardType: TextInputType.emailAddress,
validator: _validateEmail,
autovalidateMode: AutovalidateMode.onUserInteraction,
),
const SizedBox(height: 20),
// --- Password Text Field ---
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(
hintText: 'Password',
prefixIcon: Icon(Icons.lock_outline),
),
obscureText: true,
validator: _validatePassword,
autovalidateMode: AutovalidateMode.onUserInteraction,
),
const SizedBox(height: 20),
// --- Phone Number Text Field (Conditional) ---
if (!_isLoginMode)
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: TextFormField(
controller: _phoneController,
decoration: const InputDecoration(
hintText: 'Phone Number',
prefixIcon: Icon(Icons.phone_outlined),
),
keyboardType: TextInputType.phone,
validator: _validatePhoneNumber,
autovalidateMode: AutovalidateMode.onUserInteraction,
),
),
// --- Error Message Display ---
if (_errorMessage != null && !_isLoading)
Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: Text(
_errorMessage!,
style: TextStyle(
color: theme.colorScheme.error,
fontWeight: FontWeight.w500),
textAlign: TextAlign.center,
),
),
// --- Loading Indicator or Main Action Button ---
_isLoading
? const Center(child: CircularProgressIndicator())
: ElevatedButton(
onPressed: _submitForm,
child: Text(_isLoginMode ? 'Login' : 'Create Account'),
),
const SizedBox(height: 15),
// --- Toggle Mode Button ---
if (!_isLoading)
TextButton(
onPressed: _toggleMode,
child: Text(
_isLoginMode
? "Don't have an account? Sign Up"
: "Already have an account? Login",
style: theme.textTheme.titleMedium,
),
),
const SizedBox(height: 10),
// --- Forgot Password (Only in Login Mode) ---
if (_isLoginMode && !_isLoading)
Padding( // Added padding for better spacing
padding: const EdgeInsets.only(top: 8.0),
child: TextButton(
onPressed: (){
// Navigate to the Forgot Password page
Navigator.pushNamed(context, '/forgot-password');
},
child: Text(
'Forgot Password?',
style: theme.textTheme.titleMedium,
)
),
)
],
),
),
),
),
);
}
// Paste your existing _validateEmail, _validatePassword, _validatePhoneNumber,
// _toggleMode, and _submitForm methods here if they were not fully included above.
String? _validateEmail(String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if (!RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(value)) {
return 'Please enter a valid email';
}
return null;
}
String? _validatePassword(String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
}
if (value.length < 6) {
return 'Password must be at least 6 characters';
}
return null;
}
String? _validatePhoneNumber(String? value) {
// This validator is only active when the field is present (i.e., signup mode)
if (value == null || value.isEmpty) {
return 'Please enter your phone number';
}
if (value.length < 10) { // Basic length check
return 'Phone number must be at least 10 digits';
}
if (!RegExp(r'^[0-9]+$').hasMatch(value)) { // Digits only
return 'Please enter a valid phone number (digits only)';
}
return null;
}
void _toggleMode() {
setState(() {
_isLoginMode = !_isLoginMode;
_errorMessage = null; // Clear errors when switching modes
_formKey.currentState?.reset(); // Optional: reset form fields
_emailController.clear();
_passwordController.clear();
_phoneController.clear();
});
}
Future<void> _submitForm() async {
setState(() {
_errorMessage = null;
});
if (_formKey.currentState!.validate()) {
setState(() {
_isLoading = true;
});
await Future.delayed(const Duration(seconds: 1)); // Simulate network
String password = _passwordController.text;
String email = _emailController.text;
String actionType = _isLoginMode ? "Login" : "Sign Up";
if (password.startsWith('gym')) {
print('$actionType successful for: $email');
if (!_isLoginMode) {
print('Phone Number: ${_phoneController.text}');
}
if (mounted) { // Check if the widget is still in the tree
Navigator.pushReplacementNamed(context, '/home');
}
} else {
setState(() {
_errorMessage = 'Password must start with "gym" to $actionType.';
});
}
setState(() {
_isLoading = false;
});
}
}
}