changed logoRepository to authRepository

This commit is contained in:
llsajjad
2025-08-09 17:25:19 +03:30
parent e468ec9c43
commit 83ca169059
6 changed files with 138 additions and 164 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ List<SingleChildWidget> get repositories {
List<SingleChildWidget> get viewModels {
return [
Provider(
ChangeNotifierProvider(
create: (context) => AuthViewModel(authRepository: context.read()),
),
];
+41 -6
View File
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import '../core/utils/result.dart';
import '../data/models/user_model.dart';
import '../data/repositories/auth_repository.dart';
@@ -8,8 +7,25 @@ class AuthViewModel with ChangeNotifier {
final AuthRepository _authRepository;
AuthViewModel({required AuthRepository authRepository})
: _authRepository = authRepository;
: _authRepository = authRepository {
usernameController.addListener(_onTextChanged);
passwordController.addListener(_onTextChanged);
usernameFocus.addListener(_onTextChanged);
passwordFocus.addListener(_onTextChanged);
}
final TextEditingController usernameController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final FocusNode usernameFocus = FocusNode();
final FocusNode passwordFocus = FocusNode();
bool _obscurePassword = true;
bool get obscurePassword => _obscurePassword;
bool get isLoginEnabled =>
usernameController.text.isNotEmpty &&
passwordController.text.isNotEmpty;
// Auth state
bool _isLoading = false;
String? _errorMessage;
UserModel? _loggedInUser;
@@ -18,25 +34,44 @@ class AuthViewModel with ChangeNotifier {
String? get errorMessage => _errorMessage;
UserModel? get loggedInUser => _loggedInUser;
Future<void> login(String email, String password) async {
void togglePasswordVisibility() {
_obscurePassword = !_obscurePassword;
notifyListeners();
}
void _onTextChanged() {
notifyListeners();
}
Future<void> login() async {
_isLoading = true;
_errorMessage = null;
notifyListeners();
final result = await _authRepository.login(email, password);
final result = await _authRepository.login(
usernameController.text.trim(),
passwordController.text.trim(),
);
switch (result) {
case Ok<UserModel>():
_loggedInUser = result.value;
// موفقیت‌آمیز
break;
case Error<UserModel>():
_errorMessage = result.error.toString();
// خطا
break;
}
_isLoading = false;
notifyListeners();
}
@override
void dispose() {
usernameController.dispose();
passwordController.dispose();
usernameFocus.dispose();
passwordFocus.dispose();
super.dispose();
}
}
-42
View File
@@ -1,42 +0,0 @@
// lib/view_models/login_view_model.dart
import 'package:flutter/material.dart';
class LoginViewModel with ChangeNotifier {
final TextEditingController usernameController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final FocusNode usernameFocus = FocusNode();
final FocusNode passwordFocus = FocusNode();
bool _obscurePassword = true;
LoginViewModel() {
usernameController.addListener(_onTextChanged);
passwordController.addListener(_onTextChanged);
usernameFocus.addListener(_onTextChanged);
passwordFocus.addListener(_onTextChanged);
}
bool get obscurePassword => _obscurePassword;
bool get isLoginEnabled =>
usernameController.text.isNotEmpty &&
passwordController.text.isNotEmpty;
void togglePasswordVisibility() {
_obscurePassword = !_obscurePassword;
notifyListeners();
}
void _onTextChanged() {
notifyListeners();
}
@override
void dispose() {
usernameController.dispose();
passwordController.dispose();
usernameFocus.dispose();
passwordFocus.dispose();
super.dispose();
}
}
+28 -34
View File
@@ -1,36 +1,17 @@
// lib/views/login_desktop_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/core/theme/colors.dart';
import '../../../core/constants/assets.dart';
import '../../../core/constants/strings.dart';
import '../../../core/utils/size_config.dart';
import '../../../view_models/login_view_model.dart';
import '../../../view_models/auth_view_model.dart';
import '../widgets/widgets.dart';
class LoginDesktopPage extends StatefulWidget {
class LoginDesktopPage extends StatelessWidget {
const LoginDesktopPage({super.key});
@override
State<LoginDesktopPage> createState() => _LoginDesktopPageState();
}
class _LoginDesktopPageState extends State<LoginDesktopPage> {
late final LoginViewModel _viewModel;
@override
void initState() {
super.initState();
_viewModel = LoginViewModel();
}
@override
void dispose() {
_viewModel.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
SizeConfig.init(context);
@@ -41,9 +22,8 @@ class _LoginDesktopPageState extends State<LoginDesktopPage> {
padding: EdgeInsets.symmetric(horizontal: 24.0.w()),
child: SizedBox(
width: 526,
child: ListenableBuilder(
listenable: _viewModel,
builder: (context, _) {
child: Consumer<AuthViewModel>(
builder: (context, viewModel, _) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -53,8 +33,8 @@ class _LoginDesktopPageState extends State<LoginDesktopPage> {
SizedBox(height: 32.0.h()),
LoginTextField(
controller: _viewModel.usernameController,
focusNode: _viewModel.usernameFocus,
controller: viewModel.usernameController,
focusNode: viewModel.usernameFocus,
label: AppStrings.usernameLabel,
iconPath: AssetsManager.userIcon,
fieldHeight: 60.0.h(),
@@ -64,24 +44,38 @@ class _LoginDesktopPageState extends State<LoginDesktopPage> {
SizedBox(height: 16.0.h()),
LoginTextField(
controller: _viewModel.passwordController,
focusNode: _viewModel.passwordFocus,
controller: viewModel.passwordController,
focusNode: viewModel.passwordFocus,
label: AppStrings.passwordLabel,
iconPath: AssetsManager.passwordIcon,
prefixIconPadding: 4.0.w(),
isPassword: true,
obscureText: _viewModel.obscurePassword,
obscureText: viewModel.obscurePassword,
fieldHeight: 60.0.h(),
onToggleVisibility: _viewModel.togglePasswordVisibility,
onToggleVisibility: viewModel.togglePasswordVisibility,
borderRedus: 4.0.w(),
),
SizedBox(height: 32.0.h()),
if (viewModel.isLoading)
const CircularProgressIndicator()
else
BaseButton(
isEnabled: _viewModel.isLoginEnabled,
isEnabled: viewModel.isLoginEnabled,
onPressed:
_viewModel.isLoginEnabled
? () => HomeRouteData().go(context)
viewModel.isLoginEnabled
? () async {
await viewModel.login();
if (viewModel.loggedInUser != null) {
HomeRouteData().go(context);
} else if (viewModel.errorMessage != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(viewModel.errorMessage!),
),
);
}
}
: null,
),
],
+27 -34
View File
@@ -1,36 +1,17 @@
// lib/views/login_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/core/theme/colors.dart';
import '../../../core/constants/assets.dart';
import '../../../core/constants/strings.dart';
import '../../../core/utils/size_config.dart';
import '../../../view_models/auth_view_model.dart';
import '../widgets/widgets.dart';
import '../../../view_models/login_view_model.dart';
class LoginMobilePage extends StatefulWidget {
class LoginMobilePage extends StatelessWidget {
const LoginMobilePage({super.key});
@override
State<LoginMobilePage> createState() => _LoginMobilePageState();
}
class _LoginMobilePageState extends State<LoginMobilePage> {
late final LoginViewModel _viewModel;
@override
void initState() {
super.initState();
_viewModel = LoginViewModel();
}
@override
void dispose() {
_viewModel.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
SizeConfig.init(context);
@@ -40,9 +21,8 @@ class _LoginMobilePageState extends State<LoginMobilePage> {
body: Center(
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 24.0.w()),
child: ListenableBuilder(
listenable: _viewModel,
builder: (context, _) {
child: Consumer<AuthViewModel>(
builder: (context, viewModel, _) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -52,29 +32,42 @@ class _LoginMobilePageState extends State<LoginMobilePage> {
SizedBox(height: 32.0.h()),
LoginTextField(
controller: _viewModel.usernameController,
focusNode: _viewModel.usernameFocus,
controller: viewModel.usernameController,
focusNode: viewModel.usernameFocus,
label: AppStrings.usernameLabel,
iconPath: AssetsManager.userIcon,
),
SizedBox(height: 16.0.h()),
LoginTextField(
controller: _viewModel.passwordController,
focusNode: _viewModel.passwordFocus,
controller: viewModel.passwordController,
focusNode: viewModel.passwordFocus,
label: AppStrings.passwordLabel,
iconPath: AssetsManager.passwordIcon,
isPassword: true,
obscureText: _viewModel.obscurePassword,
onToggleVisibility: _viewModel.togglePasswordVisibility,
obscureText: viewModel.obscurePassword,
onToggleVisibility: viewModel.togglePasswordVisibility,
),
SizedBox(height: 32.0.h()),
if (viewModel.isLoading)
const CircularProgressIndicator()
else
BaseButton(
isEnabled: _viewModel.isLoginEnabled,
onPressed: _viewModel.isLoginEnabled
? () {
isEnabled: viewModel.isLoginEnabled,
onPressed:
viewModel.isLoginEnabled
? () async {
await viewModel.login();
if (viewModel.loggedInUser != null) {
HomeRouteData().go(context);
} else if (viewModel.errorMessage != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(viewModel.errorMessage!),
),
);
}
}
: null,
),
+28 -34
View File
@@ -1,36 +1,17 @@
// lib/views/login_tablet_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/core/theme/colors.dart';
import '../../../core/constants/assets.dart';
import '../../../core/constants/strings.dart';
import '../../../core/utils/size_config.dart';
import '../../../view_models/login_view_model.dart';
import '../../../view_models/auth_view_model.dart';
import '../widgets/widgets.dart';
class LoginTabletPage extends StatefulWidget {
class LoginTabletPage extends StatelessWidget {
const LoginTabletPage({super.key});
@override
State<LoginTabletPage> createState() => _LoginTabletPageState();
}
class _LoginTabletPageState extends State<LoginTabletPage> {
late final LoginViewModel _viewModel;
@override
void initState() {
super.initState();
_viewModel = LoginViewModel();
}
@override
void dispose() {
_viewModel.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
SizeConfig.init(context);
@@ -41,9 +22,8 @@ class _LoginTabletPageState extends State<LoginTabletPage> {
padding: EdgeInsets.symmetric(horizontal: 24.0.w()),
child: SizedBox(
width: 526,
child: ListenableBuilder(
listenable: _viewModel,
builder: (context, _) {
child: Consumer<AuthViewModel>(
builder: (context, viewModel, _) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -53,8 +33,8 @@ class _LoginTabletPageState extends State<LoginTabletPage> {
SizedBox(height: 32.0.h()),
LoginTextField(
controller: _viewModel.usernameController,
focusNode: _viewModel.usernameFocus,
controller: viewModel.usernameController,
focusNode: viewModel.usernameFocus,
label: AppStrings.usernameLabel,
iconPath: AssetsManager.userIcon,
fieldHeight: 60.0.h(),
@@ -64,24 +44,38 @@ class _LoginTabletPageState extends State<LoginTabletPage> {
SizedBox(height: 16.0.h()),
LoginTextField(
controller: _viewModel.passwordController,
focusNode: _viewModel.passwordFocus,
controller: viewModel.passwordController,
focusNode: viewModel.passwordFocus,
label: AppStrings.passwordLabel,
iconPath: AssetsManager.passwordIcon,
prefixIconPadding: 4.0.w(),
isPassword: true,
obscureText: _viewModel.obscurePassword,
obscureText: viewModel.obscurePassword,
fieldHeight: 60.0.h(),
onToggleVisibility: _viewModel.togglePasswordVisibility,
onToggleVisibility: viewModel.togglePasswordVisibility,
borderRedus: 4.0.w(),
),
SizedBox(height: 32.0.h()),
if (viewModel.isLoading)
const CircularProgressIndicator()
else
BaseButton(
isEnabled: _viewModel.isLoginEnabled,
isEnabled: viewModel.isLoginEnabled,
onPressed:
_viewModel.isLoginEnabled
? () => HomeRouteData().go(context)
viewModel.isLoginEnabled
? () async {
await viewModel.login();
if (viewModel.loggedInUser != null) {
HomeRouteData().go(context);
} else if (viewModel.errorMessage != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(viewModel.errorMessage!),
),
);
}
}
: null,
),
],