This commit is contained in:
Mohammed Al-Samarraie
2026-01-13 13:07:31 +03:00
parent ac8a769ff0
commit fa4bee4771
15 changed files with 578 additions and 45 deletions

View File

@@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import '../screens/main_screen.dart';
import '../screens/main_screen.dart';
import '../core/di/injection_container.dart';
import '../domain/usecases/login_usecase.dart';
import '../domain/models/login_request.dart';
import 'onboarding_button.dart';
class AuthForm extends StatefulWidget {
@@ -13,25 +16,86 @@ class AuthForm extends StatefulWidget {
class _AuthFormState extends State<AuthForm> {
bool _obscure = true;
bool _isLoading = false;
// Text controllers
final TextEditingController _phoneNumberController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
// Focus nodes for text fields
late FocusNode _usernameFocusNode;
late FocusNode _phoneNumberFocusNode;
late FocusNode _passwordFocusNode;
void _handleLogin() {
// Unfocus any focused text field
_usernameFocusNode.unfocus();
_passwordFocusNode.unfocus();
// Get LoginUseCase from dependency injection
final LoginUseCase _loginUseCase = sl<LoginUseCase>();
// Call the onSubmit callback if provided (for any other logic you might have)
if (widget.onSubmit != null) {
widget.onSubmit!();
Future<void> _handleLogin() async {
// Validate inputs
if (_phoneNumberController.text.trim().isEmpty) {
_showError('الرجاء إدخال رقم الهاتف');
return;
}
// Navigate to the AttendancePage
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const MainPage()),
if (_passwordController.text.trim().isEmpty) {
_showError('الرجاء إدخال كلمة المرور');
return;
}
// Unfocus any focused text field
_phoneNumberFocusNode.unfocus();
_passwordFocusNode.unfocus();
setState(() {
_isLoading = true;
});
try {
final request = LoginRequest(
phoneNumber: _phoneNumberController.text.trim(),
password: _passwordController.text.trim(),
);
final result = await _loginUseCase(request);
result.fold(
(failure) {
_showError(failure.message);
},
(response) {
if (response.isSuccess) {
// Call the onSubmit callback if provided
if (widget.onSubmit != null) {
widget.onSubmit!();
}
// Navigate to the MainPage
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const MainPage()),
);
} else {
_showError(response.message);
}
},
);
} catch (e) {
_showError('حدث خطأ غير متوقع: $e');
} finally {
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
}
void _showError(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Colors.red,
behavior: SnackBarBehavior.floating,
),
);
}
@@ -39,14 +103,16 @@ class _AuthFormState extends State<AuthForm> {
void initState() {
super.initState();
// Initialize focus nodes
_usernameFocusNode = FocusNode();
_phoneNumberFocusNode = FocusNode();
_passwordFocusNode = FocusNode();
}
@override
void dispose() {
// Clean up focus nodes when widget is disposed
_usernameFocusNode.dispose();
// Clean up controllers and focus nodes
_phoneNumberController.dispose();
_passwordController.dispose();
_phoneNumberFocusNode.dispose();
_passwordFocusNode.dispose();
super.dispose();
}
@@ -130,11 +196,11 @@ class _AuthFormState extends State<AuthForm> {
SizedBox(height: verticalSpacing),
/// Username Label
/// Phone Number Label
Align(
alignment: Alignment.centerRight,
child: Text(
"اسم المستخدم",
"رقم الهاتف",
style: TextStyle(
fontSize: labelFontSize,
color: Colors.black87,
@@ -144,9 +210,11 @@ class _AuthFormState extends State<AuthForm> {
const SizedBox(height: 8),
_buildField(
hint: "اسم المستخدم",
controller: _phoneNumberController,
hint: "رقم الهاتف",
obscure: false,
focusNode: _usernameFocusNode,
keyboardType: TextInputType.phone,
focusNode: _phoneNumberFocusNode,
textInputAction: TextInputAction.next,
onSubmitted: (_) {
// Move focus to password field when next is pressed
@@ -171,14 +239,13 @@ class _AuthFormState extends State<AuthForm> {
const SizedBox(height: 8),
_buildField(
controller: _passwordController,
hint: "كلمة المرور",
obscure: _obscure,
hasEye: true,
focusNode: _passwordFocusNode,
textInputAction: TextInputAction.done,
onSubmitted:
(_) =>
_handleLogin(), // Added parentheses to call the method
onSubmitted: (_) => _handleLogin(),
fontSize: fieldFontSize,
),
@@ -186,9 +253,9 @@ class _AuthFormState extends State<AuthForm> {
Center(
child: OnboardingButton(
text: "تسجيل دخول",
text: _isLoading ? "جاري تسجيل الدخول..." : "تسجيل دخول",
backgroundColor: const Color.fromARGB(239, 35, 87, 74),
onPressed: _handleLogin,
onPressed: _isLoading ? null : _handleLogin,
),
),
@@ -203,9 +270,11 @@ class _AuthFormState extends State<AuthForm> {
}
Widget _buildField({
TextEditingController? controller,
required String hint,
required bool obscure,
bool hasEye = false,
TextInputType? keyboardType,
FocusNode? focusNode,
TextInputAction? textInputAction,
Function(String)? onSubmitted,
@@ -220,8 +289,10 @@ class _AuthFormState extends State<AuthForm> {
],
),
child: TextField(
controller: controller,
focusNode: focusNode,
obscureText: obscure,
keyboardType: keyboardType,
textAlign: TextAlign.right,
textInputAction: textInputAction,
onSubmitted: onSubmitted,