feat : auth live stock
This commit is contained in:
@@ -4,6 +4,8 @@ import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_inspection/injection/inspection_di.dart';
|
||||
import 'package:rasadyar_inspection/inspection.dart';
|
||||
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
|
||||
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
||||
|
||||
class CustomNavigationObserver extends NavigatorObserver {
|
||||
bool _isWorkDone = false;
|
||||
@@ -16,7 +18,7 @@ class CustomNavigationObserver extends NavigatorObserver {
|
||||
void didPush(Route route, Route? previousRoute) async {
|
||||
super.didPush(route, previousRoute);
|
||||
final routeName = route.settings.name;
|
||||
if (!_isWorkDone &&( routeName == ChickenRoutes.init || routeName == ChickenRoutes.auth)) {
|
||||
if (!_isWorkDone && (routeName == ChickenRoutes.init || routeName == ChickenRoutes.auth)) {
|
||||
_isWorkDone = true;
|
||||
await setupChickenDI();
|
||||
} else if (!_isWorkDone &&
|
||||
@@ -24,6 +26,10 @@ class CustomNavigationObserver extends NavigatorObserver {
|
||||
_isWorkDone = true;
|
||||
|
||||
await setupInspectionDI();
|
||||
} else if (!_isWorkDone &&
|
||||
(routeName == LiveStockRoutes.init || routeName == LiveStockRoutes.auth)) {
|
||||
_isWorkDone = true;
|
||||
await setupLiveStockDI();
|
||||
}
|
||||
tLog('CustomNavigationObserver: didPush - $routeName');
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ class ModulesLogic extends GetxController {
|
||||
|
||||
List<ModuleModel> moduleList = [
|
||||
ModuleModel(title: 'بازرسی', icon: Assets.icons.inspection.path, module: Module.inspection),
|
||||
// ModuleModel(title: 'دام', icon: Assets.icons.liveStock.path, module: Module.liveStocks),
|
||||
ModuleModel(title: 'دام', icon: Assets.icons.liveStock.path, module: Module.liveStocks),
|
||||
ModuleModel(title: 'مرغ', icon: Assets.icons.liveStock.path, module: Module.chicken),
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class DioErrorHandler {
|
||||
void handle(DioException error) {
|
||||
switch (error.response?.statusCode) {
|
||||
case 401:
|
||||
_handleGeneric(error);
|
||||
break;
|
||||
case 403:
|
||||
_handleGeneric(error);
|
||||
break;
|
||||
|
||||
case 410:
|
||||
_handle410();
|
||||
break;
|
||||
default:
|
||||
_handleGeneric(error);
|
||||
}
|
||||
}
|
||||
|
||||
//wrong password/user name => "detail": "No active account found with the given credentials" - 401
|
||||
void _handle410() {
|
||||
Get.showSnackbar(_errorSnackBar('نام کاربری یا رمز عبور اشتباه است'));
|
||||
}
|
||||
|
||||
//wrong captcha => "detail": "Captcha code is incorrect" - 403
|
||||
void _handle403() {}
|
||||
|
||||
void _handleGeneric(DioException error) {
|
||||
Get.showSnackbar(
|
||||
_errorSnackBar(
|
||||
error.response?.data.keys.first == 'is_user'
|
||||
? 'کاربر با این شماره تلفن وجود ندارد'
|
||||
: error.response?.data[error.response?.data.keys.first] ??
|
||||
'خطا در برقراری ارتباط با سرور',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
GetSnackBar _errorSnackBar(String message) {
|
||||
return GetSnackBar(
|
||||
titleText: Text(
|
||||
'خطا',
|
||||
style: AppFonts.yekan14.copyWith(color: Colors.white),
|
||||
),
|
||||
messageText: Text(
|
||||
message,
|
||||
style: AppFonts.yekan12.copyWith(color: Colors.white),
|
||||
),
|
||||
backgroundColor: AppColor.error,
|
||||
margin: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
borderRadius: 12,
|
||||
duration: Duration(milliseconds: 3500),
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
|
||||
|
||||
abstract class AuthRemoteDataSource {
|
||||
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest});
|
||||
|
||||
Future<CaptchaResponseModel?> captcha();
|
||||
|
||||
Future<void> logout();
|
||||
|
||||
Future<bool> hasAuthenticated();
|
||||
|
||||
Future<AuthResponseModel?> loginWithRefreshToken({required Map<String, dynamic> authRequest});
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
|
||||
|
||||
import 'auth_remote.dart';
|
||||
|
||||
class AuthRemoteDataSourceImp extends AuthRemoteDataSource {
|
||||
final DioRemote _httpClient;
|
||||
final String _BASE_URL = 'auth/api/v1/';
|
||||
|
||||
AuthRemoteDataSourceImp(this._httpClient);
|
||||
|
||||
@override
|
||||
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest}) async {
|
||||
var res = await _httpClient.post<AuthResponseModel?>(
|
||||
'${_BASE_URL}login/',
|
||||
data: authRequest,
|
||||
fromJson: AuthResponseModel.fromJson,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CaptchaResponseModel?> captcha() async {
|
||||
var res = await _httpClient.post<CaptchaResponseModel?>(
|
||||
'captcha/',
|
||||
fromJson: CaptchaResponseModel.fromJson,
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthResponseModel?> loginWithRefreshToken({
|
||||
required Map<String, dynamic> authRequest,
|
||||
}) async {
|
||||
var res = await _httpClient.post<AuthResponseModel>(
|
||||
'$_BASE_URL/login/',
|
||||
data: authRequest,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> logout() {
|
||||
// TODO: implement logout
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> hasAuthenticated() async {
|
||||
final response = await _httpClient.get<bool>(
|
||||
'$_BASE_URL/login/',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
);
|
||||
|
||||
return response.data ?? false;
|
||||
}
|
||||
|
||||
/* @override
|
||||
Future<UserProfileModel?> getUserInfo(String phoneNumber) async {
|
||||
var res = await _httpClient.post<UserProfileModel?>(
|
||||
'https://userbackend.rasadyaar.ir/api/send_otp/',
|
||||
data: {"mobile": phoneNumber, "state": ""},
|
||||
fromJson: UserProfileModel.fromJson,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
);
|
||||
return res.data;
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
part 'login_request_model.freezed.dart';
|
||||
part 'login_request_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class LoginRequestModel with _$LoginRequestModel {
|
||||
const factory LoginRequestModel({
|
||||
String? username,
|
||||
String? password,
|
||||
String? captchaCode,
|
||||
String? captchaKey,
|
||||
}) = _LoginRequestModel;
|
||||
|
||||
factory LoginRequestModel.createWithCaptcha({
|
||||
required String username,
|
||||
required String password,
|
||||
required String captchaCode,
|
||||
required String captchaKey,
|
||||
}) {
|
||||
return LoginRequestModel(
|
||||
username: username,
|
||||
password: password,
|
||||
captchaCode: captchaCode,
|
||||
captchaKey: 'rest_captcha_$captchaKey.0',
|
||||
);
|
||||
}
|
||||
|
||||
factory LoginRequestModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$LoginRequestModelFromJson(json);
|
||||
|
||||
const LoginRequestModel._();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'login_request_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$LoginRequestModel {
|
||||
|
||||
String? get username; String? get password; String? get captchaCode; String? get captchaKey;
|
||||
/// Create a copy of LoginRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$LoginRequestModelCopyWith<LoginRequestModel> get copyWith => _$LoginRequestModelCopyWithImpl<LoginRequestModel>(this as LoginRequestModel, _$identity);
|
||||
|
||||
/// Serializes this LoginRequestModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is LoginRequestModel&&(identical(other.username, username) || other.username == username)&&(identical(other.password, password) || other.password == password)&&(identical(other.captchaCode, captchaCode) || other.captchaCode == captchaCode)&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,username,password,captchaCode,captchaKey);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LoginRequestModel(username: $username, password: $password, captchaCode: $captchaCode, captchaKey: $captchaKey)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $LoginRequestModelCopyWith<$Res> {
|
||||
factory $LoginRequestModelCopyWith(LoginRequestModel value, $Res Function(LoginRequestModel) _then) = _$LoginRequestModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? username, String? password, String? captchaCode, String? captchaKey
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$LoginRequestModelCopyWithImpl<$Res>
|
||||
implements $LoginRequestModelCopyWith<$Res> {
|
||||
_$LoginRequestModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final LoginRequestModel _self;
|
||||
final $Res Function(LoginRequestModel) _then;
|
||||
|
||||
/// Create a copy of LoginRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? username = freezed,Object? password = freezed,Object? captchaCode = freezed,Object? captchaKey = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
username: freezed == username ? _self.username : username // ignore: cast_nullable_to_non_nullable
|
||||
as String?,password: freezed == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String?,captchaCode: freezed == captchaCode ? _self.captchaCode : captchaCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [LoginRequestModel].
|
||||
extension LoginRequestModelPatterns on LoginRequestModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LoginRequestModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginRequestModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LoginRequestModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginRequestModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LoginRequestModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginRequestModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? username, String? password, String? captchaCode, String? captchaKey)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginRequestModel() when $default != null:
|
||||
return $default(_that.username,_that.password,_that.captchaCode,_that.captchaKey);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? username, String? password, String? captchaCode, String? captchaKey) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginRequestModel():
|
||||
return $default(_that.username,_that.password,_that.captchaCode,_that.captchaKey);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? username, String? password, String? captchaCode, String? captchaKey)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginRequestModel() when $default != null:
|
||||
return $default(_that.username,_that.password,_that.captchaCode,_that.captchaKey);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _LoginRequestModel extends LoginRequestModel {
|
||||
const _LoginRequestModel({this.username, this.password, this.captchaCode, this.captchaKey}): super._();
|
||||
factory _LoginRequestModel.fromJson(Map<String, dynamic> json) => _$LoginRequestModelFromJson(json);
|
||||
|
||||
@override final String? username;
|
||||
@override final String? password;
|
||||
@override final String? captchaCode;
|
||||
@override final String? captchaKey;
|
||||
|
||||
/// Create a copy of LoginRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$LoginRequestModelCopyWith<_LoginRequestModel> get copyWith => __$LoginRequestModelCopyWithImpl<_LoginRequestModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$LoginRequestModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LoginRequestModel&&(identical(other.username, username) || other.username == username)&&(identical(other.password, password) || other.password == password)&&(identical(other.captchaCode, captchaCode) || other.captchaCode == captchaCode)&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,username,password,captchaCode,captchaKey);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LoginRequestModel(username: $username, password: $password, captchaCode: $captchaCode, captchaKey: $captchaKey)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$LoginRequestModelCopyWith<$Res> implements $LoginRequestModelCopyWith<$Res> {
|
||||
factory _$LoginRequestModelCopyWith(_LoginRequestModel value, $Res Function(_LoginRequestModel) _then) = __$LoginRequestModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? username, String? password, String? captchaCode, String? captchaKey
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$LoginRequestModelCopyWithImpl<$Res>
|
||||
implements _$LoginRequestModelCopyWith<$Res> {
|
||||
__$LoginRequestModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _LoginRequestModel _self;
|
||||
final $Res Function(_LoginRequestModel) _then;
|
||||
|
||||
/// Create a copy of LoginRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? username = freezed,Object? password = freezed,Object? captchaCode = freezed,Object? captchaKey = freezed,}) {
|
||||
return _then(_LoginRequestModel(
|
||||
username: freezed == username ? _self.username : username // ignore: cast_nullable_to_non_nullable
|
||||
as String?,password: freezed == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String?,captchaCode: freezed == captchaCode ? _self.captchaCode : captchaCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,23 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'login_request_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_LoginRequestModel _$LoginRequestModelFromJson(Map<String, dynamic> json) =>
|
||||
_LoginRequestModel(
|
||||
username: json['username'] as String?,
|
||||
password: json['password'] as String?,
|
||||
captchaCode: json['captcha_code'] as String?,
|
||||
captchaKey: json['captcha_key'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LoginRequestModelToJson(_LoginRequestModel instance) =>
|
||||
<String, dynamic>{
|
||||
'username': instance.username,
|
||||
'password': instance.password,
|
||||
'captcha_code': instance.captchaCode,
|
||||
'captcha_key': instance.captchaKey,
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'auth_response_model.freezed.dart';
|
||||
part 'auth_response_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class AuthResponseModel with _$AuthResponseModel {
|
||||
const factory AuthResponseModel({
|
||||
String? refresh,
|
||||
String? access,
|
||||
bool? otpStatus,
|
||||
}) = _AuthResponseModel;
|
||||
|
||||
factory AuthResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$AuthResponseModelFromJson(json);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'auth_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AuthResponseModel {
|
||||
|
||||
String? get refresh; String? get access; bool? get otpStatus;
|
||||
/// Create a copy of AuthResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AuthResponseModelCopyWith<AuthResponseModel> get copyWith => _$AuthResponseModelCopyWithImpl<AuthResponseModel>(this as AuthResponseModel, _$identity);
|
||||
|
||||
/// Serializes this AuthResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AuthResponseModel&&(identical(other.refresh, refresh) || other.refresh == refresh)&&(identical(other.access, access) || other.access == access)&&(identical(other.otpStatus, otpStatus) || other.otpStatus == otpStatus));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,refresh,access,otpStatus);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthResponseModel(refresh: $refresh, access: $access, otpStatus: $otpStatus)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AuthResponseModelCopyWith<$Res> {
|
||||
factory $AuthResponseModelCopyWith(AuthResponseModel value, $Res Function(AuthResponseModel) _then) = _$AuthResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? refresh, String? access, bool? otpStatus
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AuthResponseModelCopyWithImpl<$Res>
|
||||
implements $AuthResponseModelCopyWith<$Res> {
|
||||
_$AuthResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AuthResponseModel _self;
|
||||
final $Res Function(AuthResponseModel) _then;
|
||||
|
||||
/// Create a copy of AuthResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? refresh = freezed,Object? access = freezed,Object? otpStatus = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
refresh: freezed == refresh ? _self.refresh : refresh // ignore: cast_nullable_to_non_nullable
|
||||
as String?,access: freezed == access ? _self.access : access // ignore: cast_nullable_to_non_nullable
|
||||
as String?,otpStatus: freezed == otpStatus ? _self.otpStatus : otpStatus // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [AuthResponseModel].
|
||||
extension AuthResponseModelPatterns on AuthResponseModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AuthResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AuthResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AuthResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AuthResponseModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AuthResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AuthResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? refresh, String? access, bool? otpStatus)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AuthResponseModel() when $default != null:
|
||||
return $default(_that.refresh,_that.access,_that.otpStatus);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? refresh, String? access, bool? otpStatus) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AuthResponseModel():
|
||||
return $default(_that.refresh,_that.access,_that.otpStatus);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? refresh, String? access, bool? otpStatus)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AuthResponseModel() when $default != null:
|
||||
return $default(_that.refresh,_that.access,_that.otpStatus);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _AuthResponseModel implements AuthResponseModel {
|
||||
const _AuthResponseModel({this.refresh, this.access, this.otpStatus});
|
||||
factory _AuthResponseModel.fromJson(Map<String, dynamic> json) => _$AuthResponseModelFromJson(json);
|
||||
|
||||
@override final String? refresh;
|
||||
@override final String? access;
|
||||
@override final bool? otpStatus;
|
||||
|
||||
/// Create a copy of AuthResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$AuthResponseModelCopyWith<_AuthResponseModel> get copyWith => __$AuthResponseModelCopyWithImpl<_AuthResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$AuthResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AuthResponseModel&&(identical(other.refresh, refresh) || other.refresh == refresh)&&(identical(other.access, access) || other.access == access)&&(identical(other.otpStatus, otpStatus) || other.otpStatus == otpStatus));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,refresh,access,otpStatus);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthResponseModel(refresh: $refresh, access: $access, otpStatus: $otpStatus)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$AuthResponseModelCopyWith<$Res> implements $AuthResponseModelCopyWith<$Res> {
|
||||
factory _$AuthResponseModelCopyWith(_AuthResponseModel value, $Res Function(_AuthResponseModel) _then) = __$AuthResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? refresh, String? access, bool? otpStatus
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$AuthResponseModelCopyWithImpl<$Res>
|
||||
implements _$AuthResponseModelCopyWith<$Res> {
|
||||
__$AuthResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _AuthResponseModel _self;
|
||||
final $Res Function(_AuthResponseModel) _then;
|
||||
|
||||
/// Create a copy of AuthResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? refresh = freezed,Object? access = freezed,Object? otpStatus = freezed,}) {
|
||||
return _then(_AuthResponseModel(
|
||||
refresh: freezed == refresh ? _self.refresh : refresh // ignore: cast_nullable_to_non_nullable
|
||||
as String?,access: freezed == access ? _self.access : access // ignore: cast_nullable_to_non_nullable
|
||||
as String?,otpStatus: freezed == otpStatus ? _self.otpStatus : otpStatus // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'auth_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_AuthResponseModel _$AuthResponseModelFromJson(Map<String, dynamic> json) =>
|
||||
_AuthResponseModel(
|
||||
refresh: json['refresh'] as String?,
|
||||
access: json['access'] as String?,
|
||||
otpStatus: json['otp_status'] as bool?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AuthResponseModelToJson(_AuthResponseModel instance) =>
|
||||
<String, dynamic>{
|
||||
'refresh': instance.refresh,
|
||||
'access': instance.access,
|
||||
'otp_status': instance.otpStatus,
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'captcha_response_model.freezed.dart';
|
||||
part 'captcha_response_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class CaptchaResponseModel with _$CaptchaResponseModel {
|
||||
const factory CaptchaResponseModel({
|
||||
String? captchaKey,
|
||||
String? captchaImage,
|
||||
String? imageType,
|
||||
String? imageDecode,
|
||||
}) = _CaptchaResponseModel;
|
||||
|
||||
factory CaptchaResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$CaptchaResponseModelFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'captcha_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$CaptchaResponseModel {
|
||||
|
||||
String? get captchaKey; String? get captchaImage; String? get imageType; String? get imageDecode;
|
||||
/// Create a copy of CaptchaResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$CaptchaResponseModelCopyWith<CaptchaResponseModel> get copyWith => _$CaptchaResponseModelCopyWithImpl<CaptchaResponseModel>(this as CaptchaResponseModel, _$identity);
|
||||
|
||||
/// Serializes this CaptchaResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CaptchaResponseModel&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey)&&(identical(other.captchaImage, captchaImage) || other.captchaImage == captchaImage)&&(identical(other.imageType, imageType) || other.imageType == imageType)&&(identical(other.imageDecode, imageDecode) || other.imageDecode == imageDecode));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,captchaKey,captchaImage,imageType,imageDecode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CaptchaResponseModel(captchaKey: $captchaKey, captchaImage: $captchaImage, imageType: $imageType, imageDecode: $imageDecode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $CaptchaResponseModelCopyWith<$Res> {
|
||||
factory $CaptchaResponseModelCopyWith(CaptchaResponseModel value, $Res Function(CaptchaResponseModel) _then) = _$CaptchaResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? captchaKey, String? captchaImage, String? imageType, String? imageDecode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$CaptchaResponseModelCopyWithImpl<$Res>
|
||||
implements $CaptchaResponseModelCopyWith<$Res> {
|
||||
_$CaptchaResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final CaptchaResponseModel _self;
|
||||
final $Res Function(CaptchaResponseModel) _then;
|
||||
|
||||
/// Create a copy of CaptchaResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? captchaKey = freezed,Object? captchaImage = freezed,Object? imageType = freezed,Object? imageDecode = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
|
||||
as String?,captchaImage: freezed == captchaImage ? _self.captchaImage : captchaImage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,imageType: freezed == imageType ? _self.imageType : imageType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,imageDecode: freezed == imageDecode ? _self.imageDecode : imageDecode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [CaptchaResponseModel].
|
||||
extension CaptchaResponseModelPatterns on CaptchaResponseModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _CaptchaResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CaptchaResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _CaptchaResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CaptchaResponseModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _CaptchaResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CaptchaResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? captchaKey, String? captchaImage, String? imageType, String? imageDecode)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CaptchaResponseModel() when $default != null:
|
||||
return $default(_that.captchaKey,_that.captchaImage,_that.imageType,_that.imageDecode);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? captchaKey, String? captchaImage, String? imageType, String? imageDecode) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CaptchaResponseModel():
|
||||
return $default(_that.captchaKey,_that.captchaImage,_that.imageType,_that.imageDecode);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? captchaKey, String? captchaImage, String? imageType, String? imageDecode)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CaptchaResponseModel() when $default != null:
|
||||
return $default(_that.captchaKey,_that.captchaImage,_that.imageType,_that.imageDecode);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _CaptchaResponseModel implements CaptchaResponseModel {
|
||||
const _CaptchaResponseModel({this.captchaKey, this.captchaImage, this.imageType, this.imageDecode});
|
||||
factory _CaptchaResponseModel.fromJson(Map<String, dynamic> json) => _$CaptchaResponseModelFromJson(json);
|
||||
|
||||
@override final String? captchaKey;
|
||||
@override final String? captchaImage;
|
||||
@override final String? imageType;
|
||||
@override final String? imageDecode;
|
||||
|
||||
/// Create a copy of CaptchaResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$CaptchaResponseModelCopyWith<_CaptchaResponseModel> get copyWith => __$CaptchaResponseModelCopyWithImpl<_CaptchaResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$CaptchaResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CaptchaResponseModel&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey)&&(identical(other.captchaImage, captchaImage) || other.captchaImage == captchaImage)&&(identical(other.imageType, imageType) || other.imageType == imageType)&&(identical(other.imageDecode, imageDecode) || other.imageDecode == imageDecode));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,captchaKey,captchaImage,imageType,imageDecode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CaptchaResponseModel(captchaKey: $captchaKey, captchaImage: $captchaImage, imageType: $imageType, imageDecode: $imageDecode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$CaptchaResponseModelCopyWith<$Res> implements $CaptchaResponseModelCopyWith<$Res> {
|
||||
factory _$CaptchaResponseModelCopyWith(_CaptchaResponseModel value, $Res Function(_CaptchaResponseModel) _then) = __$CaptchaResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? captchaKey, String? captchaImage, String? imageType, String? imageDecode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$CaptchaResponseModelCopyWithImpl<$Res>
|
||||
implements _$CaptchaResponseModelCopyWith<$Res> {
|
||||
__$CaptchaResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _CaptchaResponseModel _self;
|
||||
final $Res Function(_CaptchaResponseModel) _then;
|
||||
|
||||
/// Create a copy of CaptchaResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? captchaKey = freezed,Object? captchaImage = freezed,Object? imageType = freezed,Object? imageDecode = freezed,}) {
|
||||
return _then(_CaptchaResponseModel(
|
||||
captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
|
||||
as String?,captchaImage: freezed == captchaImage ? _self.captchaImage : captchaImage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,imageType: freezed == imageType ? _self.imageType : imageType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,imageDecode: freezed == imageDecode ? _self.imageDecode : imageDecode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,25 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'captcha_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_CaptchaResponseModel _$CaptchaResponseModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _CaptchaResponseModel(
|
||||
captchaKey: json['captcha_key'] as String?,
|
||||
captchaImage: json['captcha_image'] as String?,
|
||||
imageType: json['image_type'] as String?,
|
||||
imageDecode: json['image_decode'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CaptchaResponseModelToJson(
|
||||
_CaptchaResponseModel instance,
|
||||
) => <String, dynamic>{
|
||||
'captcha_key': instance.captchaKey,
|
||||
'captcha_image': instance.captchaImage,
|
||||
'image_type': instance.imageType,
|
||||
'image_decode': instance.imageDecode,
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
part 'user_profile_model.freezed.dart';
|
||||
|
||||
part 'user_profile_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class UserProfileModel with _$UserProfileModel {
|
||||
const factory UserProfileModel({
|
||||
required User user,
|
||||
required Role role,
|
||||
required List<Permission> permissions,
|
||||
}) = _UserProfileModel;
|
||||
|
||||
factory UserProfileModel.fromJson(Map<String, dynamic> json) => _$UserProfileModelFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class User with _$User {
|
||||
const factory User({
|
||||
required int id,
|
||||
required String username,
|
||||
required String password,
|
||||
required String firstName,
|
||||
required String lastName,
|
||||
required bool isActive,
|
||||
required String mobile,
|
||||
required String phone,
|
||||
required String nationalCode,
|
||||
required DateTime birthdate,
|
||||
required String nationality,
|
||||
required String ownership,
|
||||
required String address,
|
||||
required String photo,
|
||||
required int province,
|
||||
required int city,
|
||||
required bool otpStatus,
|
||||
required String cityName,
|
||||
required String provinceName,
|
||||
}) = _User;
|
||||
|
||||
|
||||
|
||||
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class Role with _$Role {
|
||||
const factory Role({
|
||||
required int id,
|
||||
required String roleName,
|
||||
required String description,
|
||||
required RoleType type,
|
||||
required List<dynamic> permissions,
|
||||
}) = _Role;
|
||||
|
||||
factory Role.fromJson(Map<String, dynamic> json) => _$RoleFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class RoleType with _$RoleType {
|
||||
const factory RoleType({String? key, required String name}) = _RoleType;
|
||||
|
||||
factory RoleType.fromJson(Map<String, dynamic> json) => _$RoleTypeFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class Permission with _$Permission {
|
||||
const factory Permission({required String pageName, required List<String> pageAccess}) =
|
||||
_Permission;
|
||||
|
||||
factory Permission.fromJson(Map<String, dynamic> json) => _$PermissionFromJson(json);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'user_profile_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_UserProfileModel _$UserProfileModelFromJson(Map<String, dynamic> json) =>
|
||||
_UserProfileModel(
|
||||
user: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
role: Role.fromJson(json['role'] as Map<String, dynamic>),
|
||||
permissions: (json['permissions'] as List<dynamic>)
|
||||
.map((e) => Permission.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UserProfileModelToJson(_UserProfileModel instance) =>
|
||||
<String, dynamic>{
|
||||
'user': instance.user,
|
||||
'role': instance.role,
|
||||
'permissions': instance.permissions,
|
||||
};
|
||||
|
||||
_User _$UserFromJson(Map<String, dynamic> json) => _User(
|
||||
id: (json['id'] as num).toInt(),
|
||||
username: json['username'] as String,
|
||||
password: json['password'] as String,
|
||||
firstName: json['first_name'] as String,
|
||||
lastName: json['last_name'] as String,
|
||||
isActive: json['is_active'] as bool,
|
||||
mobile: json['mobile'] as String,
|
||||
phone: json['phone'] as String,
|
||||
nationalCode: json['national_code'] as String,
|
||||
birthdate: DateTime.parse(json['birthdate'] as String),
|
||||
nationality: json['nationality'] as String,
|
||||
ownership: json['ownership'] as String,
|
||||
address: json['address'] as String,
|
||||
photo: json['photo'] as String,
|
||||
province: (json['province'] as num).toInt(),
|
||||
city: (json['city'] as num).toInt(),
|
||||
otpStatus: json['otp_status'] as bool,
|
||||
cityName: json['city_name'] as String,
|
||||
provinceName: json['province_name'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UserToJson(_User instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'username': instance.username,
|
||||
'password': instance.password,
|
||||
'first_name': instance.firstName,
|
||||
'last_name': instance.lastName,
|
||||
'is_active': instance.isActive,
|
||||
'mobile': instance.mobile,
|
||||
'phone': instance.phone,
|
||||
'national_code': instance.nationalCode,
|
||||
'birthdate': instance.birthdate.toIso8601String(),
|
||||
'nationality': instance.nationality,
|
||||
'ownership': instance.ownership,
|
||||
'address': instance.address,
|
||||
'photo': instance.photo,
|
||||
'province': instance.province,
|
||||
'city': instance.city,
|
||||
'otp_status': instance.otpStatus,
|
||||
'city_name': instance.cityName,
|
||||
'province_name': instance.provinceName,
|
||||
};
|
||||
|
||||
_Role _$RoleFromJson(Map<String, dynamic> json) => _Role(
|
||||
id: (json['id'] as num).toInt(),
|
||||
roleName: json['role_name'] as String,
|
||||
description: json['description'] as String,
|
||||
type: RoleType.fromJson(json['type'] as Map<String, dynamic>),
|
||||
permissions: json['permissions'] as List<dynamic>,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$RoleToJson(_Role instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'role_name': instance.roleName,
|
||||
'description': instance.description,
|
||||
'type': instance.type,
|
||||
'permissions': instance.permissions,
|
||||
};
|
||||
|
||||
_RoleType _$RoleTypeFromJson(Map<String, dynamic> json) =>
|
||||
_RoleType(key: json['key'] as String?, name: json['name'] as String);
|
||||
|
||||
Map<String, dynamic> _$RoleTypeToJson(_RoleType instance) => <String, dynamic>{
|
||||
'key': instance.key,
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
_Permission _$PermissionFromJson(Map<String, dynamic> json) => _Permission(
|
||||
pageName: json['page_name'] as String,
|
||||
pageAccess: (json['page_access'] as List<dynamic>)
|
||||
.map((e) => e as String)
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PermissionToJson(_Permission instance) =>
|
||||
<String, dynamic>{
|
||||
'page_name': instance.pageName,
|
||||
'page_access': instance.pageAccess,
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
|
||||
|
||||
abstract class AuthRepository {
|
||||
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest});
|
||||
|
||||
Future<CaptchaResponseModel?> captcha();
|
||||
|
||||
Future<void> logout();
|
||||
|
||||
Future<bool> hasAuthenticated();
|
||||
|
||||
Future<AuthResponseModel?> loginWithRefreshToken({required Map<String, dynamic> authRequest});
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:rasadyar_livestock/data/data_source/remote/auth/auth_remote.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
|
||||
|
||||
import 'auth_repository.dart';
|
||||
|
||||
class AuthRepositoryImp implements AuthRepository {
|
||||
final AuthRemoteDataSource authRemote;
|
||||
|
||||
AuthRepositoryImp(this.authRemote);
|
||||
|
||||
@override
|
||||
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest}) async =>
|
||||
await authRemote.login(authRequest: authRequest);
|
||||
|
||||
@override
|
||||
Future<CaptchaResponseModel?> captcha() async {
|
||||
return await authRemote.captcha();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthResponseModel?> loginWithRefreshToken({
|
||||
required Map<String, dynamic> authRequest,
|
||||
}) async {
|
||||
return await authRemote.loginWithRefreshToken(authRequest: authRequest);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> logout() async {
|
||||
await authRemote.logout();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> hasAuthenticated() async {
|
||||
return await authRemote.hasAuthenticated();
|
||||
}
|
||||
}
|
||||
59
packages/livestock/lib/injection/live_stock_di.dart
Normal file
59
packages/livestock/lib/injection/live_stock_di.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_livestock/data/common/dio_exception_handeler.dart';
|
||||
import 'package:rasadyar_livestock/data/data_source/remote/auth/auth_remote.dart';
|
||||
import 'package:rasadyar_livestock/data/data_source/remote/auth/auth_remote_imp.dart';
|
||||
import 'package:rasadyar_livestock/data/repository/auth/auth_repository_imp.dart';
|
||||
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
||||
|
||||
GetIt get diLiveStock => GetIt.instance;
|
||||
|
||||
Future setupLiveStockDI() async {
|
||||
diLiveStock.registerSingleton(DioErrorHandler());
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
if (tokenService.baseurl.value == null) {
|
||||
await tokenService.saveBaseUrl('https://api.dam.rasadyar.net/');
|
||||
}
|
||||
diLiveStock.registerLazySingleton<AppInterceptor>(
|
||||
() => AppInterceptor(
|
||||
refreshTokenCallback: () async {
|
||||
var authRepository = diLiveStock.get<AuthRepositoryImp>();
|
||||
var hasAuthenticated = await authRepository.hasAuthenticated();
|
||||
if (hasAuthenticated) {
|
||||
var newToken = await authRepository.loginWithRefreshToken(
|
||||
authRequest: {'refresh': tokenService.refreshToken.value},
|
||||
);
|
||||
return newToken?.access;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
saveTokenCallback: (String newToken) async {
|
||||
await tokenService.saveAccessToken(newToken);
|
||||
},
|
||||
clearTokenCallback: () async {
|
||||
await tokenService.deleteTokens();
|
||||
Get.offAllNamed(LiveStockRoutes.auth, arguments: Module.liveStocks);
|
||||
},
|
||||
authArguments: Module.liveStocks,
|
||||
),
|
||||
);
|
||||
|
||||
// Register the DioRemote client
|
||||
diLiveStock.registerLazySingleton<DioRemote>(
|
||||
() => DioRemote(
|
||||
baseUrl: tokenService.baseurl.value,
|
||||
interceptors: diLiveStock.get<AppInterceptor>(),
|
||||
),
|
||||
);
|
||||
var dioRemoteClient = diLiveStock.get<DioRemote>();
|
||||
await dioRemoteClient.init();
|
||||
|
||||
// Register the AuthRemote data source implementation
|
||||
diLiveStock.registerLazySingleton<AuthRemoteDataSource>(
|
||||
() => AuthRemoteDataSourceImp(diLiveStock.get<DioRemote>()),
|
||||
);
|
||||
|
||||
// Register the AuthRepository implementation
|
||||
diLiveStock.registerLazySingleton<AuthRepositoryImp>(
|
||||
() => AuthRepositoryImp(diLiveStock.get<AuthRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
188
packages/livestock/lib/presentation/page/auth/logic.dart
Normal file
188
packages/livestock/lib/presentation/page/auth/logic.dart
Normal file
@@ -0,0 +1,188 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_livestock/data/common/dio_exception_handeler.dart';
|
||||
import 'package:rasadyar_livestock/data/model/request/login_request/login_request_model.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
|
||||
import 'package:rasadyar_livestock/data/repository/auth/auth_repository_imp.dart';
|
||||
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
|
||||
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
||||
import 'package:rasadyar_livestock/presentation/widgets/captcha/logic.dart';
|
||||
|
||||
enum AuthType { useAndPass, otp }
|
||||
|
||||
enum AuthStatus { init }
|
||||
|
||||
enum OtpStatus { init, sent, verified, reSend }
|
||||
|
||||
class AuthLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
late AnimationController _textAnimationController;
|
||||
late Animation<double> textAnimation;
|
||||
RxBool showCard = false.obs;
|
||||
|
||||
Rx<GlobalKey<FormState>> formKeyOtp = GlobalKey<FormState>().obs;
|
||||
Rx<GlobalKey<FormState>> formKeySentOtp = GlobalKey<FormState>().obs;
|
||||
Rx<TextEditingController> usernameController = TextEditingController().obs;
|
||||
Rx<TextEditingController> passwordController = TextEditingController().obs;
|
||||
Rx<TextEditingController> phoneOtpNumberController = TextEditingController().obs;
|
||||
Rx<TextEditingController> otpCodeController = TextEditingController().obs;
|
||||
|
||||
var captchaController = Get.find<CaptchaWidgetLogic>();
|
||||
|
||||
RxnString phoneNumber = RxnString(null);
|
||||
RxBool isLoading = false.obs;
|
||||
RxBool isDisabled = true.obs;
|
||||
TokenStorageService tokenStorageService = Get.find<TokenStorageService>();
|
||||
|
||||
Rx<AuthType> authType = AuthType.useAndPass.obs;
|
||||
Rx<AuthStatus> authStatus = AuthStatus.init.obs;
|
||||
Rx<OtpStatus> otpStatus = OtpStatus.init.obs;
|
||||
|
||||
RxInt secondsRemaining = 120.obs;
|
||||
Timer? _timer;
|
||||
|
||||
AuthRepositoryImp authRepository = diLiveStock.get<AuthRepositoryImp>();
|
||||
|
||||
final Module _module = Get.arguments;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
_textAnimationController =
|
||||
AnimationController(vsync: this, duration: const Duration(milliseconds: 1200))
|
||||
..repeat(reverse: true, count: 2).whenComplete(() {
|
||||
showCard.value = true;
|
||||
});
|
||||
|
||||
textAnimation = CurvedAnimation(parent: _textAnimationController, curve: Curves.easeInOut);
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
//_textAnimationController.forward();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_timer?.cancel();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void startTimer() {
|
||||
_timer?.cancel();
|
||||
secondsRemaining.value = 120;
|
||||
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if (secondsRemaining.value > 0) {
|
||||
secondsRemaining.value--;
|
||||
} else {
|
||||
timer.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void stopTimer() {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
String get timeFormatted {
|
||||
final minutes = secondsRemaining.value ~/ 60;
|
||||
final seconds = secondsRemaining.value % 60;
|
||||
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
bool _isFormValid() {
|
||||
final isCaptchaValid = captchaController.formKey.currentState?.validate() ?? false;
|
||||
final isFormValid = formKey.currentState?.validate() ?? false;
|
||||
return isCaptchaValid && isFormValid;
|
||||
}
|
||||
|
||||
LoginRequestModel _buildLoginRequest() {
|
||||
final phone = usernameController.value.text;
|
||||
final pass = passwordController.value.text;
|
||||
final code = captchaController.textController.value.text;
|
||||
final key = captchaController.captchaKey.value;
|
||||
|
||||
return LoginRequestModel.createWithCaptcha(
|
||||
username: phone,
|
||||
password: pass,
|
||||
captchaCode: code,
|
||||
captchaKey: key!,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> submitLoginForm() async {
|
||||
if (!_isFormValid()) return;
|
||||
|
||||
final loginRequestModel = _buildLoginRequest();
|
||||
isLoading.value = true;
|
||||
await safeCall<AuthResponseModel?>(
|
||||
call: () async => authRepository.login(authRequest: loginRequestModel.toJson()),
|
||||
onSuccess: (result) async {
|
||||
await tokenStorageService.saveModule(_module);
|
||||
await tokenStorageService.saveRefreshToken(result?.refresh ?? '');
|
||||
await tokenStorageService.saveAccessToken(result?.access ?? '');
|
||||
Get.offAllNamed(LiveStockRoutes.init);
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
if (error is DioException) {
|
||||
diLiveStock.get<DioErrorHandler>().handle(error);
|
||||
}
|
||||
captchaController.getCaptcha();
|
||||
},
|
||||
);
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
Future<void> submitLoginForm2() async {
|
||||
if (!_isFormValid()) return;
|
||||
//AuthRepositoryImpl authTmp = diAuth.get<AuthRepositoryImpl>(instanceName: 'newUrl');
|
||||
isLoading.value = true;
|
||||
/* await safeCall<UserProfileModel?>(
|
||||
call: () => authTmp.login(
|
||||
authRequest: {
|
||||
"username": usernameController.value.text,
|
||||
"password": passwordController.value.text,
|
||||
},
|
||||
),
|
||||
onSuccess: (result) async {
|
||||
await tokenStorageService.saveModule(_module);
|
||||
await tokenStorageService.saveAccessToken(result?.accessToken ?? '');
|
||||
await tokenStorageService.saveRefreshToken(result?.accessToken ?? '');
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
if (error is DioException) {
|
||||
// diAuth.get<DioErrorHandler>().handle(error);
|
||||
}
|
||||
captchaController.getCaptcha();
|
||||
},
|
||||
);*/
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
Future<void> getUserInfo(String value) async {
|
||||
isLoading.value = true;
|
||||
/*await safeCall<UserInfoModel?>(
|
||||
call: () async => await authRepository.getUserInfo(value),
|
||||
onSuccess: (result) async {
|
||||
if (result != null) {
|
||||
//await newSetupAuthDI(result.backend ?? '');
|
||||
await tokenStorageService.saveApiKey(result.apiKey ?? '');
|
||||
await tokenStorageService.saveBaseUrl(result.backend ?? '');
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
if (error is DioException) {
|
||||
// diAuth.get<DioErrorHandler>().handle(error);
|
||||
}
|
||||
captchaController.getCaptcha();
|
||||
},
|
||||
);*/
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
541
packages/livestock/lib/presentation/page/auth/view.dart
Normal file
541
packages/livestock/lib/presentation/page/auth/view.dart
Normal file
@@ -0,0 +1,541 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_livestock/presentation/widgets/captcha/view.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class AuthPage extends GetView<AuthLogic> {
|
||||
const AuthPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
alignment: Alignment.center,
|
||||
|
||||
children: [
|
||||
Assets.vec.bgAuthSvg.svg(fit: BoxFit.fill),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.r),
|
||||
child: FadeTransition(
|
||||
opacity: controller.textAnimation,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 12,
|
||||
children: [
|
||||
Text(
|
||||
'به سامانه رصدیار خوش آمدید!',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan25Bold.copyWith(color: Colors.white),
|
||||
),
|
||||
Text(
|
||||
'سامانه رصد و پایش زنجیره تامین، تولید و توزیع کالا های اساسی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
final screenHeight = MediaQuery.of(context).size.height;
|
||||
final targetTop = (screenHeight - 676) / 2;
|
||||
|
||||
return AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 1200),
|
||||
curve: Curves.linear,
|
||||
top: controller.showCard.value ? targetTop : screenHeight,
|
||||
left: 10.r,
|
||||
right: 10.r,
|
||||
child: Container(
|
||||
width: 381.w,
|
||||
height: 676.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 50.h),
|
||||
LogoWidget(),
|
||||
SizedBox(height: 20.h),
|
||||
useAndPassFrom(),
|
||||
SizedBox(height: 24.h),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'مطالعه بیانیه ',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.bottomSheet(
|
||||
privacyPolicyWidget(),
|
||||
isScrollControlled: true,
|
||||
enableDrag: true,
|
||||
ignoreSafeArea: false,
|
||||
);
|
||||
},
|
||||
text: 'حریم خصوصی',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget useAndPassFrom() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30.r),
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: AutofillGroup(
|
||||
child: Column(
|
||||
children: [
|
||||
RTextField(
|
||||
label: 'نام کاربری',
|
||||
maxLength: 11,
|
||||
maxLines: 1,
|
||||
controller: controller.usernameController.value,
|
||||
keyboardType: TextInputType.number,
|
||||
initText: controller.usernameController.value.text,
|
||||
autofillHints: [AutofillHints.username],
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: AppColor.textColor, width: 1),
|
||||
),
|
||||
onChanged: (value) async {
|
||||
controller.usernameController.value.text = value;
|
||||
controller.usernameController.refresh();
|
||||
},
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 6, 8),
|
||||
child: Assets.vec.callSvg.svg(width: 12, height: 12),
|
||||
),
|
||||
suffixIcon: controller.usernameController.value.text.trim().isNotEmpty
|
||||
? clearButton(() {
|
||||
controller.usernameController.value.clear();
|
||||
controller.usernameController.refresh();
|
||||
})
|
||||
: null,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '⚠️ شماره موبایل را وارد کنید';
|
||||
} else if (value.length < 10) {
|
||||
return '⚠️ شماره موبایل باید 11 رقم باشد';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(color: AppColor.redNormal),
|
||||
labelStyle: AppFonts.yekan13,
|
||||
boxConstraints: const BoxConstraints(
|
||||
maxHeight: 40,
|
||||
minHeight: 40,
|
||||
maxWidth: 40,
|
||||
minWidth: 40,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 26),
|
||||
ObxValue(
|
||||
(passwordController) => RTextField(
|
||||
label: 'رمز عبور',
|
||||
filled: false,
|
||||
obscure: true,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: AppColor.textColor, width: 1),
|
||||
),
|
||||
controller: passwordController.value,
|
||||
autofillHints: [AutofillHints.password],
|
||||
variant: RTextFieldVariant.password,
|
||||
initText: passwordController.value.text,
|
||||
onChanged: (value) {
|
||||
passwordController.refresh();
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '⚠️ رمز عبور را وارد کنید';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(color: AppColor.redNormal),
|
||||
labelStyle: AppFonts.yekan13,
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
|
||||
child: Assets.vec.keySvg.svg(width: 12, height: 12),
|
||||
),
|
||||
boxConstraints: const BoxConstraints(
|
||||
maxHeight: 34,
|
||||
minHeight: 34,
|
||||
maxWidth: 34,
|
||||
minWidth: 34,
|
||||
),
|
||||
),
|
||||
controller.passwordController,
|
||||
),
|
||||
SizedBox(height: 26),
|
||||
CaptchaWidget(),
|
||||
SizedBox(height: 23),
|
||||
|
||||
Obx(() {
|
||||
return RElevated(
|
||||
text: 'ورود',
|
||||
isLoading: controller.isLoading.value,
|
||||
onPressed: controller.isDisabled.value
|
||||
? null
|
||||
: () async {
|
||||
await controller.submitLoginForm();
|
||||
},
|
||||
width: Get.width,
|
||||
height: 48,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget privacyPolicyWidget() {
|
||||
return BaseBottomSheet(
|
||||
child: Column(
|
||||
spacing: 5,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(8.w),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'بيانيه حريم خصوصی',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'اطلاعات مربوط به هر شخص، حریم خصوصی وی محسوب میشود. حفاظت و حراست از اطلاعات شخصی در سامانه رصد یار، نه تنها موجب حفظ امنیت کاربران میشود، بلکه باعث اعتماد بیشتر و مشارکت آنها در فعالیتهای جاری میگردد. هدف از این بیانیه، آگاه ساختن شما درباره ی نوع و نحوه ی استفاده از اطلاعاتی است که در هنگام استفاده از سامانه رصد یار ، از جانب شما دریافت میگردد. شرکت هوشمند سازان خود را ملزم به رعایت حریم خصوصی همه شهروندان و کاربران سامانه دانسته و آن دسته از اطلاعات کاربران را که فقط به منظور ارائه خدمات کفایت میکند، دریافت کرده و از انتشار آن یا در اختیار قرار دادن آن به دیگران خودداری مینماید.',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark, height: 1.8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(8.w),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'چگونگی جمع آوری و استفاده از اطلاعات کاربران',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'''الف: اطلاعاتی که شما خود در اختيار این سامانه قرار میدهيد، شامل موارد زيرهستند:
|
||||
اقلام اطلاعاتی شامل شماره تلفن همراه، تاریخ تولد، کد پستی و کد ملی کاربران را دریافت مینماییم که از این اقلام، صرفا جهت احراز هویت کاربران استفاده خواهد شد.
|
||||
ب: برخی اطلاعات ديگر که به صورت خودکار از شما دريافت میشود شامل موارد زير میباشد:
|
||||
⦁ دستگاهی که از طریق آن سامانه رصد یار را مشاهده مینمایید( تلفن همراه، تبلت، رایانه).
|
||||
⦁ نام و نسخه سیستم عامل و browser کامپیوتر شما.
|
||||
⦁ اطلاعات صفحات بازدید شده.
|
||||
⦁ تعداد بازدیدهای روزانه در درگاه.
|
||||
⦁ هدف ما از دریافت این اطلاعات استفاده از آنها در تحلیل عملکرد کاربران درگاه می باشد تا بتوانیم در خدمت رسانی بهتر عمل کنیم.
|
||||
''',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark, height: 1.8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(8.w),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'امنیت اطلاعات',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'متعهدیم که امنیت اطلاعات شما را تضمین نماییم و برای جلوگیری از هر نوع دسترسی غیرمجاز و افشای اطلاعات شما از همه شیوههای لازم استفاده میکنیم تا امنیت اطلاعاتی را که به صورت آنلاین گردآوری میکنیم، حفظ شود. لازم به ذکر است در سامانه ما، ممکن است به سایت های دیگری لینک شوید، وقتی که شما از طریق این لینکها از سامانه ما خارج میشوید، توجه داشته باشید که ما بر دیگر سایت ها کنترل نداریم و سازمان تعهدی بر حفظ حریم شخصی آنان در سایت مقصد نخواهد داشت و مراجعه کنندگان میبایست به بیانیه حریم شخصی آن سایت ها مراجعه نمایند.',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark, height: 1.8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
Widget sendCodeForm() {
|
||||
return ObxValue((data) {
|
||||
return Form(
|
||||
key: data.value,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 26),
|
||||
ObxValue((phoneController) {
|
||||
return TextFormField(
|
||||
controller: phoneController.value,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
gapPadding: 11,
|
||||
),
|
||||
labelText: 'شماره موبایل',
|
||||
labelStyle: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.redNormal,
|
||||
),
|
||||
prefixIconConstraints: BoxConstraints(
|
||||
maxHeight: 40,
|
||||
minHeight: 40,
|
||||
maxWidth: 40,
|
||||
minWidth: 40,
|
||||
),
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 6, 8),
|
||||
child: vecWidget(Assets.vecCallSvg),
|
||||
),
|
||||
suffix:
|
||||
phoneController.value.text.trim().isNotEmpty
|
||||
? clearButton(() {
|
||||
phoneController.value.clear();
|
||||
phoneController.refresh();
|
||||
})
|
||||
: null,
|
||||
counterText: '',
|
||||
),
|
||||
keyboardType: TextInputType.numberWithOptions(
|
||||
decimal: false,
|
||||
signed: false,
|
||||
),
|
||||
maxLines: 1,
|
||||
maxLength: 11,
|
||||
onChanged: (value) {
|
||||
if (controller.isOnError.value) {
|
||||
controller.isOnError.value = !controller.isOnError.value;
|
||||
data.value.currentState?.reset();
|
||||
data.refresh();
|
||||
phoneController.value.text = value;
|
||||
}
|
||||
phoneController.refresh();
|
||||
},
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return '⚠️ شماره موبایل را وارد کنید';
|
||||
} else if (value.length < 11) {
|
||||
return '⚠️ شماره موبایل باید 11 رقم باشد';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}, controller.phoneOtpNumberController),
|
||||
|
||||
SizedBox(height: 26),
|
||||
|
||||
CaptchaWidget(),
|
||||
|
||||
SizedBox(height: 23),
|
||||
RElevated(
|
||||
text: 'ارسال رمز یکبار مصرف',
|
||||
onPressed: () {
|
||||
if (data.value.currentState?.validate() == true) {
|
||||
controller.otpStatus.value = OtpStatus.sent;
|
||||
controller.startTimer();
|
||||
}
|
||||
},
|
||||
width: Get.width,
|
||||
height: 48,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}, controller.formKeyOtp);
|
||||
}
|
||||
|
||||
Widget confirmCodeForm() {
|
||||
return ObxValue((data) {
|
||||
return Form(
|
||||
key: data.value,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 26),
|
||||
|
||||
ObxValue((passwordController) {
|
||||
return TextFormField(
|
||||
controller: passwordController.value,
|
||||
obscureText: controller.hidePassword.value,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
gapPadding: 11,
|
||||
),
|
||||
labelText: 'رمز عبور',
|
||||
labelStyle: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.redNormal,
|
||||
),
|
||||
|
||||
prefixIconConstraints: BoxConstraints(
|
||||
maxHeight: 34,
|
||||
minHeight: 34,
|
||||
maxWidth: 34,
|
||||
minWidth: 34,
|
||||
),
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
|
||||
child: vecWidget(Assets.vecKeySvg),
|
||||
),
|
||||
suffix:
|
||||
passwordController.value.text.trim().isNotEmpty
|
||||
? GestureDetector(
|
||||
onTap: () {
|
||||
controller.hidePassword.value =
|
||||
!controller.hidePassword.value;
|
||||
},
|
||||
child: Icon(
|
||||
controller.hidePassword.value
|
||||
? CupertinoIcons.eye
|
||||
: CupertinoIcons.eye_slash,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
counterText: '',
|
||||
),
|
||||
textInputAction: TextInputAction.done,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
maxLines: 1,
|
||||
onChanged: (value) {
|
||||
if (controller.isOnError.value) {
|
||||
controller.isOnError.value = !controller.isOnError.value;
|
||||
data.value.currentState?.reset();
|
||||
passwordController.value.text = value;
|
||||
}
|
||||
passwordController.refresh();
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '⚠️ رمز عبور را وارد کنید'; // "Please enter the password"
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}, controller.passwordController),
|
||||
|
||||
SizedBox(height: 23),
|
||||
|
||||
ObxValue((timer) {
|
||||
if (timer.value == 0) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
controller.otpStatus.value = OtpStatus.reSend;
|
||||
controller.startTimer();
|
||||
},
|
||||
child: Text(
|
||||
style: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
'ارسال مجدد کد یکبار مصرف',
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
'اعتبار رمز ارسال شده ${controller.timeFormatted}',
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}
|
||||
}, controller.secondsRemaining),
|
||||
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: ' کد ارسال شده به شماره ',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.darkGreyDark,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: controller.phoneOtpNumberController.value.text,
|
||||
style: AppFonts.yekan13Bold.copyWith(
|
||||
color: AppColor.darkGreyDark,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
recognizer:
|
||||
TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
controller.otpStatus.value = OtpStatus.init;
|
||||
},
|
||||
text: ' ویرایش',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 23),
|
||||
RElevated(
|
||||
text: 'ورود',
|
||||
onPressed: () {
|
||||
if (controller.formKeyOtp.value.currentState?.validate() ==
|
||||
true) {}
|
||||
},
|
||||
width: Get.width,
|
||||
height: 48,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}, controller.formKeySentOtp);
|
||||
}*/
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
||||
|
||||
class RootLogic extends GetxController {
|
||||
List<Widget> pages = [
|
||||
MapPage(),
|
||||
Navigator(
|
||||
key: Get.nestedKey(0),
|
||||
initialRoute: LiveStockRoutes.requests,
|
||||
@@ -22,7 +23,7 @@ class RootLogic extends GetxController {
|
||||
}
|
||||
},
|
||||
),
|
||||
MapPage(),
|
||||
|
||||
ProfilePage(),
|
||||
];
|
||||
RxInt currentIndex = 1.obs;
|
||||
|
||||
@@ -9,7 +9,6 @@ class RootPage extends GetView<RootLogic> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ObxValue((currentIndex) {
|
||||
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
onPopInvokedWithResult: (didPop, result) {
|
||||
@@ -43,28 +42,39 @@ class RootPage extends GetView<RootLogic> {
|
||||
index: currentIndex.value,
|
||||
sizing: StackFit.expand,
|
||||
),
|
||||
extendBody: true,
|
||||
|
||||
bottomNavigationBar: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
icon: Assets.vec.filterSvg.path,
|
||||
label: 'درخواستها',
|
||||
isSelected: currentIndex.value == 0,
|
||||
onTap: () => controller.changePage(0),
|
||||
),
|
||||
|
||||
RBottomNavigationItem(
|
||||
icon: Assets.vec.mapSvg.path,
|
||||
label: 'نقشه',
|
||||
icon: Assets.vec.mapSvg.path,
|
||||
isSelected: currentIndex.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'درخواستها',
|
||||
icon: Assets.vec.settingSvg.path,
|
||||
isSelected: currentIndex.value == 1,
|
||||
onTap: () => controller.changePage(1),
|
||||
onTap: () {
|
||||
Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
|
||||
RBottomNavigationItem(
|
||||
icon: Assets.vec.profileUserSvg.path,
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: currentIndex.value == 2,
|
||||
onTap: () => controller.changePage(2),
|
||||
onTap: () {
|
||||
Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst);
|
||||
|
||||
controller.changePage(2);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_core/presentation/widget/map/logic.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/auth/logic.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/auth/view.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/map/logic.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/profile/logic.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/request_tagging/logic.dart';
|
||||
@@ -9,6 +11,7 @@ import 'package:rasadyar_livestock/presentation/page/root/logic.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/root/view.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/tagging/logic.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/tagging/view.dart';
|
||||
import 'package:rasadyar_livestock/presentation/widgets/captcha/logic.dart';
|
||||
|
||||
part 'app_routes.dart';
|
||||
|
||||
@@ -16,6 +19,14 @@ sealed class LiveStockPages {
|
||||
LiveStockPages._();
|
||||
|
||||
static final pages = [
|
||||
GetPage(
|
||||
name: LiveStockRoutes.auth,
|
||||
page: () => AuthPage(),
|
||||
binding: BindingsBuilder(() {
|
||||
Get.lazyPut(() => AuthLogic());
|
||||
Get.lazyPut(() => CaptchaWidgetLogic());
|
||||
}),
|
||||
),
|
||||
GetPage(
|
||||
name: LiveStockRoutes.init,
|
||||
page: () => RootPage(),
|
||||
@@ -40,7 +51,6 @@ sealed class LiveStockPages {
|
||||
),*/
|
||||
],
|
||||
),
|
||||
|
||||
GetPage(
|
||||
name: LiveStockRoutes.requestTagging,
|
||||
page: () => RequestTaggingPage(),
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
|
||||
import 'package:rasadyar_livestock/data/repository/auth/auth_repository_imp.dart';
|
||||
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
|
||||
|
||||
class CaptchaWidgetLogic extends GetxController with StateMixin<CaptchaResponseModel> {
|
||||
TextEditingController textController = TextEditingController();
|
||||
RxnString captchaKey = RxnString();
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
AuthRepositoryImp authRepository = diLiveStock.get<AuthRepositoryImp>();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
getCaptcha();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
textController.clear();
|
||||
textController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
Future<void> getCaptcha() async {
|
||||
change(null, status: RxStatus.loading());
|
||||
textController.clear();
|
||||
formKey.currentState?.reset();
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
await safeCall(
|
||||
call: () async => authRepository.captcha(),
|
||||
onSuccess: (result) {
|
||||
if (result == null) {
|
||||
change(null, status: RxStatus.error('Failed to load captcha'));
|
||||
return;
|
||||
}
|
||||
captchaKey.value = result.captchaKey;
|
||||
change(result, status: RxStatus.success());
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
|
||||
change(value, status: RxStatus.success());
|
||||
}
|
||||
}
|
||||
105
packages/livestock/lib/presentation/widgets/captcha/view.dart
Normal file
105
packages/livestock/lib/presentation/widgets/captcha/view.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_livestock/presentation/page/auth/logic.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class CaptchaWidget extends GetView<CaptchaWidgetLogic> {
|
||||
const CaptchaWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: controller.getCaptcha,
|
||||
child: Container(
|
||||
width: 135,
|
||||
height: 50,
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.whiteNormalHover,
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: controller.obx(
|
||||
(state) => Image.memory(base64Decode(state?.captchaImage ?? ''), fit: BoxFit.cover),
|
||||
onLoading: const Center(
|
||||
child: CupertinoActivityIndicator(color: AppColor.blueNormal),
|
||||
),
|
||||
onError: (error) {
|
||||
return Center(
|
||||
child: Text('خطا ', style: AppFonts.yekan13.copyWith(color: Colors.red)),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
autovalidateMode: AutovalidateMode.disabled,
|
||||
child: RTextField(
|
||||
label: 'کد امنیتی',
|
||||
controller: controller.textController,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: AppColor.textColor, width: 1),
|
||||
),
|
||||
keyboardType: TextInputType.numberWithOptions(decimal: false, signed: false),
|
||||
maxLines: 1,
|
||||
maxLength: 6,
|
||||
suffixIcon: (controller.textController.text.trim().isNotEmpty ?? false)
|
||||
? clearButton(() => controller.textController.clear())
|
||||
: null,
|
||||
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'کد امنیتی را وارد کنید';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (pass) {
|
||||
if (pass.length == 6) {
|
||||
if (controller.formKey.currentState?.validate() ?? false) {
|
||||
Get.find<AuthLogic>().isDisabled.value = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CaptchaLinePainter extends CustomPainter {
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final random = Random();
|
||||
final paint1 = Paint()
|
||||
..color = Colors.deepOrange
|
||||
..strokeWidth = 2;
|
||||
final paint2 = Paint()
|
||||
..color = Colors.blue
|
||||
..strokeWidth = 2;
|
||||
|
||||
// First line: top-left to bottom-right
|
||||
canvas.drawLine(Offset(0, 0), Offset(size.width, size.height), paint1);
|
||||
|
||||
// Second line: bottom-left to top-right
|
||||
canvas.drawLine(Offset(0, size.height), Offset(size.width, 0), paint2);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
name: rasadyar_livestock
|
||||
description: A starting point for Dart libraries or applications.
|
||||
version: 1.0.0
|
||||
version: 2.0.0
|
||||
publish_to: 'none'
|
||||
# repository: https://github.com/my_org/my_repo
|
||||
|
||||
|
||||
@@ -1272,7 +1272,7 @@ packages:
|
||||
path: "packages/livestock"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0"
|
||||
version: "2.0.0"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
Reference in New Issue
Block a user