From d9724f681cb19b4074c5d46f4744d7c3250256ce Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Mon, 28 Jul 2025 15:57:30 +0330 Subject: [PATCH] feat : profile and map --- assets/icons/bg_auth.svg | 57 ++ assets/icons/chicken_marker_location.svg | 116 +++ lib/infrastructure/di/di.dart | 6 - .../service/app_navigation_observer.dart | 10 +- lib/main.dart | 1 + lib/presentation/pages/modules/logic.dart | 14 +- lib/presentation/pages/modules/view.dart | 3 + lib/presentation/pages/splash/logic.dart | 2 +- .../login_request/login_request_model.dart | 0 .../login_request_model.freezed.dart | 0 .../login_request/login_request_model.g.dart | 8 +- .../response/auth/auth_response_model.dart | 0 .../auth/auth_response_model.freezed.dart | 0 .../response/auth/auth_response_model.g.dart | 4 +- .../captcha/captcha_response_model.dart | 0 .../captcha_response_model.freezed.dart | 0 .../captcha/captcha_response_model.g.dart | 16 +- .../response/user_info/user_info_model.dart | 0 .../user_info/user_info_model.freezed.dart | 0 .../response/user_info/user_info_model.g.dart | 8 +- .../user_profile_model.dart | 0 .../user_profile_model.freezed.dart | 0 .../user_profile_model.g.dart | 24 +- packages/core/build.yaml | 6 + packages/core/lib/data/model/model.dart | 3 +- .../data/services/token_storage_service.dart | 7 +- .../lib/presentation/common/assets.gen.dart | 8 + packages/inspection/build.yaml | 6 + .../data_source/remote/auth/auth_remote.dart | 14 + .../remote/auth/auth_remote_imp.dart} | 32 +- .../remote/inspection/inspection_remote.dart | 22 + .../inspection/inspection_remote_imp.dart | 42 + .../remote/user/user_data_source.dart | 8 + .../remote/user/user_data_source_imp.dart | 25 + .../login_request/login_request_model.dart | 34 + .../login_request_model.freezed.dart | 286 +++++++ .../login_request/login_request_model.g.dart | 23 + .../response/auth/auth_response_model.dart | 20 + .../auth/auth_response_model.freezed.dart | 283 +++++++ .../response/auth/auth_response_model.g.dart | 21 + .../captcha/captcha_response_model.dart | 17 + .../captcha_response_model.freezed.dart | 286 +++++++ .../captcha/captcha_response_model.g.dart | 25 + .../poultry_location_model.dart | 68 ++ .../user_profile/user_profile_model.dart | 73 ++ .../repositories/auth/auth_repository.dart | 17 + .../auth/auth_repository_imp.dart | 37 + .../data/repositories/auth_repository.dart | 18 - .../inspection/inspection_repository.dart | 24 + .../inspection/inspection_repository_imp.dart | 34 + .../repositories/user/user_repository.dart | 19 + .../user/user_repository_imp.dart | 28 + .../data/utils/dio_exception_handeler.dart | 58 ++ .../lib/injection/inspection_di.dart | 71 ++ .../lib/presentation/pages/auth/logic.dart | 25 +- .../lib/presentation/pages/auth/view.dart | 2 +- .../pages/inspection_map/logic.dart | 159 ++-- .../pages/inspection_map/view.dart | 3 +- .../lib/presentation/pages/profile/logic.dart | 51 +- .../lib/presentation/pages/profile/view.dart | 717 +++++++++++++----- .../lib/presentation/pages/root/logic.dart | 77 +- .../lib/presentation/pages/root/view.dart | 76 +- .../lib/presentation/routes/app_pages.dart | 6 +- .../presentation/widget/captcha/logic.dart | 27 +- .../lib/presentation/widget/captcha/view.dart | 11 +- packages/inspection/pubspec.lock | 223 +++++- packages/inspection/pubspec.yaml | 18 + 67 files changed, 2835 insertions(+), 444 deletions(-) create mode 100644 assets/icons/bg_auth.svg create mode 100644 assets/icons/chicken_marker_location.svg rename packages/{core/lib/data/model => chicken/lib/data/models}/request/login_request/login_request_model.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/request/login_request/login_request_model.freezed.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/request/login_request/login_request_model.g.dart (77%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/auth/auth_response_model.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/auth/auth_response_model.freezed.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/auth/auth_response_model.g.dart (88%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/captcha/captcha_response_model.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/captcha/captcha_response_model.freezed.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/captcha/captcha_response_model.g.dart (59%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/user_info/user_info_model.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/user_info/user_info_model.freezed.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/user_info/user_info_model.g.dart (80%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/user_profile_model/user_profile_model.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/user_profile_model/user_profile_model.freezed.dart (100%) rename packages/{core/lib/data/model => chicken/lib/data/models}/response/user_profile_model/user_profile_model.g.dart (69%) create mode 100644 packages/core/build.yaml create mode 100644 packages/inspection/build.yaml create mode 100644 packages/inspection/lib/data/data_source/remote/auth/auth_remote.dart rename packages/inspection/lib/data/{repositories/auth_repository_imp.dart => data_source/remote/auth/auth_remote_imp.dart} (65%) create mode 100644 packages/inspection/lib/data/data_source/remote/inspection/inspection_remote.dart create mode 100644 packages/inspection/lib/data/data_source/remote/inspection/inspection_remote_imp.dart create mode 100644 packages/inspection/lib/data/data_source/remote/user/user_data_source.dart create mode 100644 packages/inspection/lib/data/data_source/remote/user/user_data_source_imp.dart create mode 100644 packages/inspection/lib/data/model/request/login_request/login_request_model.dart create mode 100644 packages/inspection/lib/data/model/request/login_request/login_request_model.freezed.dart create mode 100644 packages/inspection/lib/data/model/request/login_request/login_request_model.g.dart create mode 100644 packages/inspection/lib/data/model/response/auth/auth_response_model.dart create mode 100644 packages/inspection/lib/data/model/response/auth/auth_response_model.freezed.dart create mode 100644 packages/inspection/lib/data/model/response/auth/auth_response_model.g.dart create mode 100644 packages/inspection/lib/data/model/response/captcha/captcha_response_model.dart create mode 100644 packages/inspection/lib/data/model/response/captcha/captcha_response_model.freezed.dart create mode 100644 packages/inspection/lib/data/model/response/captcha/captcha_response_model.g.dart create mode 100644 packages/inspection/lib/data/model/response/poultry_location/poultry_location_model.dart create mode 100644 packages/inspection/lib/data/model/response/user_profile/user_profile_model.dart create mode 100644 packages/inspection/lib/data/repositories/auth/auth_repository.dart create mode 100644 packages/inspection/lib/data/repositories/auth/auth_repository_imp.dart delete mode 100644 packages/inspection/lib/data/repositories/auth_repository.dart create mode 100644 packages/inspection/lib/data/repositories/inspection/inspection_repository.dart create mode 100644 packages/inspection/lib/data/repositories/inspection/inspection_repository_imp.dart create mode 100644 packages/inspection/lib/data/repositories/user/user_repository.dart create mode 100644 packages/inspection/lib/data/repositories/user/user_repository_imp.dart create mode 100644 packages/inspection/lib/data/utils/dio_exception_handeler.dart create mode 100644 packages/inspection/lib/injection/inspection_di.dart diff --git a/assets/icons/bg_auth.svg b/assets/icons/bg_auth.svg new file mode 100644 index 0000000..3863899 --- /dev/null +++ b/assets/icons/bg_auth.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chicken_marker_location.svg b/assets/icons/chicken_marker_location.svg new file mode 100644 index 0000000..6d79658 --- /dev/null +++ b/assets/icons/chicken_marker_location.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/infrastructure/di/di.dart b/lib/infrastructure/di/di.dart index fdf6b7a..9a5a287 100644 --- a/lib/infrastructure/di/di.dart +++ b/lib/infrastructure/di/di.dart @@ -1,5 +1,3 @@ - -import 'package:rasadyar_chicken/data/di/chicken_di.dart'; import 'package:rasadyar_core/core.dart'; final di = GetIt.instance; @@ -7,7 +5,3 @@ final di = GetIt.instance; Future setupPreInjection() async { await setupAllCoreProvider(); } - -Future setupInjection() async { - await setupChickenDI(); -} diff --git a/lib/infrastructure/service/app_navigation_observer.dart b/lib/infrastructure/service/app_navigation_observer.dart index 9ad7b38..3cebc64 100644 --- a/lib/infrastructure/service/app_navigation_observer.dart +++ b/lib/infrastructure/service/app_navigation_observer.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:rasadyar_app/infrastructure/di/di.dart'; import 'package:rasadyar_chicken/chicken.dart'; +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'; class CustomNavigationObserver extends NavigatorObserver { bool _isWorkDone = false; @@ -16,7 +18,11 @@ class CustomNavigationObserver extends NavigatorObserver { final routeName = route.settings.name; if (!_isWorkDone && routeName == ChickenRoutes.init) { _isWorkDone = true; - await setupInjection(); + setupChickenDI(); + } else if (!_isWorkDone && (routeName == InspectionRoutes.init || routeName == InspectionRoutes.auth)) { + _isWorkDone = true; + + await setupInspectionDI(); } tLog('CustomNavigationObserver: didPush - $routeName'); } diff --git a/lib/main.dart b/lib/main.dart index ec1cee0..09db360 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,6 +14,7 @@ Future main() async { await Get.find().init(); Get.put(AppAuthRouteResolver()); Get.put(AuthMiddleware()); + runApp(MyApp()); // runApp(DevicePreview(builder: (context) => ForDevicePreview(),)); diff --git a/lib/presentation/pages/modules/logic.dart b/lib/presentation/pages/modules/logic.dart index 628b7a8..d35b096 100644 --- a/lib/presentation/pages/modules/logic.dart +++ b/lib/presentation/pages/modules/logic.dart @@ -1,28 +1,28 @@ - import 'package:rasadyar_core/core.dart'; class ModulesLogic extends GetxController { + TokenStorageService tokenService = Get.find(); - List moduleList=[ + List 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.chicken), ]; - RxnInt selectedIndex = RxnInt(null); - @override void onReady() { super.onReady(); } - - - @override void onClose() { super.onClose(); } + + void saveModule(Module module) { + tokenService.saveModule(module); + tokenService.appModule.value = module; + } } diff --git a/lib/presentation/pages/modules/view.dart b/lib/presentation/pages/modules/view.dart index 464b741..b1d1bbf 100644 --- a/lib/presentation/pages/modules/view.dart +++ b/lib/presentation/pages/modules/view.dart @@ -25,6 +25,9 @@ class ModulesPage extends GetView { icon: module.icon, onTap: () { controller.selectedIndex.value = index; + controller.saveModule(module.module); + + // Navigate to the appropriate route based on the selected module switch (module.module) { case Module.inspection: Get.toNamed(InspectionRoutes.init); diff --git a/lib/presentation/pages/splash/logic.dart b/lib/presentation/pages/splash/logic.dart index 1b62220..a9f1a8d 100644 --- a/lib/presentation/pages/splash/logic.dart +++ b/lib/presentation/pages/splash/logic.dart @@ -152,7 +152,7 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin { try { final isUpdateNeeded = await checkVersion(); if (isUpdateNeeded) return; - + tokenService.getModule(); final module = tokenService.appModule.value; final target = getTargetPage(module); Get.offAndToNamed(target); diff --git a/packages/core/lib/data/model/request/login_request/login_request_model.dart b/packages/chicken/lib/data/models/request/login_request/login_request_model.dart similarity index 100% rename from packages/core/lib/data/model/request/login_request/login_request_model.dart rename to packages/chicken/lib/data/models/request/login_request/login_request_model.dart diff --git a/packages/core/lib/data/model/request/login_request/login_request_model.freezed.dart b/packages/chicken/lib/data/models/request/login_request/login_request_model.freezed.dart similarity index 100% rename from packages/core/lib/data/model/request/login_request/login_request_model.freezed.dart rename to packages/chicken/lib/data/models/request/login_request/login_request_model.freezed.dart diff --git a/packages/core/lib/data/model/request/login_request/login_request_model.g.dart b/packages/chicken/lib/data/models/request/login_request/login_request_model.g.dart similarity index 77% rename from packages/core/lib/data/model/request/login_request/login_request_model.g.dart rename to packages/chicken/lib/data/models/request/login_request/login_request_model.g.dart index f10c8a6..4504142 100644 --- a/packages/core/lib/data/model/request/login_request/login_request_model.g.dart +++ b/packages/chicken/lib/data/models/request/login_request/login_request_model.g.dart @@ -10,14 +10,14 @@ _LoginRequestModel _$LoginRequestModelFromJson(Map json) => _LoginRequestModel( username: json['username'] as String?, password: json['password'] as String?, - captchaCode: json['captchaCode'] as String?, - captchaKey: json['captchaKey'] as String?, + captchaCode: json['captcha_code'] as String?, + captchaKey: json['captcha_key'] as String?, ); Map _$LoginRequestModelToJson(_LoginRequestModel instance) => { 'username': instance.username, 'password': instance.password, - 'captchaCode': instance.captchaCode, - 'captchaKey': instance.captchaKey, + 'captcha_code': instance.captchaCode, + 'captcha_key': instance.captchaKey, }; diff --git a/packages/core/lib/data/model/response/auth/auth_response_model.dart b/packages/chicken/lib/data/models/response/auth/auth_response_model.dart similarity index 100% rename from packages/core/lib/data/model/response/auth/auth_response_model.dart rename to packages/chicken/lib/data/models/response/auth/auth_response_model.dart diff --git a/packages/core/lib/data/model/response/auth/auth_response_model.freezed.dart b/packages/chicken/lib/data/models/response/auth/auth_response_model.freezed.dart similarity index 100% rename from packages/core/lib/data/model/response/auth/auth_response_model.freezed.dart rename to packages/chicken/lib/data/models/response/auth/auth_response_model.freezed.dart diff --git a/packages/core/lib/data/model/response/auth/auth_response_model.g.dart b/packages/chicken/lib/data/models/response/auth/auth_response_model.g.dart similarity index 88% rename from packages/core/lib/data/model/response/auth/auth_response_model.g.dart rename to packages/chicken/lib/data/models/response/auth/auth_response_model.g.dart index 642fa02..dc5d66d 100644 --- a/packages/core/lib/data/model/response/auth/auth_response_model.g.dart +++ b/packages/chicken/lib/data/models/response/auth/auth_response_model.g.dart @@ -10,12 +10,12 @@ _AuthResponseModel _$AuthResponseModelFromJson(Map json) => _AuthResponseModel( refresh: json['refresh'] as String?, access: json['access'] as String?, - otpStatus: json['otpStatus'] as bool?, + otpStatus: json['otp_status'] as bool?, ); Map _$AuthResponseModelToJson(_AuthResponseModel instance) => { 'refresh': instance.refresh, 'access': instance.access, - 'otpStatus': instance.otpStatus, + 'otp_status': instance.otpStatus, }; diff --git a/packages/core/lib/data/model/response/captcha/captcha_response_model.dart b/packages/chicken/lib/data/models/response/captcha/captcha_response_model.dart similarity index 100% rename from packages/core/lib/data/model/response/captcha/captcha_response_model.dart rename to packages/chicken/lib/data/models/response/captcha/captcha_response_model.dart diff --git a/packages/core/lib/data/model/response/captcha/captcha_response_model.freezed.dart b/packages/chicken/lib/data/models/response/captcha/captcha_response_model.freezed.dart similarity index 100% rename from packages/core/lib/data/model/response/captcha/captcha_response_model.freezed.dart rename to packages/chicken/lib/data/models/response/captcha/captcha_response_model.freezed.dart diff --git a/packages/core/lib/data/model/response/captcha/captcha_response_model.g.dart b/packages/chicken/lib/data/models/response/captcha/captcha_response_model.g.dart similarity index 59% rename from packages/core/lib/data/model/response/captcha/captcha_response_model.g.dart rename to packages/chicken/lib/data/models/response/captcha/captcha_response_model.g.dart index a0ffdcb..8d69248 100644 --- a/packages/core/lib/data/model/response/captcha/captcha_response_model.g.dart +++ b/packages/chicken/lib/data/models/response/captcha/captcha_response_model.g.dart @@ -9,17 +9,17 @@ part of 'captcha_response_model.dart'; _CaptchaResponseModel _$CaptchaResponseModelFromJson( Map json, ) => _CaptchaResponseModel( - captchaKey: json['captchaKey'] as String?, - captchaImage: json['captchaImage'] as String?, - imageType: json['imageType'] as String?, - imageDecode: json['imageDecode'] as String?, + 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 _$CaptchaResponseModelToJson( _CaptchaResponseModel instance, ) => { - 'captchaKey': instance.captchaKey, - 'captchaImage': instance.captchaImage, - 'imageType': instance.imageType, - 'imageDecode': instance.imageDecode, + 'captcha_key': instance.captchaKey, + 'captcha_image': instance.captchaImage, + 'image_type': instance.imageType, + 'image_decode': instance.imageDecode, }; diff --git a/packages/core/lib/data/model/response/user_info/user_info_model.dart b/packages/chicken/lib/data/models/response/user_info/user_info_model.dart similarity index 100% rename from packages/core/lib/data/model/response/user_info/user_info_model.dart rename to packages/chicken/lib/data/models/response/user_info/user_info_model.dart diff --git a/packages/core/lib/data/model/response/user_info/user_info_model.freezed.dart b/packages/chicken/lib/data/models/response/user_info/user_info_model.freezed.dart similarity index 100% rename from packages/core/lib/data/model/response/user_info/user_info_model.freezed.dart rename to packages/chicken/lib/data/models/response/user_info/user_info_model.freezed.dart diff --git a/packages/core/lib/data/model/response/user_info/user_info_model.g.dart b/packages/chicken/lib/data/models/response/user_info/user_info_model.g.dart similarity index 80% rename from packages/core/lib/data/model/response/user_info/user_info_model.g.dart rename to packages/chicken/lib/data/models/response/user_info/user_info_model.g.dart index 13ceb8e..2c8f1c4 100644 --- a/packages/core/lib/data/model/response/user_info/user_info_model.g.dart +++ b/packages/chicken/lib/data/models/response/user_info/user_info_model.g.dart @@ -8,16 +8,16 @@ part of 'user_info_model.dart'; _UserInfoModel _$UserInfoModelFromJson(Map json) => _UserInfoModel( - isUser: json['isUser'] as bool?, + isUser: json['is_user'] as bool?, address: json['address'] as String?, backend: json['backend'] as String?, - apiKey: json['apiKey'] as String?, + apiKey: json['api_key'] as String?, ); Map _$UserInfoModelToJson(_UserInfoModel instance) => { - 'isUser': instance.isUser, + 'is_user': instance.isUser, 'address': instance.address, 'backend': instance.backend, - 'apiKey': instance.apiKey, + 'api_key': instance.apiKey, }; diff --git a/packages/core/lib/data/model/response/user_profile_model/user_profile_model.dart b/packages/chicken/lib/data/models/response/user_profile_model/user_profile_model.dart similarity index 100% rename from packages/core/lib/data/model/response/user_profile_model/user_profile_model.dart rename to packages/chicken/lib/data/models/response/user_profile_model/user_profile_model.dart diff --git a/packages/core/lib/data/model/response/user_profile_model/user_profile_model.freezed.dart b/packages/chicken/lib/data/models/response/user_profile_model/user_profile_model.freezed.dart similarity index 100% rename from packages/core/lib/data/model/response/user_profile_model/user_profile_model.freezed.dart rename to packages/chicken/lib/data/models/response/user_profile_model/user_profile_model.freezed.dart diff --git a/packages/core/lib/data/model/response/user_profile_model/user_profile_model.g.dart b/packages/chicken/lib/data/models/response/user_profile_model/user_profile_model.g.dart similarity index 69% rename from packages/core/lib/data/model/response/user_profile_model/user_profile_model.g.dart rename to packages/chicken/lib/data/models/response/user_profile_model/user_profile_model.g.dart index 170f03f..df72e0e 100644 --- a/packages/core/lib/data/model/response/user_profile_model/user_profile_model.g.dart +++ b/packages/chicken/lib/data/models/response/user_profile_model/user_profile_model.g.dart @@ -8,40 +8,40 @@ part of 'user_profile_model.dart'; _UserProfileModel _$UserProfileModelFromJson(Map json) => _UserProfileModel( - accessToken: json['accessToken'] as String?, - expiresIn: json['expiresIn'] as String?, + accessToken: json['access_token'] as String?, + expiresIn: json['expires_in'] as String?, scope: json['scope'] as String?, - expireTime: json['expireTime'] as String?, + expireTime: json['expire_time'] as String?, mobile: json['mobile'] as String?, fullname: json['fullname'] as String?, firstname: json['firstname'] as String?, lastname: json['lastname'] as String?, city: json['city'] as String?, province: json['province'] as String?, - nationalCode: json['nationalCode'] as String?, - nationalId: json['nationalId'] as String?, + nationalCode: json['national_code'] as String?, + nationalId: json['national_id'] as String?, birthday: json['birthday'] as String?, image: json['image'] as String?, - baseOrder: (json['baseOrder'] as num?)?.toInt(), + baseOrder: (json['base_order'] as num?)?.toInt(), role: (json['role'] as List?)?.map((e) => e as String).toList(), ); Map _$UserProfileModelToJson(_UserProfileModel instance) => { - 'accessToken': instance.accessToken, - 'expiresIn': instance.expiresIn, + 'access_token': instance.accessToken, + 'expires_in': instance.expiresIn, 'scope': instance.scope, - 'expireTime': instance.expireTime, + 'expire_time': instance.expireTime, 'mobile': instance.mobile, 'fullname': instance.fullname, 'firstname': instance.firstname, 'lastname': instance.lastname, 'city': instance.city, 'province': instance.province, - 'nationalCode': instance.nationalCode, - 'nationalId': instance.nationalId, + 'national_code': instance.nationalCode, + 'national_id': instance.nationalId, 'birthday': instance.birthday, 'image': instance.image, - 'baseOrder': instance.baseOrder, + 'base_order': instance.baseOrder, 'role': instance.role, }; diff --git a/packages/core/build.yaml b/packages/core/build.yaml new file mode 100644 index 0000000..840029b --- /dev/null +++ b/packages/core/build.yaml @@ -0,0 +1,6 @@ +targets: + $default: + builders: + json_serializable: + options: + field_rename: snake \ No newline at end of file diff --git a/packages/core/lib/data/model/model.dart b/packages/core/lib/data/model/model.dart index 4a8a622..6d07ea5 100644 --- a/packages/core/lib/data/model/model.dart +++ b/packages/core/lib/data/model/model.dart @@ -1,3 +1,4 @@ + +export 'pagination_model/pagination_model.dart'; export 'local/module/module_model.dart'; export 'local/user_local/user_local_model.dart'; -export 'pagination_model/pagination_model.dart'; diff --git a/packages/core/lib/data/services/token_storage_service.dart b/packages/core/lib/data/services/token_storage_service.dart index c62c2ba..ab551c9 100644 --- a/packages/core/lib/data/services/token_storage_service.dart +++ b/packages/core/lib/data/services/token_storage_service.dart @@ -1,4 +1,5 @@ import 'dart:convert'; + import 'package:rasadyar_core/core.dart'; import 'package:rasadyar_core/hive_registrar.g.dart'; @@ -38,7 +39,7 @@ class TokenStorageService extends GetxService { accessToken.value = _localStorage.read(boxName: _tokenBoxName, key: _accessTokenKey); refreshToken.value = _localStorage.read(boxName: _tokenBoxName, key: _refreshTokenKey); - appModule.value = _localStorage.read(boxName: _appBoxName, key: _moduleKey); + appModule.value = getModule(); baseurl.value = _localStorage.read(boxName: _appBoxName, key: _baseUrlKey); } @@ -60,6 +61,10 @@ class TokenStorageService extends GetxService { appModule.refresh(); } + Module? getModule() { + return _localStorage.read(boxName: _tokenBoxName, key: _moduleKey); + } + Future deleteTokens() async { await _localStorage.clear(_tokenBoxName); accessToken.value = null; diff --git a/packages/core/lib/presentation/common/assets.gen.dart b/packages/core/lib/presentation/common/assets.gen.dart index aa17d8b..dba8dfe 100644 --- a/packages/core/lib/presentation/common/assets.gen.dart +++ b/packages/core/lib/presentation/common/assets.gen.dart @@ -46,6 +46,9 @@ class $AssetsIconsGen { /// File path: assets/icons/arrow_right.svg SvgGenImage get arrowRight => const SvgGenImage('assets/icons/arrow_right.svg'); + /// File path: assets/icons/bg_auth.svg + SvgGenImage get bgAuth => const SvgGenImage('assets/icons/bg_auth.svg'); + /// File path: assets/icons/bg_header_user_profile.svg SvgGenImage get bgHeaderUserProfile => const SvgGenImage('assets/icons/bg_header_user_profile.svg'); @@ -278,6 +281,7 @@ class $AssetsIconsGen { appBarInspection, arrowLeft, arrowRight, + bgAuth, bgHeaderUserProfile, buy, calendar, @@ -403,6 +407,9 @@ class $AssetsVecGen { /// File path: assets/vec/arrow_right.svg.vec SvgGenImage get arrowRightSvg => const SvgGenImage.vec('assets/vec/arrow_right.svg.vec'); + /// File path: assets/vec/bg_auth.svg.vec + SvgGenImage get bgAuthSvg => const SvgGenImage.vec('assets/vec/bg_auth.svg.vec'); + /// File path: assets/vec/bg_header_user_profile.svg.vec SvgGenImage get bgHeaderUserProfileSvg => const SvgGenImage.vec('assets/vec/bg_header_user_profile.svg.vec'); @@ -635,6 +642,7 @@ class $AssetsVecGen { appBarInspectionSvg, arrowLeftSvg, arrowRightSvg, + bgAuthSvg, bgHeaderUserProfileSvg, buySvg, calendarSvg, diff --git a/packages/inspection/build.yaml b/packages/inspection/build.yaml new file mode 100644 index 0000000..840029b --- /dev/null +++ b/packages/inspection/build.yaml @@ -0,0 +1,6 @@ +targets: + $default: + builders: + json_serializable: + options: + field_rename: snake \ No newline at end of file diff --git a/packages/inspection/lib/data/data_source/remote/auth/auth_remote.dart b/packages/inspection/lib/data/data_source/remote/auth/auth_remote.dart new file mode 100644 index 0000000..eacaeeb --- /dev/null +++ b/packages/inspection/lib/data/data_source/remote/auth/auth_remote.dart @@ -0,0 +1,14 @@ +import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart'; +import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart'; + +abstract class AuthRemote { + Future login({required Map authRequest}); + + Future captcha(); + + Future logout(); + + Future hasAuthenticated(); + + Future loginWithRefreshToken({required Map authRequest}); +} diff --git a/packages/inspection/lib/data/repositories/auth_repository_imp.dart b/packages/inspection/lib/data/data_source/remote/auth/auth_remote_imp.dart similarity index 65% rename from packages/inspection/lib/data/repositories/auth_repository_imp.dart rename to packages/inspection/lib/data/data_source/remote/auth/auth_remote_imp.dart index 25a3ff6..ff1b37e 100644 --- a/packages/inspection/lib/data/repositories/auth_repository_imp.dart +++ b/packages/inspection/lib/data/data_source/remote/auth/auth_remote_imp.dart @@ -1,22 +1,22 @@ import 'package:rasadyar_core/core.dart'; -import 'package:rasadyar_core/data/model/response/auth/auth_response_model.dart'; -import 'package:rasadyar_core/data/model/response/captcha/captcha_response_model.dart'; -import 'package:rasadyar_core/data/model/response/user_info/user_info_model.dart'; -import 'package:rasadyar_core/data/model/response/user_profile_model/user_profile_model.dart'; -import 'auth_repository.dart'; +import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart'; +import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart'; +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; -class AuthRepositoryImpl implements AuthRepository { +import 'auth_remote.dart'; + +class AuthRemoteImp extends AuthRemote { final DioRemote _httpClient; final String _BASE_URL = 'auth/api/v1/'; - AuthRepositoryImpl(this._httpClient); + AuthRemoteImp(this._httpClient); @override - Future login({required Map authRequest}) async { - var res = await _httpClient.post( - '/api/login/', + Future login({required Map authRequest}) async { + var res = await _httpClient.post( + '${_BASE_URL}login/', data: authRequest, - fromJson: UserProfileModel.fromJson, + fromJson: AuthResponseModel.fromJson, headers: {'Content-Type': 'application/json'}, ); return res.data; @@ -59,14 +59,14 @@ class AuthRepositoryImpl implements AuthRepository { return response.data ?? false; } - @override - Future getUserInfo(String phoneNumber) async { - var res = await _httpClient.post( +/* @override + Future getUserInfo(String phoneNumber) async { + var res = await _httpClient.post( 'https://userbackend.rasadyaar.ir/api/send_otp/', data: {"mobile": phoneNumber, "state": ""}, - fromJson: UserInfoModel.fromJson, + fromJson: UserProfileModel.fromJson, headers: {'Content-Type': 'application/json'}, ); return res.data; - } + }*/ } diff --git a/packages/inspection/lib/data/data_source/remote/inspection/inspection_remote.dart b/packages/inspection/lib/data/data_source/remote/inspection/inspection_remote.dart new file mode 100644 index 0000000..4641e70 --- /dev/null +++ b/packages/inspection/lib/data/data_source/remote/inspection/inspection_remote.dart @@ -0,0 +1,22 @@ +import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart'; + +abstract class InspectionRemoteDataSource { + /// Fetches the inspection data for a given [inspectionId]. + /// + /// Returns a `Future` that resolves to a `Map` containing + /// the inspection data. + Future> fetchInspectionData(String inspectionId); + + /// Fetches the list of inspections for a given [userId]. + /// + /// Returns a `Future` that resolves to a `List>` + /// containing the list of inspections. + Future>> fetchInspections(String userId); + + + Future?> getNearbyLocation({ + double? centerLat, + double? centerLng, + double? radius, + }); +} diff --git a/packages/inspection/lib/data/data_source/remote/inspection/inspection_remote_imp.dart b/packages/inspection/lib/data/data_source/remote/inspection/inspection_remote_imp.dart new file mode 100644 index 0000000..6309fa6 --- /dev/null +++ b/packages/inspection/lib/data/data_source/remote/inspection/inspection_remote_imp.dart @@ -0,0 +1,42 @@ +import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/data/data_source/remote/inspection/inspection_remote.dart'; +import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart'; + +class InspectionRemoteDataSourceImp implements InspectionRemoteDataSource { + final DioRemote _httpClient; + final String _BASE_URL = 'auth/api/v1/'; + + InspectionRemoteDataSourceImp(this._httpClient); + + @override + Future> fetchInspectionData(String inspectionId) { + // TODO: implement fetchInspectionData + throw UnimplementedError(); + } + + @override + Future>> fetchInspections(String userId) { + // TODO: implement fetchInspections + throw UnimplementedError(); + } + + @override + Future?> getNearbyLocation({ + double? centerLat, + double? centerLng, + double? radius, + }) async { + DioRemote dioRemote = DioRemote(baseUrl: 'https://habackend.rasadyaar.ir/'); + await dioRemote.init(); + + var res = await dioRemote.get>( + 'poultry-loc/', + queryParameters: {'center_lat': centerLat, 'center_lng': centerLng, 'radius': radius}, + headers: {'Content-Type': 'application/json'}, + fromJsonList: (json) => + json.map((item) => PoultryLocationModel.fromJson(item as Map)).toList(), + ); + + return res.data; + } +} diff --git a/packages/inspection/lib/data/data_source/remote/user/user_data_source.dart b/packages/inspection/lib/data/data_source/remote/user/user_data_source.dart new file mode 100644 index 0000000..7d013a7 --- /dev/null +++ b/packages/inspection/lib/data/data_source/remote/user/user_data_source.dart @@ -0,0 +1,8 @@ + +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; + +abstract class UserRemoteDataSource { + + Future getProfile({required String token}); + +} \ No newline at end of file diff --git a/packages/inspection/lib/data/data_source/remote/user/user_data_source_imp.dart b/packages/inspection/lib/data/data_source/remote/user/user_data_source_imp.dart new file mode 100644 index 0000000..da0a32f --- /dev/null +++ b/packages/inspection/lib/data/data_source/remote/user/user_data_source_imp.dart @@ -0,0 +1,25 @@ +import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/data/data_source/remote/user/user_data_source.dart'; +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; + +class UserRemoteDataSourceImp extends UserRemoteDataSource { + final DioRemote _httpClient; + final String _BASE_URL = 'auth/api/v1/'; + + UserRemoteDataSourceImp(this._httpClient); + + @override + Future getProfile({required String token}) async { + var res = await _httpClient.get( + '${_BASE_URL}user/profile/', + fromJson: UserProfileModel.fromJson, + headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer $token'}, + ); + + if (res.data == null) { + throw Exception('Failed to load user profile'); + } + + return res.data!; + } +} diff --git a/packages/inspection/lib/data/model/request/login_request/login_request_model.dart b/packages/inspection/lib/data/model/request/login_request/login_request_model.dart new file mode 100644 index 0000000..0e76bc2 --- /dev/null +++ b/packages/inspection/lib/data/model/request/login_request/login_request_model.dart @@ -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 json) => + _$LoginRequestModelFromJson(json); + + const LoginRequestModel._(); + +} diff --git a/packages/inspection/lib/data/model/request/login_request/login_request_model.freezed.dart b/packages/inspection/lib/data/model/request/login_request/login_request_model.freezed.dart new file mode 100644 index 0000000..9b91ad6 --- /dev/null +++ b/packages/inspection/lib/data/model/request/login_request/login_request_model.freezed.dart @@ -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 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 get copyWith => _$LoginRequestModelCopyWithImpl(this as LoginRequestModel, _$identity); + + /// Serializes this LoginRequestModel to a JSON map. + Map 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 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 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? 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 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 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? 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 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 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 diff --git a/packages/inspection/lib/data/model/request/login_request/login_request_model.g.dart b/packages/inspection/lib/data/model/request/login_request/login_request_model.g.dart new file mode 100644 index 0000000..4504142 --- /dev/null +++ b/packages/inspection/lib/data/model/request/login_request/login_request_model.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'login_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LoginRequestModel _$LoginRequestModelFromJson(Map 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 _$LoginRequestModelToJson(_LoginRequestModel instance) => + { + 'username': instance.username, + 'password': instance.password, + 'captcha_code': instance.captchaCode, + 'captcha_key': instance.captchaKey, + }; diff --git a/packages/inspection/lib/data/model/response/auth/auth_response_model.dart b/packages/inspection/lib/data/model/response/auth/auth_response_model.dart new file mode 100644 index 0000000..1f5faba --- /dev/null +++ b/packages/inspection/lib/data/model/response/auth/auth_response_model.dart @@ -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 json) => + _$AuthResponseModelFromJson(json); + +} + diff --git a/packages/inspection/lib/data/model/response/auth/auth_response_model.freezed.dart b/packages/inspection/lib/data/model/response/auth/auth_response_model.freezed.dart new file mode 100644 index 0000000..fdca0fc --- /dev/null +++ b/packages/inspection/lib/data/model/response/auth/auth_response_model.freezed.dart @@ -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 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 get copyWith => _$AuthResponseModelCopyWithImpl(this as AuthResponseModel, _$identity); + + /// Serializes this AuthResponseModel to a JSON map. + Map 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 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 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? 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 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 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? 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 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 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 diff --git a/packages/inspection/lib/data/model/response/auth/auth_response_model.g.dart b/packages/inspection/lib/data/model/response/auth/auth_response_model.g.dart new file mode 100644 index 0000000..dc5d66d --- /dev/null +++ b/packages/inspection/lib/data/model/response/auth/auth_response_model.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'auth_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_AuthResponseModel _$AuthResponseModelFromJson(Map json) => + _AuthResponseModel( + refresh: json['refresh'] as String?, + access: json['access'] as String?, + otpStatus: json['otp_status'] as bool?, + ); + +Map _$AuthResponseModelToJson(_AuthResponseModel instance) => + { + 'refresh': instance.refresh, + 'access': instance.access, + 'otp_status': instance.otpStatus, + }; diff --git a/packages/inspection/lib/data/model/response/captcha/captcha_response_model.dart b/packages/inspection/lib/data/model/response/captcha/captcha_response_model.dart new file mode 100644 index 0000000..2b2f986 --- /dev/null +++ b/packages/inspection/lib/data/model/response/captcha/captcha_response_model.dart @@ -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 json) => + _$CaptchaResponseModelFromJson(json); +} diff --git a/packages/inspection/lib/data/model/response/captcha/captcha_response_model.freezed.dart b/packages/inspection/lib/data/model/response/captcha/captcha_response_model.freezed.dart new file mode 100644 index 0000000..33d0167 --- /dev/null +++ b/packages/inspection/lib/data/model/response/captcha/captcha_response_model.freezed.dart @@ -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 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 get copyWith => _$CaptchaResponseModelCopyWithImpl(this as CaptchaResponseModel, _$identity); + + /// Serializes this CaptchaResponseModel to a JSON map. + Map 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 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 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? 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 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 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? 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 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 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 diff --git a/packages/inspection/lib/data/model/response/captcha/captcha_response_model.g.dart b/packages/inspection/lib/data/model/response/captcha/captcha_response_model.g.dart new file mode 100644 index 0000000..8d69248 --- /dev/null +++ b/packages/inspection/lib/data/model/response/captcha/captcha_response_model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'captcha_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_CaptchaResponseModel _$CaptchaResponseModelFromJson( + Map 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 _$CaptchaResponseModelToJson( + _CaptchaResponseModel instance, +) => { + 'captcha_key': instance.captchaKey, + 'captcha_image': instance.captchaImage, + 'image_type': instance.imageType, + 'image_decode': instance.imageDecode, +}; diff --git a/packages/inspection/lib/data/model/response/poultry_location/poultry_location_model.dart b/packages/inspection/lib/data/model/response/poultry_location/poultry_location_model.dart new file mode 100644 index 0000000..c470b20 --- /dev/null +++ b/packages/inspection/lib/data/model/response/poultry_location/poultry_location_model.dart @@ -0,0 +1,68 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'poultry_location_model.freezed.dart'; +part 'poultry_location_model.g.dart'; + +@freezed +abstract class PoultryLocationModel with _$PoultryLocationModel { + const factory PoultryLocationModel({ + int? id, + String? unitName, + @JsonKey(name: 'Lat') + double? lat, + @JsonKey(name: 'Long') + double? long, + User? user, + List? hatching, + Address? address, + }) = _PoultryLocationModel; + + factory PoultryLocationModel.fromJson(Map json) => + _$PoultryLocationModelFromJson(json); +} + +@freezed +abstract class User with _$User { + const factory User({ + String? fullname, + String? mobile, + }) = _User; + + factory User.fromJson(Map json) => _$UserFromJson(json); +} + +@freezed +abstract class Hatching with _$Hatching { + const factory Hatching({ + int? quantity, + int? leftOver, + int? period, + int? chickenAge, + DateTime? date, + bool?violation, + bool?archive, + }) = _Hatching; + + factory Hatching.fromJson(Map json) => + _$HatchingFromJson(json); +} + +@freezed +abstract class Address with _$Address { + const factory Address({ + City? city, + String? address, + }) = _Address; + + factory Address.fromJson(Map json) => + _$AddressFromJson(json); +} + +@freezed +abstract class City with _$City { + const factory City({ + String? name, + }) = _City; + + factory City.fromJson(Map json) => _$CityFromJson(json); +} diff --git a/packages/inspection/lib/data/model/response/user_profile/user_profile_model.dart b/packages/inspection/lib/data/model/response/user_profile/user_profile_model.dart new file mode 100644 index 0000000..a9dea06 --- /dev/null +++ b/packages/inspection/lib/data/model/response/user_profile/user_profile_model.dart @@ -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 permissions, + }) = _UserProfileModel; + + factory UserProfileModel.fromJson(Map 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 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 permissions, + }) = _Role; + + factory Role.fromJson(Map json) => _$RoleFromJson(json); +} + +@freezed +abstract class RoleType with _$RoleType { + const factory RoleType({String? key, required String name}) = _RoleType; + + factory RoleType.fromJson(Map json) => _$RoleTypeFromJson(json); +} + +@freezed +abstract class Permission with _$Permission { + const factory Permission({required String pageName, required List pageAccess}) = + _Permission; + + factory Permission.fromJson(Map json) => _$PermissionFromJson(json); +} diff --git a/packages/inspection/lib/data/repositories/auth/auth_repository.dart b/packages/inspection/lib/data/repositories/auth/auth_repository.dart new file mode 100644 index 0000000..d582adb --- /dev/null +++ b/packages/inspection/lib/data/repositories/auth/auth_repository.dart @@ -0,0 +1,17 @@ + +import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart'; +import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart'; + +abstract class AuthRepository { + Future login({required Map authRequest}); + + Future captcha(); + + Future logout(); + + Future hasAuthenticated(); + + Future loginWithRefreshToken({required Map authRequest}); + + +} diff --git a/packages/inspection/lib/data/repositories/auth/auth_repository_imp.dart b/packages/inspection/lib/data/repositories/auth/auth_repository_imp.dart new file mode 100644 index 0000000..2e6e452 --- /dev/null +++ b/packages/inspection/lib/data/repositories/auth/auth_repository_imp.dart @@ -0,0 +1,37 @@ +import 'package:rasadyar_inspection/data/data_source/remote/auth/auth_remote.dart'; +import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart'; +import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart'; + +import 'auth_repository.dart'; + +class AuthRepositoryImpl implements AuthRepository { + final AuthRemote authRemote; + + AuthRepositoryImpl(this.authRemote); + + @override + Future login({required Map authRequest}) async => + await authRemote.login(authRequest: authRequest); + + @override + Future captcha() async { + return await authRemote.captcha(); + } + + @override + Future loginWithRefreshToken({ + required Map authRequest, + }) async { + return await authRemote.loginWithRefreshToken(authRequest: authRequest); + } + + @override + Future logout() async { + await authRemote.logout(); + } + + @override + Future hasAuthenticated() async { + return await authRemote.hasAuthenticated(); + } +} diff --git a/packages/inspection/lib/data/repositories/auth_repository.dart b/packages/inspection/lib/data/repositories/auth_repository.dart deleted file mode 100644 index 179483a..0000000 --- a/packages/inspection/lib/data/repositories/auth_repository.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:rasadyar_core/data/model/response/auth/auth_response_model.dart'; -import 'package:rasadyar_core/data/model/response/captcha/captcha_response_model.dart'; -import 'package:rasadyar_core/data/model/response/user_info/user_info_model.dart'; -import 'package:rasadyar_core/data/model/response/user_profile_model/user_profile_model.dart'; - -abstract class AuthRepository { - Future login({required Map authRequest}); - - Future captcha(); - - Future logout(); - - Future hasAuthenticated(); - - Future loginWithRefreshToken({required Map authRequest}); - - Future getUserInfo(String phoneNumber); -} diff --git a/packages/inspection/lib/data/repositories/inspection/inspection_repository.dart b/packages/inspection/lib/data/repositories/inspection/inspection_repository.dart new file mode 100644 index 0000000..148ce5b --- /dev/null +++ b/packages/inspection/lib/data/repositories/inspection/inspection_repository.dart @@ -0,0 +1,24 @@ +import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart'; + +abstract class InspectionRepository { + /// Fetches the inspection data for a given [inspectionId]. + /// + /// Returns a `Future` that resolves to a `Map` containing + /// the inspection data. + Future> fetchInspectionData(String inspectionId); + + /// Fetches the list of inspections for a given [userId]. + /// + /// Returns a `Future` that resolves to a `List>` + /// containing the list of inspections. + Future>> fetchInspections(String userId); + + /// Fetches nearby poultry locations based on the provided coordinates and radius. + /// + /// Returns a `Future` that resolves to a `List?`. + Future?> getNearbyLocation({ + double? centerLat, + double? centerLng, + double? radius, + }); +} \ No newline at end of file diff --git a/packages/inspection/lib/data/repositories/inspection/inspection_repository_imp.dart b/packages/inspection/lib/data/repositories/inspection/inspection_repository_imp.dart new file mode 100644 index 0000000..90feb85 --- /dev/null +++ b/packages/inspection/lib/data/repositories/inspection/inspection_repository_imp.dart @@ -0,0 +1,34 @@ +import 'package:rasadyar_inspection/data/data_source/remote/inspection/inspection_remote.dart'; +import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart'; +import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository.dart'; + +class InspectionRepositoryImp implements InspectionRepository { + final InspectionRemoteDataSource remoteDataSource; + + InspectionRepositoryImp({required this.remoteDataSource}); + + @override + Future> fetchInspectionData(String inspectionId) { + // TODO: implement fetchInspectionData + throw UnimplementedError(); + } + + @override + Future>> fetchInspections(String userId) { + // TODO: implement fetchInspections + throw UnimplementedError(); + } + + @override + Future?> getNearbyLocation({ + double? centerLat, + double? centerLng, + double? radius, + }) async { + return remoteDataSource.getNearbyLocation( + centerLat: centerLat, + centerLng: centerLng, + radius: radius, + ); + } +} diff --git a/packages/inspection/lib/data/repositories/user/user_repository.dart b/packages/inspection/lib/data/repositories/user/user_repository.dart new file mode 100644 index 0000000..b5974e9 --- /dev/null +++ b/packages/inspection/lib/data/repositories/user/user_repository.dart @@ -0,0 +1,19 @@ + +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; + +abstract class UserRepository { + /// Fetches the user profile from the remote data source. + /// + /// Returns a [Future] that resolves to a [UserProfileModel]. + Future fetchUserProfile({required String token}); + + /// Updates the user profile in the remote data source. + /// + /// Takes a [UserProfileModel] as an argument and returns a [Future] that resolves to a boolean indicating success or failure. + Future updateUserProfile(UserProfileModel userProfile); + + /// Changes the password of the user in the remote data source. + /// + /// Takes the old password, new password, and confirm password as arguments and returns a [Future] that resolves to a boolean indicating success or failure. + Future changePassword(String oldPassword, String newPassword, String confirmPassword); +} diff --git a/packages/inspection/lib/data/repositories/user/user_repository_imp.dart b/packages/inspection/lib/data/repositories/user/user_repository_imp.dart new file mode 100644 index 0000000..abd87fe --- /dev/null +++ b/packages/inspection/lib/data/repositories/user/user_repository_imp.dart @@ -0,0 +1,28 @@ + +import 'package:rasadyar_inspection/data/data_source/remote/user/user_data_source_imp.dart'; +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; + +import 'user_repository.dart'; + +class UserRepositoryImp implements UserRepository { + final UserRemoteDataSourceImp _remoteDataSource; + + UserRepositoryImp(this._remoteDataSource); + + @override + Future changePassword(String oldPassword, String newPassword, String confirmPassword) { + // TODO: implement changePassword + throw UnimplementedError(); + } + + @override + Future fetchUserProfile({required String token}) async { + return await _remoteDataSource.getProfile(token: token); + } + + @override + Future updateUserProfile(UserProfileModel userProfile) { + // TODO: implement updateUserProfile + throw UnimplementedError(); + } +} diff --git a/packages/inspection/lib/data/utils/dio_exception_handeler.dart b/packages/inspection/lib/data/utils/dio_exception_handeler.dart new file mode 100644 index 0000000..6f5e233 --- /dev/null +++ b/packages/inspection/lib/data/utils/dio_exception_handeler.dart @@ -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, + ); + } +} diff --git a/packages/inspection/lib/injection/inspection_di.dart b/packages/inspection/lib/injection/inspection_di.dart new file mode 100644 index 0000000..456896e --- /dev/null +++ b/packages/inspection/lib/injection/inspection_di.dart @@ -0,0 +1,71 @@ +import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/data/data_source/remote/auth/auth_remote.dart'; +import 'package:rasadyar_inspection/data/data_source/remote/auth/auth_remote_imp.dart'; +import 'package:rasadyar_inspection/data/data_source/remote/inspection/inspection_remote_imp.dart'; +import 'package:rasadyar_inspection/data/data_source/remote/user/user_data_source_imp.dart'; +import 'package:rasadyar_inspection/data/repositories/auth/auth_repository_imp.dart'; +import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository_imp.dart'; +import 'package:rasadyar_inspection/data/repositories/user/user_repository_imp.dart'; +import 'package:rasadyar_inspection/data/utils/dio_exception_handeler.dart'; +import 'package:rasadyar_inspection/presentation/routes/app_routes.dart'; + +GetIt diInspection = GetIt.instance; + +Future setupInspectionDI() async { + diInspection.registerSingleton(DioErrorHandler()); + var tokenService = Get.find(); + if (tokenService.baseurl.value == null) { + await tokenService.saveBaseUrl('https://bazrasbackend.rasadyaar.ir/'); + } + diInspection.registerLazySingleton( + () => AppInterceptor( + //TODO : Update the base URL to the correct one for inspection module + refreshTokenCallback: () async => null, + saveTokenCallback: (String newToken) async { + await tokenService.saveAccessToken(newToken); + }, + clearTokenCallback: () async { + await tokenService.deleteTokens(); + Get.offAllNamed(InspectionRoutes.auth, arguments: Module.inspection); + }, + authArguments: Module.inspection, + ), + instanceName: 'inspectionInterceptor', + ); + + diInspection.registerLazySingleton(() { + return DioRemote( + baseUrl: tokenService.baseurl.value, + interceptors: diInspection.get(instanceName: 'inspectionInterceptor'), + ); + }, instanceName: 'inspectionDioRemote'); + + var dioRemote = diInspection.get(instanceName: 'inspectionDioRemote'); + await dioRemote.init(); + + diInspection.registerLazySingleton( + () => AuthRemoteImp(diInspection.get(instanceName: 'inspectionDioRemote')), + ); + + diInspection.registerSingleton( + AuthRepositoryImpl(diInspection.get()), + ); + + diInspection.registerSingleton( + UserRemoteDataSourceImp(diInspection.get(instanceName: 'inspectionDioRemote')), + ); + + diInspection.registerSingleton( + UserRepositoryImp(diInspection.get()), + ); + + diInspection.registerSingleton( + InspectionRemoteDataSourceImp(diInspection.get(instanceName: 'inspectionDioRemote')), + ); + + diInspection.registerSingleton( + InspectionRepositoryImp(remoteDataSource: diInspection.get()), + ); + + diInspection.registerSingleton(ImagePicker()); +} diff --git a/packages/inspection/lib/presentation/pages/auth/logic.dart b/packages/inspection/lib/presentation/pages/auth/logic.dart index 126589b..0e157a2 100644 --- a/packages/inspection/lib/presentation/pages/auth/logic.dart +++ b/packages/inspection/lib/presentation/pages/auth/logic.dart @@ -2,10 +2,12 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; -import 'package:rasadyar_core/data/model/request/login_request/login_request_model.dart'; -import 'package:rasadyar_core/data/model/response/user_info/user_info_model.dart'; -import 'package:rasadyar_core/data/model/response/user_profile_model/user_profile_model.dart'; -import 'package:rasadyar_inspection/data/repositories/auth_repository_imp.dart'; +import 'package:rasadyar_inspection/data/model/request/login_request/login_request_model.dart'; +import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart'; +import 'package:rasadyar_inspection/data/repositories/auth/auth_repository_imp.dart'; +import 'package:rasadyar_inspection/data/utils/dio_exception_handeler.dart'; +import 'package:rasadyar_inspection/injection/inspection_di.dart'; +import 'package:rasadyar_inspection/presentation/routes/app_routes.dart'; import 'package:rasadyar_inspection/presentation/widget/captcha/logic.dart'; enum AuthType { useAndPass, otp } @@ -38,7 +40,7 @@ class AuthLogic extends GetxController { RxInt secondsRemaining = 120.obs; Timer? _timer; - //AuthRepositoryImpl authRepository = diAuth.get(); + AuthRepositoryImpl authRepository = diInspection.get(); final Module _module = Get.arguments; @@ -97,33 +99,34 @@ class AuthLogic extends GetxController { ); } - /*Future submitLoginForm() async { + Future submitLoginForm() async { if (!_isFormValid()) return; - iLog('module222 : ${_module.toString()}'); + final loginRequestModel = _buildLoginRequest(); isLoading.value = true; await safeCall( - call: () => authRepository.login(authRequest: loginRequestModel.toJson()), + 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(InspectionRoutes.init); }, onError: (error, stackTrace) { if (error is DioException) { - diAuth.get().handle(error); + diInspection.get().handle(error); } captchaController.getCaptcha(); }, ); isLoading.value = false; - }*/ + } Future submitLoginForm2() async { if (!_isFormValid()) return; //AuthRepositoryImpl authTmp = diAuth.get(instanceName: 'newUrl'); isLoading.value = true; - /* await safeCall( + /* await safeCall( call: () => authTmp.login( authRequest: { "username": usernameController.value.text, diff --git a/packages/inspection/lib/presentation/pages/auth/view.dart b/packages/inspection/lib/presentation/pages/auth/view.dart index 213c747..0c10507 100644 --- a/packages/inspection/lib/presentation/pages/auth/view.dart +++ b/packages/inspection/lib/presentation/pages/auth/view.dart @@ -184,7 +184,7 @@ class AuthPage extends GetView { onPressed: controller.isDisabled.value ? null : () async { - await controller.submitLoginForm2(); + await controller.submitLoginForm(); }, width: Get.width, height: 48, diff --git a/packages/inspection/lib/presentation/pages/inspection_map/logic.dart b/packages/inspection/lib/presentation/pages/inspection_map/logic.dart index 944784c..f1dfd8c 100644 --- a/packages/inspection/lib/presentation/pages/inspection_map/logic.dart +++ b/packages/inspection/lib/presentation/pages/inspection_map/logic.dart @@ -1,20 +1,23 @@ - import 'dart:async'; import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; -import 'package:rasadyar_inspection/data/utils/marker_generator.dart'; +import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart'; +import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository_imp.dart'; +import 'package:rasadyar_inspection/injection/inspection_di.dart'; import 'package:rasadyar_inspection/presentation/widget/base_page/logic.dart'; import '../filter/view.dart'; class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin { - final BaseLogic baseLogic = Get.find(); - Rx currentLocation = LatLng(35.824891, 50.948025).obs; - RxList allMarkers = [].obs; - RxList markers = [].obs; + Rx currentLocation = LatLng(34.798315281272544, 48.51479142983491).obs; + Rx>> allPoultryLocation = + Resource>.loading().obs; + + RxList markers = [].obs; + Timer? _debounceTimer; RxBool isLoading = false.obs; RxBool isSelectedDetailsLocation = false.obs; @@ -33,55 +36,7 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin late DraggableBottomSheetController detailsLocationBottomSheetController; late final BottomSheetManager bottomSheetManager; - Future determineCurrentPosition() async { - isLoading.value = true; - final position = await Geolocator.getCurrentPosition( - locationSettings: AndroidSettings(accuracy: LocationAccuracy.best), - ); - final latLng = LatLng(position.latitude, position.longitude); - - currentLocation.value = latLng; - markers.add(latLng); - animatedMapController.animateTo( - dest: latLng, - zoom: 18, - curve: Curves.easeInOut, - duration: const Duration(seconds: 1), - ); - isLoading.value = false; - } - - void debouncedUpdateVisibleMarkers({required LatLng center}) { - _debounceTimer?.cancel(); - _debounceTimer = Timer(const Duration(milliseconds: 300), () { - final filtered = filterNearbyMarkers({ - 'markers': allMarkers, - 'centerLat': center.latitude, - 'centerLng': center.longitude, - 'radius': 2000.0, - }); - - markers.addAll(filtered); - }); - } - - List filterNearbyMarkers(Map args) { - final List rawMarkers = args['markers']; - final double centerLat = args['centerLat']; - final double centerLng = args['centerLng']; - final double radiusInMeters = args['radius']; - final center = LatLng(centerLat, centerLng); - final distance = Distance(); - - return rawMarkers - .where((marker) => distance(center, marker) <= radiusInMeters) - .toList(); - } - - Future generatedMarkers() async { - final generatedMarkers = await generateLocationsUsingCompute(100000); - allMarkers.value = generatedMarkers; - } + InspectionRepositoryImp inspectionRepository = diInspection.get(); @override void onInit() { @@ -92,6 +47,7 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin curve: Curves.easeInOut, cancelPreviousAnimations: true, ); + fetchAllPoultryLocations(); filterBottomSheetController = DraggableBottomSheetController( initialHeight: 350, @@ -105,7 +61,6 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin maxHeight: 200, ); - detailsLocationBottomSheetController = DraggableBottomSheetController( initialHeight: Get.height * 0.5, minHeight: Get.height * 0.37, @@ -114,13 +69,10 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin slidController = SlidableController(this).obs; bottomSheetManager = BottomSheetManager({ - filterBottomSheetController: - () => filterWidget(filterIndex: filterIndex, showIndex: showIndex), - selectedLocationBottomSheetController: - () => selectedLocationWidget( - showHint: - selectedLocationBottomSheetController.isVisible.value && - showSlideHint, + filterBottomSheetController: () => + filterWidget(filterIndex: filterIndex, showIndex: showIndex), + selectedLocationBottomSheetController: () => selectedLocationWidget( + showHint: selectedLocationBottomSheetController.isVisible.value && showSlideHint, sliderController: slidController.value, trigger: triggerSlidableAnimation, toggle: selectedLocationBottomSheetController.toggle, @@ -132,8 +84,63 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin @override void onReady() { super.onReady(); - determineCurrentPosition(); - generatedMarkers(); + //determineCurrentPosition(); + } + + @override + void onClose() { + slidController.close(); + super.onClose(); + } + + Future determineCurrentPosition() async { + isLoading.value = true; + final position = await Geolocator.getCurrentPosition( + locationSettings: AndroidSettings(accuracy: LocationAccuracy.best), + ); + final latLng = LatLng(position.latitude, position.longitude); + + /*currentLocation.value = latLng; + markers.add(PoultryLocationModel( + lat: latLng.latitude, + long: latLng.longitude + ));*/ + animatedMapController.animateTo( + dest: latLng, + zoom: 18, + curve: Curves.easeInOut, + duration: const Duration(seconds: 1), + ); + isLoading.value = false; + } + + void debouncedUpdateVisibleMarkers({required LatLng center}) { + _debounceTimer?.cancel(); + _debounceTimer = Timer(const Duration(milliseconds: 300), () { + final filtered = filterNearbyMarkers( + allPoultryLocation.value.data ?? [], + center.latitude, + center.longitude, + 10000, // Radius in meters + ); + + markers.addAll(filtered); + }); + } + + List filterNearbyMarkers( + List allMarkers, + double centerLat, + double centerLng, + double radiusInMeters, + ) { + final center = LatLng(centerLat, centerLng); + final distance = Distance(); + + return allMarkers.where((marker) { + var tmp =LatLng(marker.lat ?? 0, marker.long ?? 0); + return distance(center,tmp ) <= radiusInMeters; + }).toList(); } Future triggerSlidableAnimation() async { @@ -144,9 +151,23 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin showSlideHint = false; } - @override - void onClose() { - slidController.close(); - super.onClose(); + Future fetchAllPoultryLocations() async { + isLoading.value = true; + allPoultryLocation.value = Resource>.loading(); + await safeCall( + call: () => inspectionRepository.getNearbyLocation(), + onSuccess: (result) { + if (result != null) { + allPoultryLocation.value = Resource>.success(result); + } else { + allPoultryLocation.value = Resource>.error( + 'No locations found', + ); + } + }, + onError: (error, stackTrace) { + allPoultryLocation.value = Resource>.error(error.toString()); + }, + ); } } diff --git a/packages/inspection/lib/presentation/pages/inspection_map/view.dart b/packages/inspection/lib/presentation/pages/inspection_map/view.dart index 9932fe0..9645419 100644 --- a/packages/inspection/lib/presentation/pages/inspection_map/view.dart +++ b/packages/inspection/lib/presentation/pages/inspection_map/view.dart @@ -54,7 +54,7 @@ class InspectionMapPage extends GetView { markers: markers .map( (e) => markerWidget( - marker: e, + marker: LatLng(e.lat??0, e.long??0), onTap: () { Get.bottomSheet( selectedLocationWidget2( @@ -295,6 +295,7 @@ class InspectionMapPage extends GetView { } Marker markerWidget({required LatLng marker, required VoidCallback onTap}) { + iLog('lat: ${marker.latitude}, lng: ${marker.longitude}'); return Marker( point: marker, child: GestureDetector( diff --git a/packages/inspection/lib/presentation/pages/profile/logic.dart b/packages/inspection/lib/presentation/pages/profile/logic.dart index ced5ff0..e71a84b 100644 --- a/packages/inspection/lib/presentation/pages/profile/logic.dart +++ b/packages/inspection/lib/presentation/pages/profile/logic.dart @@ -1,28 +1,27 @@ import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; +import 'package:rasadyar_inspection/data/repositories/user/user_repository_imp.dart'; +import 'package:rasadyar_inspection/injection/inspection_di.dart'; +import 'package:rasadyar_inspection/inspection.dart'; class ProfileLogic extends GetxController { - - - List roles = [ - 'کاربر عادی', - 'کاربر ویژه', - 'کاربر VIP', - 'کاربر نقره ای', - 'کاربر طلایی', - - ]; - - - + RootLogic rootLogic = Get.find(); + UserRepositoryImp userRepository = diInspection.get(); + Rx> userProfile = Resource.loading().obs; RxInt selectedRole = 0.obs; RxInt selectedInformationType = 0.obs; - @override void onReady() { - // TODO: implement onReady super.onReady(); + rootLogic.userProfile.listen((data) { + if (data != null) { + userProfile.value = Resource.success(data); + } else { + userProfile.value = Resource.error('Failed to load user profile'); + } + }); } @override @@ -30,4 +29,26 @@ class ProfileLogic extends GetxController { // TODO: implement onClose super.onClose(); } + + Future fetchUserProfile() async { + userProfile.value = Resource.loading(); + + await safeCall( + call: () => userRepository.fetchUserProfile( + token: rootLogic.tokenStorageService.accessToken.value ?? '', + ), + onSuccess: (profile) { + if (profile != null) { + userProfile.value = Resource.success(profile); + } else { + userProfile.value = Resource.error('Failed to load user profile'); + } + }, + onError: (error, stackTrace) { + userProfile.value = Resource.error( + 'Failed to load user profile: ${error.toString()}', + ); + }, + ); + } } diff --git a/packages/inspection/lib/presentation/pages/profile/view.dart b/packages/inspection/lib/presentation/pages/profile/view.dart index b125f1a..510f243 100644 --- a/packages/inspection/lib/presentation/pages/profile/view.dart +++ b/packages/inspection/lib/presentation/pages/profile/view.dart @@ -1,5 +1,7 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; import 'logic.dart'; @@ -9,124 +11,96 @@ class ProfilePage extends GetView { @override Widget build(BuildContext context) { return Column( - spacing: 30, children: [ - SizedBox( - height: Get.height * 0.3, - child: Stack( - fit: StackFit.expand, - alignment: Alignment.center, - clipBehavior: Clip.none, - children: [ - Assets.vec.bgHeaderUserProfileSvg.svg(), - Positioned( - bottom: -20, - left: 0, - right: 0, - child: SizedBox( - width: 110, - height: 110, - child: CircleAvatar( - backgroundColor: AppColor.blueLightHover, - child: FaIcon( - FontAwesomeIcons.user, - size: 45, - color: Colors.white, + Expanded( + flex: 1, + child: Container( + color: AppColor.blueNormal, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row(), + ObxValue((data) { + final status = data.value.status; + + if (status == ResourceStatus.loading) { + return Container( + width: 128.w, + height: 128.h, + child: Center(child: CupertinoActivityIndicator(color: AppColor.greenNormal)), + ); + } + + if (status == ResourceStatus.error) { + return Container( + width: 128.w, + height: 128.h, + child: Center(child: Text('خطا در دریافت اطلاعات')), + ); + } + + // Default UI + return Container( + width: 128.w, + height: 128.h, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.blueLightActive, ), - ), - ), - ), - ], + child: Center( + child: CircleAvatar( + radius: 64.w, + backgroundImage: NetworkImage(data.value.data?.user.photo ?? ''), + ), + ), + ); + }, controller.userProfile), + ], + ), ), ), Expanded( + flex: 3, child: Column( crossAxisAlignment: CrossAxisAlignment.start, spacing: 16, children: [ - SizedBox( - height: 75, - child: ListView.separated( - shrinkWrap: true, - padding: EdgeInsets.all(16), - scrollDirection: Axis.horizontal, - itemBuilder: - (context, index) => ObxValue((data) { - return ChoiceChip( - onSelected: (value) { - data.value = index; - }, - selectedColor: AppColor.blueNormal, - labelStyle: - data.value == index - ? AppFonts.yekan13.copyWith( - color: AppColor.whiteLight, - ) - : AppFonts.yekan12.copyWith( - color: AppColor.darkGreyNormalActive, - ), - checkmarkColor: Colors.white, - label: Text(controller.roles[index]), - selected: index == data.value, - ); - }, controller.selectedRole), - - separatorBuilder: (context, index) => SizedBox(width: 8), - itemCount: controller.roles.length, - ), - ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 30, - vertical: 10, - ), - child: ObxValue((data) { - return switch (data.value) { - 0 => userProfileInformation(), - 1 => bankInformationWidget(), - 2 => invoiceIssuanceInformation(), - int() => Placeholder(), - }; - }, controller.selectedInformationType), + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10), + child: userProfileInformation(), ), ), - ObxValue((data) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Wrap( - spacing: 20, - runSpacing: 10, - children: [ - cardActionWidget( - title: 'اطلاعات کاربری', - onPressed: () { - data.value = 0; - }, - icon: Assets.vec.profileUserSvg.path, - selected: data.value == 0, - ), - cardActionWidget( - title: 'اطلاعات بانکی', - onPressed: () { - data.value = 1; - }, - icon: Assets.vec.informationSvg.path, - selected: data.value == 1, - ), - cardActionWidget( - title: 'اطلاعات \nصدور فاکتور', - onPressed: () { - data.value = 2; - }, - icon: Assets.vec.receiptDiscountSvg.path, - selected: data.value == 2, - ), - ], - ), - ); - }, controller.selectedInformationType), + Center( + child: Wrap( + alignment: WrapAlignment.center, + spacing: 20, + runSpacing: 10, + children: [ + cardActionWidget( + title: 'تغییر رمز عبور', + selected: true, + onPressed: () { + Get.bottomSheet(changePasswordBottomSheet(), isScrollControlled: true); + }, + icon: Assets.vec.lockSvg.path, + ), + cardActionWidget( + title: 'خروج', + selected: true, + color: ColorFilter.mode(Colors.redAccent, BlendMode.srcIn), + cardColor: Color(0xFFEFEFEF), + textColor: AppColor.redDarkerText, + onPressed: () { + Get.bottomSheet(exitBottomSheet(), isScrollControlled: true); + }, + icon: Assets.vec.logoutSvg.path, + ), + ], + ), + ), SizedBox(height: 100), ], @@ -149,72 +123,113 @@ class ProfilePage extends GetView { ], ); - Column userProfileInformation() { - return Column( - spacing: 10, - children: [ - itemList( - title: 'نام و نام خانوادگی', - content: 'آیدا گل محمدی', - icon: Assets.vec.userSvg.path, - ), - itemList( - title: 'موبایل', - content: '09302654896', - icon: Assets.vec.callSvg.path, - ), - itemList( - title: 'کدملی', - content: 'نا مشخص', - icon: Assets.vec.tagUserSvg.path, - ), - itemList( - title: 'شماره شناسنامه', - content: 'نا مشخص', - icon: Assets.vec.userSquareSvg.path, - ), - itemList( - title: 'تاریخ تولد', - content: '1404/10/12', - icon: Assets.vec.calendarSvg.path, - ), - itemList( - title: 'استان', - content: 'لرستان', - icon: Assets.vec.pictureFrameSvg.path, - ), - itemList( - title: 'شهر', - content: 'خرم آباد', - icon: Assets.vec.mapSvg.path, - ), - ], - ); + Widget userProfileInformation() { + return ObxValue((data) { + if (data.value.status == ResourceStatus.loading) { + return LoadingWidget(); + } else if (data.value.status == ResourceStatus.error) { + return ErrorWidget('خطا در دریافت اطلاعات کاربر'); + } else if (data.value.status == ResourceStatus.success) { + User item = data.value.data!.user; + return Column( + spacing: 6, + children: [ + buildRowOnTapped( + onTap: () { + Get.bottomSheet( + userInformationBottomSheet(), + isScrollControlled: true, + ignoreSafeArea: false, + ); + }, + titleWidget: Column( + spacing: 3, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'اطلاعات هویتی', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), + ), + Container(width: 37.w, height: 1.h, color: AppColor.greenNormal), + ], + ), + valueWidget: Assets.vec.editSvg.svg( + width: 24.w, + height: 24.h, + colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn), + ), + ), + itemList( + title: 'نام و نام خانوادگی', + content: '${item.firstName} ${item.lastName}', + icon: Assets.vec.userSvg.path, + hasColoredBox: true, + ), + itemList( + title: 'موبایل', + content: item.mobile ?? 'نامشخص', + icon: Assets.vec.callSvg.path, + ), + itemList( + title: 'کدملی', + content: item.nationalCode ?? 'نامشخص', + icon: Assets.vec.tagUserSvg.path, + ), + itemList( + title: 'شماره شناسنامه', + content: item.nationalCode ?? 'نامشخص', + icon: Assets.vec.userSquareSvg.path, + ), + + itemList( + title: 'استان', + content: item.provinceName ?? 'نامشخص', + icon: Assets.vec.pictureFrameSvg.path, + ), + itemList( + title: 'شهر', + content: item.cityName ?? 'نامشخص', + icon: Assets.vec.mapSvg.path, + ), + ], + ); + } else { + return SizedBox.shrink(); + } + }, controller.userProfile); } Widget itemList({ required String title, required String content, String? icon, - }) => Row( - spacing: 4, - children: [ - if (icon != null) - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: SvgGenImage.vec(icon).svg( - width: 20, - height: 20, - colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn), + bool hasColoredBox = false, + }) => Container( + padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h), + decoration: BoxDecoration( + color: hasColoredBox ? AppColor.greenLight : Colors.transparent, + borderRadius: BorderRadius.circular(8), + border: hasColoredBox + ? Border.all(width: 0.25, color: AppColor.bgDark) + : Border.all(width: 0, color: Colors.transparent), + ), + child: Row( + spacing: 4, + children: [ + if (icon != null) + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: SvgGenImage.vec(icon).svg( + width: 20.w, + height: 20.h, + colorFilter: ColorFilter.mode(AppColor.mediumGreyNormalActive, BlendMode.srcIn), + ), ), - ), - Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal)), - Spacer(), - Text( - content, - style: AppFonts.yekan13.copyWith(color: AppColor.darkGreyNormalHover), - ), - ], + Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)), + Spacer(), + Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)), + ], + ), ); Widget cardActionWidget({ @@ -222,6 +237,9 @@ class ProfilePage extends GetView { required VoidCallback onPressed, required String icon, bool selected = false, + ColorFilter? color, + Color? cardColor, + Color? textColor, }) { return GestureDetector( onTap: onPressed, @@ -233,25 +251,25 @@ class ProfilePage extends GetView { height: 52, padding: EdgeInsets.all(8), decoration: ShapeDecoration( - color: selected ? AppColor.blueLightActive : AppColor.blueLight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), + color: cardColor ?? AppColor.blueLight, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: SvgGenImage.vec(icon).svg( width: 40, height: 40, - colorFilter: ColorFilter.mode( - selected ? AppColor.whiteLight : AppColor.blueNormal, - BlendMode.srcIn, - ), + colorFilter: + color ?? + ColorFilter.mode( + selected ? AppColor.blueNormal : AppColor.whiteLight, + BlendMode.srcIn, + ), ), ), SizedBox(height: 2), Text( title, style: AppFonts.yekan10.copyWith( - color: selected ? AppColor.blueNormal : AppColor.blueLightActive, + color: textColor ?? (selected ? AppColor.blueNormal : AppColor.blueLightActive), ), textAlign: TextAlign.center, ), @@ -259,4 +277,359 @@ class ProfilePage extends GetView { ), ); } + + Widget userInformationBottomSheet() { + return Container(color: Colors.red); + /* return BaseBottomSheet( + height: 750.h, + child: SingleChildScrollView( + child: Column( + spacing: 8, + children: [ + Text( + 'ویرایش اطلاعات هویتی', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), + ), + + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: AppColor.darkGreyLight, width: 1), + ), + child: Column( + spacing: 12, + children: [ + RTextField( + controller: controller.nameController, + label: 'نام', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + ), + RTextField( + controller: controller.lastNameController, + label: 'نام خانوادگی', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + ), + RTextField( + controller: controller.nationalCodeController, + label: 'شماره شناسنامه', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + ), + RTextField( + controller: controller.nationalIdController, + label: 'کد ملی', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + ), + + ObxValue((data) { + return RTextField( + controller: controller.birthdayController, + label: 'تاریخ تولد', + initText: data.value?.formatCompactDate() ?? '', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + onTap: () {}, + ); + }, controller.birthDate), + + SizedBox(), + ], + ), + ), + SizedBox(), + + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: AppColor.darkGreyLight, width: 1), + ), + child: Column( + spacing: 8, + children: [ + Text( + 'عکس پروفایل', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), + ), + ObxValue((data) { + return Container( + width: Get.width, + height: 270, + decoration: BoxDecoration( + color: AppColor.lightGreyNormal, + borderRadius: BorderRadius.circular(8), + border: Border.all(width: 1, color: AppColor.blackLight), + ), + child: Center( + child: data.value == null + ? Padding( + padding: const EdgeInsets.fromLTRB(30, 10, 10, 30), + child: Image.network( + controller.userProfile.value.data?.image ?? '', + ), + ) + : Image.file(File(data.value!.path), fit: BoxFit.cover), + ), + ); + }, controller.selectedImage), + + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RElevated( + text: 'گالری', + width: 150.w, + height: 40.h, + textStyle: AppFonts.yekan20.copyWith(color: Colors.white), + onPressed: () async { + controller.selectedImage.value = await controller.imagePicker.pickImage( + source: ImageSource.gallery, + imageQuality: 60, + maxWidth: 1080, + maxHeight: 720, + ); + }, + ), + SizedBox(width: 16), + ROutlinedElevated( + text: 'دوربین', + width: 150.w, + height: 40.h, + textStyle: AppFonts.yekan20.copyWith(color: AppColor.blueNormal), + onPressed: () async { + controller.selectedImage.value = await controller.imagePicker.pickImage( + source: ImageSource.camera, + imageQuality: 60, + maxWidth: 1080, + maxHeight: 720, + ); + }, + ), + ], + ), + ], + ), + ), + Row( + spacing: 16, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ObxValue((data) { + return RElevated( + height: 40.h, + text: 'ویرایش', + isLoading: data.value, + onPressed: () async { + await controller.updateUserProfile(); + controller.getUserProfile(); + Get.back(); + }, + ); + }, controller.isOnLoading), + ROutlinedElevated( + height: 40.h, + text: 'انصراف', + borderColor: AppColor.blueNormal, + onPressed: () { + Get.back(); + }, + ), + ], + ), + ], + ), + ), + );*/ + } + + /* Widget _provinceWidget() { + return Obx(() { + return OverlayDropdownWidget( + items: controller.rootLogic.provinces, + onChanged: (value) { + controller.selectedProvince.value = value; + }, + selectedItem: controller.selectedProvince.value, + itemBuilder: (item) => Text(item.name ?? 'بدون نام'), + labelBuilder: (item) => Text(item?.name ?? 'انتخاب استان'), + ); + }); + } + + Widget _cityWidget() { + return ObxValue((data) { + return OverlayDropdownWidget( + items: data, + onChanged: (value) { + controller.selectedCity.value = value; + }, + selectedItem: controller.selectedCity.value, + itemBuilder: (item) => Text(item.name ?? 'بدون نام'), + labelBuilder: (item) => Text(item?.name ?? 'انتخاب شهر'), + ); + }, controller.cites); + }*/ + + Widget changePasswordBottomSheet() { + return Container(color: Colors.red); + /* return BaseBottomSheet( + height: 400.h, + child: SingleChildScrollView( + child: Form( + key: controller.formKey, + child: Column( + spacing: 8, + children: [ + Text( + 'تغییر رمز عبور', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), + ), + SizedBox(), + RTextField( + controller: controller.oldPasswordController, + hintText: 'رمز عبور قبلی', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + validator: (value) { + if (value == null || value.isEmpty) { + return 'رمز عبور را وارد کنید'; + } else if (controller.userProfile.value.data?.password != value) { + return 'رمز عبور صحیح نیست'; + } + return null; + }, + ), + RTextField( + controller: controller.newPasswordController, + hintText: 'رمز عبور جدید', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + validator: (value) { + if (value == null || value.isEmpty) { + return 'رمز عبور را وارد کنید'; + } else if (value.length < 6) { + return 'رمز عبور باید بیش از 6 کارکتر باشد.'; + } + return null; + }, + ), + RTextField( + controller: controller.retryNewPasswordController, + hintText: 'تکرار رمز عبور جدید', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + validator: (value) { + if (value == null || value.isEmpty) { + return 'رمز عبور را وارد کنید'; + } else if (value.length < 6) { + return 'رمز عبور باید بیش از 6 کارکتر باشد.'; + } else if (controller.newPasswordController.text != value) { + return 'رمز عبور جدید یکسان نیست'; + } + return null; + }, + ), + + SizedBox(), + + Row( + spacing: 16, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RElevated( + height: 40.h, + text: 'ویرایش', + onPressed: () async { + if (controller.formKey.currentState?.validate() != true) { + return; + } + await controller.updatePassword(); + controller.getUserProfile(); + controller.clearPasswordForm(); + Get.back(); + }, + ), + ROutlinedElevated( + height: 40.h, + text: 'انصراف', + borderColor: AppColor.blueNormal, + onPressed: () { + Get.back(); + }, + ), + ], + ), + ], + ), + ), + ), + );*/ + } + + Widget exitBottomSheet() { + return Container(color: Colors.red); + /* return BaseBottomSheet( + height: 220.h, + child: SingleChildScrollView( + child: Form( + key: controller.formKey, + child: Column( + spacing: 8, + children: [ + Text('خروج', style: AppFonts.yekan16Bold.copyWith(color: AppColor.error)), + SizedBox(), + Text( + 'آیا مطمئن هستید که می‌خواهید از حساب کاربری خود خارج شوید؟', + textAlign: TextAlign.center, + style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor), + ), + + SizedBox(), + + Row( + spacing: 16, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RElevated( + height: 40.h, + text: 'خروج', + backgroundColor: AppColor.error, + onPressed: () async { + await controller.rootLogic.tokenService.deleteTokens().then((value) { + Get.back(); + Get.offAllNamed(ChickenRoutes.auth, arguments: Module.chicken); + }); + }, + ), + ROutlinedElevated( + height: 40.h, + text: 'انصراف', + borderColor: AppColor.blueNormal, + onPressed: () { + Get.back(); + }, + ), + ], + ), + ], + ), + ), + ), + );*/ + } } diff --git a/packages/inspection/lib/presentation/pages/root/logic.dart b/packages/inspection/lib/presentation/pages/root/logic.dart index 3e2df1e..f444120 100644 --- a/packages/inspection/lib/presentation/pages/root/logic.dart +++ b/packages/inspection/lib/presentation/pages/root/logic.dart @@ -1,16 +1,60 @@ import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart'; +import 'package:rasadyar_inspection/data/repositories/user/user_repository_imp.dart'; +import 'package:rasadyar_inspection/injection/inspection_di.dart'; import 'package:rasadyar_inspection/presentation/pages/action/view.dart'; import 'package:rasadyar_inspection/presentation/pages/inspection_map/view.dart'; import 'package:rasadyar_inspection/presentation/pages/profile/view.dart'; - enum ErrorLocationType { serviceDisabled, permissionDenied, none } class RootLogic extends GetxController { RxInt currentIndex = 0.obs; List pages = [InspectionMapPage(), ActionPage(), ProfilePage()]; RxList errorLocationType = RxList(); + TokenStorageService tokenStorageService = Get.find(); + UserRepositoryImp userRepository = diInspection.get(); + Rxn userProfile = Rxn(); + + @override + void onInit() { + super.onInit(); + userRepository + .fetchUserProfile(token: tokenStorageService.accessToken.value ?? '') + .then((value) => userProfile.value = value); + } + + @override + void onReady() { + super.onReady(); + + locationServiceEnabled().then((value) { + if (!value) { + errorLocationType.add(ErrorLocationType.serviceDisabled); + } + }); + + checkPermission().then((value) { + if (!value) { + errorLocationType.add(ErrorLocationType.permissionDenied); + } + }); + + listenToLocationServiceStatus().listen((event) { + if (!event) { + errorLocationType.add(ErrorLocationType.serviceDisabled); + } else { + errorLocationType.remove(ErrorLocationType.serviceDisabled); + } + }); + } + + @override + void onClose() { + // TODO: implement onClose + super.onClose(); + } Stream listenToLocationServiceStatus() { return Geolocator.getServiceStatusStream().map((status) { @@ -52,38 +96,7 @@ class RootLogic extends GetxController { } } - @override - void onReady() { - super.onReady(); - - locationServiceEnabled().then((value) { - if (!value) { - errorLocationType.add(ErrorLocationType.serviceDisabled); - } - }); - - checkPermission().then((value) { - if (!value) { - errorLocationType.add(ErrorLocationType.permissionDenied); - } - }); - - listenToLocationServiceStatus().listen((event) { - if (!event) { - errorLocationType.add(ErrorLocationType.serviceDisabled); - } else { - errorLocationType.remove(ErrorLocationType.serviceDisabled); - } - }); - } - void changePage(int index) { currentIndex.value = index; } - - @override - void onClose() { - // TODO: implement onClose - super.onClose(); - } } diff --git a/packages/inspection/lib/presentation/pages/root/view.dart b/packages/inspection/lib/presentation/pages/root/view.dart index 578c5f8..8b4542a 100644 --- a/packages/inspection/lib/presentation/pages/root/view.dart +++ b/packages/inspection/lib/presentation/pages/root/view.dart @@ -9,46 +9,46 @@ class RootPage extends GetView { @override Widget build(BuildContext context) { return ObxValue((currentIndex) { - return Scaffold( - body: ObxValue( - (currentIndex) => IndexedStack(index: currentIndex.value, children: controller.pages), - controller.currentIndex, - ), - bottomNavigationBar: RBottomNavigation( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - items: [ - RBottomNavigationItem( - label: 'نقشه', - icon: Assets.vec.mapSvg.path, - isSelected: currentIndex.value == 0, - onTap: () { - Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst); + return PopScope( + canPop: false, + child: Scaffold( + backgroundColor: AppColor.bgLight, + body: IndexedStack(index: currentIndex.value, children: controller.pages), + bottomNavigationBar: RBottomNavigation( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + items: [ + RBottomNavigationItem( + 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: () { + Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst); + controller.changePage(1); + }, + ), - controller.changePage(0); - }, - ), - RBottomNavigationItem( - label: 'اقدام', - icon: Assets.vec.settingSvg.path, - isSelected: currentIndex.value == 1, - onTap: () { - Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst); - controller.changePage(1); - }, - ), + RBottomNavigationItem( + label: 'پروفایل', + icon: Assets.vec.profileCircleSvg.path, + isSelected: currentIndex.value == 2, + onTap: () { + Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst); + Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst); - RBottomNavigationItem( - label: 'پروفایل', - icon: Assets.vec.profileCircleSvg.path, - isSelected: currentIndex.value == 4, - onTap: () { - Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst); - Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst); - - controller.changePage(4); - }, - ), - ], + controller.changePage(2); + }, + ), + ], + ), ), ); }, controller.currentIndex); diff --git a/packages/inspection/lib/presentation/routes/app_pages.dart b/packages/inspection/lib/presentation/routes/app_pages.dart index dcf3ac9..a6cc79a 100644 --- a/packages/inspection/lib/presentation/routes/app_pages.dart +++ b/packages/inspection/lib/presentation/routes/app_pages.dart @@ -6,6 +6,7 @@ import 'package:rasadyar_inspection/presentation/pages/pages.dart'; import 'package:rasadyar_inspection/presentation/pages/users/logic.dart'; import 'package:rasadyar_inspection/presentation/routes/app_routes.dart'; import 'package:rasadyar_inspection/presentation/widget/base_page/logic.dart'; +import 'package:rasadyar_inspection/presentation/widget/captcha/logic.dart'; sealed class InspectionPages { InspectionPages._(); @@ -64,7 +65,10 @@ sealed class InspectionPages { GetPage( name: InspectionRoutes.auth, page: () => AuthPage(), - binding: BindingsBuilder.put(() => AuthLogic()), + binding: BindingsBuilder(() { + Get.lazyPut(() => AuthLogic()); + Get.lazyPut(() =>CaptchaWidgetLogic()); + }), ), ]; } diff --git a/packages/inspection/lib/presentation/widget/captcha/logic.dart b/packages/inspection/lib/presentation/widget/captcha/logic.dart index 1ed9b15..04823a8 100644 --- a/packages/inspection/lib/presentation/widget/captcha/logic.dart +++ b/packages/inspection/lib/presentation/widget/captcha/logic.dart @@ -1,16 +1,14 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; -import 'package:rasadyar_core/data/model/response/captcha/captcha_response_model.dart'; -import 'package:rasadyar_inspection/data/repositories/auth_repository_imp.dart'; +import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart'; +import 'package:rasadyar_inspection/data/repositories/auth/auth_repository_imp.dart'; +import 'package:rasadyar_inspection/injection/inspection_di.dart'; class CaptchaWidgetLogic extends GetxController with StateMixin { TextEditingController textController = TextEditingController(); RxnString captchaKey = RxnString(); GlobalKey formKey = GlobalKey(); - //AuthRepositoryImpl authRepository = .get(); - final Random random = Random(); + AuthRepositoryImpl authRepository = diInspection.get(); @override void onInit() { @@ -29,8 +27,21 @@ class CaptchaWidgetLogic extends GetxController with StateMixin getCaptcha() async { change(null, status: RxStatus.loading()); textController.clear(); - await Future.delayed(Duration(milliseconds: 800)); - captchaKey.value = (random.nextInt(900000) + 100000).toString(); + 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()); } } diff --git a/packages/inspection/lib/presentation/widget/captcha/view.dart b/packages/inspection/lib/presentation/widget/captcha/view.dart index 0bd3523..80278f9 100644 --- a/packages/inspection/lib/presentation/widget/captcha/view.dart +++ b/packages/inspection/lib/presentation/widget/captcha/view.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:math'; import 'package:flutter/cupertino.dart'; @@ -28,12 +29,7 @@ class CaptchaWidget extends GetView { borderRadius: BorderRadius.circular(8), ), child: controller.obx( - (state) => Center( - child: Text( - controller.captchaKey.value ?? 'دوباره سعی کنید', - style: AppFonts.yekan24Bold, - ), - ), + (state) => Image.memory(base64Decode(state?.captchaImage ?? ''), fit: BoxFit.cover), onLoading: const Center( child: CupertinoActivityIndicator(color: AppColor.blueNormal), ), @@ -64,9 +60,6 @@ class CaptchaWidget extends GetView { validator: (value) { if (value == null || value.isEmpty) { return 'کد امنیتی را وارد کنید'; - } else if (controller.captchaKey.value != null && - controller.captchaKey.value != value) { - return 'کد امنیتی اشتباه است'; } return null; }, diff --git a/packages/inspection/pubspec.lock b/packages/inspection/pubspec.lock index 1794b66..b52d807 100644 --- a/packages/inspection/pubspec.lock +++ b/packages/inspection/pubspec.lock @@ -98,7 +98,7 @@ packages: source: hosted version: "3.0.0" build_runner: - dependency: transitive + dependency: "direct dev" description: name: build_runner sha256: b971d4a1c789eba7be3e6fe6ce5e5b50fd3719e3cb485b3fad6d04358304351d @@ -145,6 +145,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" clock: dependency: transitive description: @@ -185,6 +193,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" cross_file: dependency: transitive description: @@ -289,6 +305,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.3" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" ffi: dependency: transitive description: @@ -366,6 +390,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.11.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" flutter_localizations: dependency: transitive description: flutter @@ -475,6 +507,11 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" flutter_web_plugins: dependency: transitive description: flutter @@ -488,8 +525,16 @@ packages: url: "https://pub.dev" source: hosted version: "10.8.0" + freezed: + dependency: "direct dev" + description: + name: freezed + sha256: da32f8ba8cfcd4ec71d9decc8cbf28bd2c31b5283d9887eb51eb4a0659d8110c + url: "https://pub.dev" + source: hosted + version: "3.2.0" freezed_annotation: - dependency: transitive + dependency: "direct main" description: name: freezed_annotation sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" @@ -584,6 +629,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.0.3" + get_test: + dependency: "direct dev" + description: + name: get_test + sha256: "558c39cb35fb37bd501f337dc143de60a4314d5ef3b75f4b0551d6741634995b" + url: "https://pub.dev" + source: hosted + version: "4.0.1" glob: dependency: transitive description: @@ -632,6 +685,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + hive_ce_generator: + dependency: "direct dev" + description: + name: hive_ce_generator + sha256: a169feeff2da9cc2c417ce5ae9bcebf7c8a95d7a700492b276909016ad70a786 + url: "https://pub.dev" + source: hosted + version: "1.9.3" http: dependency: transitive description: @@ -769,13 +830,21 @@ packages: source: hosted version: "0.6.7" json_annotation: - dependency: transitive + dependency: "direct main" description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" url: "https://pub.dev" source: hosted version: "4.9.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: ce2cf974ccdee13be2a510832d7fba0b94b364e0b0395dee42abaa51b855be27 + url: "https://pub.dev" + source: hosted + version: "6.10.0" latlong2: dependency: transitive description: @@ -784,6 +853,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + url: "https://pub.dev" + source: hosted + version: "10.0.9" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + url: "https://pub.dev" + source: hosted + version: "3.0.9" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: "direct dev" + description: + name: lints + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + url: "https://pub.dev" + source: hosted + version: "6.0.0" lists: dependency: transitive description: @@ -856,6 +957,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + mockito: + dependency: transitive + description: + name: mockito + sha256: "2314cbe9165bcd16106513df9cf3c3224713087f09723b128928dc11a4379f99" + url: "https://pub.dev" + source: hosted + version: "5.5.0" + mocktail: + dependency: "direct dev" + description: + name: mocktail + sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" package_config: dependency: transitive description: @@ -1111,6 +1236,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" shelf_web_socket: dependency: transitive description: @@ -1132,6 +1273,38 @@ packages: description: flutter source: sdk version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: fc787b1f89ceac9580c3616f899c9a447413cbdac1df071302127764c023a134 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "4f81479fe5194a622cdd1713fe1ecb683a6e6c85cd8cec8e2e35ee5ab3fdf2a1" + url: "https://pub.dev" + source: hosted + version: "1.3.6" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" source_span: dependency: transitive description: @@ -1188,14 +1361,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.2" + test: + dependency: "direct dev" + description: + name: test + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" + url: "https://pub.dev" + source: hosted + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.4" + test_core: + dependency: transitive + description: + name: test_core + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" + url: "https://pub.dev" + source: hosted + version: "0.6.8" time: dependency: transitive description: @@ -1268,6 +1457,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + url: "https://pub.dev" + source: hosted + version: "15.0.0" watcher: dependency: transitive description: @@ -1300,6 +1497,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" win32: dependency: transitive description: @@ -1348,6 +1553,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.3" + yaml_writer: + dependency: transitive + description: + name: yaml_writer + sha256: "69651cd7238411179ac32079937d4aa9a2970150d6b2ae2c6fe6de09402a5dc5" + url: "https://pub.dev" + source: hosted + version: "2.1.0" sdks: dart: ">=3.8.1 <4.0.0" flutter: ">=3.29.0" diff --git a/packages/inspection/pubspec.yaml b/packages/inspection/pubspec.yaml index aee96aa..0a3d2b2 100644 --- a/packages/inspection/pubspec.yaml +++ b/packages/inspection/pubspec.yaml @@ -11,3 +11,21 @@ dependencies: sdk: flutter rasadyar_core: path: ../core + ##code generation + freezed_annotation: ^3.1.0 + json_annotation: ^4.9.0 +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + lints: ^6.0.0 + test: ^1.25.15 + ##code generation + build_runner: ^2.6.0 + hive_ce_generator: ^1.9.3 + freezed: ^3.2.0 + json_serializable: ^6.10.0 + + ##test + mocktail: ^1.0.4 + get_test: ^4.0.1