From b2d3d601527ad23e6828bc5c724e3cc30ac5d34b Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 20 Aug 2025 11:39:30 +0300 Subject: [PATCH 1/6] logout api added. --- lib/controllers/api_routes/urls.dart | 11 ++++++----- .../providers/api/user_provider.dart | 17 +++++++++++++++++ lib/new_views/common_widgets/app_drawer.dart | 17 ++++++++++------- lib/new_views/pages/land_page/land_page.dart | 9 ++++++--- lib/new_views/swipe_module/swipe_view.dart | 9 ++++++--- 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 336dd7b3..d78b478c 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -3,14 +3,14 @@ class URLs { static const String appReleaseBuildNumber = "22"; - static const host1 = "https://atomsm.hmg.com"; // production url + // static const host1 = "https://atomsm.hmg.com"; // production url // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url - // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url + static const host1 = "https://atomsmuat.hmg.com"; // local UAT url - // static String _baseUrl = "$_host/mobile"; + static String _baseUrl = "$_host/mobile"; // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis // static final String _baseUrl = "$_host/mobile"; // host local UAT - static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM + // static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM static String _host = host1; @@ -21,7 +21,8 @@ class URLs { // static String getFileUrl(String file) => (file == null || file.isEmpty) ? null :1 (file.contains("/") ? file : "$_host/attachment/$file"); // API Routes - static get login => "$_baseUrl/MobileAuth/Login"; // web login + static get login => "$_baseUrl/MobileAuth/Login"; + static get logout => "$_baseUrl/MobileAuth/Logout"; static get checkLoginValidation => "$_baseUrl/Account/Authenticate"; // web login static get checkAppVersion => "$_baseUrl/Account/CheckAppVersion"; // web login //Reset Password Apis... diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index d013651a..a8f0a52c 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -117,6 +117,23 @@ class UserProvider extends ChangeNotifier { } } + Future logout(BuildContext context) async { + Response response; + try { + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + response = await ApiManager.instance.post(URLs.logout, body: {}); + if (response.statusCode >= 200 && response.statusCode < 300) { + Navigator.pop(context); + return true; + } + Navigator.pop(context); + return false; + } catch (error) { + Navigator.pop(context); + return false; + } + } + /// sign up with User object; /// return -2 if request in progress /// return -1 if error happen when sending request diff --git a/lib/new_views/common_widgets/app_drawer.dart b/lib/new_views/common_widgets/app_drawer.dart index 3426a056..093b8de1 100644 --- a/lib/new_views/common_widgets/app_drawer.dart +++ b/lib/new_views/common_widgets/app_drawer.dart @@ -73,8 +73,8 @@ class AppDrawer extends StatelessWidget { // 18.height, drawerItem("setting", context.translation.settings, context).onPress(() => Navigator.of(context).pushNamed(SettingsPage.id)), 18.height, - if(userProvider.user!=null&&userProvider.user?.employeeIsHMG==false) - drawerItem("swipe", "Swipe History", context) .onPress(() => Navigator.of(context).pushNamed(SwipeHistoryView.routeName)), + if (userProvider.user != null && userProvider.user?.employeeIsHMG == false) + drawerItem("swipe", "Swipe History", context).onPress(() => Navigator.of(context).pushNamed(SwipeHistoryView.routeName)), // 18.height, // drawerItem("report", context.translation.reportBg, context) /*.onPress(() => Navigator.of(context).pushNamed(ReportBugPage.id))*/, // 18.height, @@ -87,11 +87,14 @@ class AppDrawer extends StatelessWidget { builder: (_) => AAlertDialog(title: context.translation.signOut, content: context.translation.logoutAlert), ); if (result) { - settingProvider.resetSettings(); - userProvider.reset(); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + bool isSuccess = await userProvider.logout(context); + if (isSuccess) { + settingProvider.resetSettings(); + userProvider.reset(); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + } } }), 18.height, diff --git a/lib/new_views/pages/land_page/land_page.dart b/lib/new_views/pages/land_page/land_page.dart index fee16b45..f9703cfd 100644 --- a/lib/new_views/pages/land_page/land_page.dart +++ b/lib/new_views/pages/land_page/land_page.dart @@ -131,9 +131,12 @@ class _LandPageState extends State { builder: (_) => AAlertDialog(title: context.translation.signOut, content: context.translation.logoutAlert), ); if (result) { - Provider.of(context, listen: false).resetSettings(); - Provider.of(context, listen: false).reset(); - Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + bool isSuccess = await Provider.of(context, listen: false).logout(context); + if (isSuccess) { + Provider.of(context, listen: false).resetSettings(); + Provider.of(context, listen: false).reset(); + Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + } } return false; }, diff --git a/lib/new_views/swipe_module/swipe_view.dart b/lib/new_views/swipe_module/swipe_view.dart index 40eabe46..e6412ea4 100644 --- a/lib/new_views/swipe_module/swipe_view.dart +++ b/lib/new_views/swipe_module/swipe_view.dart @@ -55,9 +55,12 @@ class _SwipeViewState extends State { builder: (_) => AAlertDialog(title: context.translation.signOut, content: context.translation.logoutAlert), ); if (result) { - Provider.of(context, listen: false).resetSettings(); - Provider.of(context, listen: false).reset(); - Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + bool isSuccess = await Provider.of(context, listen: false).logout(context); + if (isSuccess) { + Provider.of(context, listen: false).resetSettings(); + Provider.of(context, listen: false).reset(); + Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + } } return false; }, From 04da46c4bbaf26cba69e766ec3d7bc6a721eaa05 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 20 Aug 2025 14:54:32 +0300 Subject: [PATCH 2/6] 1.3.7+26 uploaded. --- lib/controllers/api_routes/urls.dart | 10 +++++----- pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index d78b478c..bb4911f1 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -1,16 +1,16 @@ class URLs { URLs._(); - static const String appReleaseBuildNumber = "22"; + static const String appReleaseBuildNumber = "23"; - // static const host1 = "https://atomsm.hmg.com"; // production url + static const host1 = "https://atomsm.hmg.com"; // production url // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url - static const host1 = "https://atomsmuat.hmg.com"; // local UAT url + // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url - static String _baseUrl = "$_host/mobile"; + // static String _baseUrl = "$_host/mobile"; // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis // static final String _baseUrl = "$_host/mobile"; // host local UAT - // static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM + static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM static String _host = host1; diff --git a/pubspec.yaml b/pubspec.yaml index a562ad1d..e7b9aadf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.3.6+25 +version: 1.3.7+26 environment: sdk: ">=3.5.0 <4.0.0" From 187bf717edac5738c8e19eb42abe0f668cddd141 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 20 Aug 2025 15:04:44 +0300 Subject: [PATCH 3/6] 1.3.7+26 uploaded - changes --- android/key.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/key.properties b/android/key.properties index 9cd1c57c..fae5f053 100644 --- a/android/key.properties +++ b/android/key.properties @@ -2,4 +2,4 @@ storePassword=Cloud@AtomsSA keyPassword=Cloud@AtomsSA keyAlias=playstore #storeFile=/Users/sikandersaleem/StudioProjects/cloudsolutions-atoms/android/AtomsSA-playStore.jks -storeFile=AtomsSA-playStore.jks +storeFile=../AtomsSA-playStore.jks From 6c3f36944a645e499c900c5eeb04dd4dbfe08d88 Mon Sep 17 00:00:00 2001 From: waseemabbasi22 Date: Wed, 27 Aug 2025 09:23:24 +0300 Subject: [PATCH 4/6] auth and attachment fixes --- lib/controllers/api_routes/urls.dart | 10 +++--- .../providers/api/user_provider.dart | 35 +++++++++++++++++++ .../providers/settings/setting_provider.dart | 16 +++++++++ lib/dashboard_latest/dashboard_view.dart | 2 +- lib/models/user.dart | 17 ++++++++- lib/new_views/pages/login_page.dart | 11 +++++- lib/new_views/pages/settings_page.dart | 1 + lib/new_views/pages/splash_page.dart | 15 ++++++-- .../widgets/images/multi_image_picker.dart | 9 ++--- 9 files changed, 103 insertions(+), 13 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index bb4911f1..11a2ecc0 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -3,14 +3,14 @@ class URLs { static const String appReleaseBuildNumber = "23"; - static const host1 = "https://atomsm.hmg.com"; // production url + // static const host1 = "https://atomsm.hmg.com"; // production url // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url - // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url + static const host1 = "https://atomsmuat.hmg.com"; // local UAT url // static String _baseUrl = "$_host/mobile"; // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis - // static final String _baseUrl = "$_host/mobile"; // host local UAT - static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM + static final String _baseUrl = "$_host/mobile"; // host local UAT + // static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM static String _host = host1; @@ -22,7 +22,9 @@ class URLs { // API Routes static get login => "$_baseUrl/MobileAuth/Login"; + static get getUserInfo => "$_baseUrl/MobileAuth/GetUserInfo"; static get logout => "$_baseUrl/MobileAuth/Logout"; + static get enableFaceId => "$_baseUrl/MobileAuth/EnabledFaceId"; static get checkLoginValidation => "$_baseUrl/Account/Authenticate"; // web login static get checkAppVersion => "$_baseUrl/Account/CheckAppVersion"; // web login //Reset Password Apis... diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index a8f0a52c..94813149 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -32,6 +32,10 @@ class UserProvider extends ChangeNotifier { User? get user => _user; + User? _refreshedUser; + + User? get refreshedUser => _refreshedUser; + File? profileImage; VerifyOtpModel _verifyOtpModel = VerifyOtpModel(); @@ -117,6 +121,37 @@ class UserProvider extends ChangeNotifier { } } + + Future getUserInfo({ String? fireBaseToken}) async { + // if (_loading == true) return false; + // _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.post(URLs.getUserInfo,body: { + 'fireBaseToken':fireBaseToken, + }); + // _loading = false; + if (response.statusCode >= 200 && response.statusCode < 300) { + _refreshedUser = await User.fromJson(jsonDecode(response.body)); + _refreshedUser!.profilePhotoName = URLs.getFileUrl(_user!.profilePhotoName); + notifyListeners(); + if (response.statusCode == 200) { + return true; + } + } + notifyListeners(); + return false; + } catch (error) { + print('SSL or Network Error: $error'); + // _loading = false; + notifyListeners(); + return false; + } + } + + + Future logout(BuildContext context) async { Response response; try { diff --git a/lib/controllers/providers/settings/setting_provider.dart b/lib/controllers/providers/settings/setting_provider.dart index 6e1a1e87..2ca13b42 100644 --- a/lib/controllers/providers/settings/setting_provider.dart +++ b/lib/controllers/providers/settings/setting_provider.dart @@ -178,6 +178,22 @@ class SettingProvider extends ChangeNotifier { } } + + Future checkIsEnabledFaceId({required bool status}) async { + try { + final response = await ApiManager.instance.post( + URLs.enableFaceId, + body: { + 'isEnabled':status, + }, + ); + return response.statusCode >= 200 && response.statusCode < 300; + } catch (error) { + return false; + } + } + + Future checkAppUpdate(String buildNumber, String osType) async { Response response; bool isValid = false; diff --git a/lib/dashboard_latest/dashboard_view.dart b/lib/dashboard_latest/dashboard_view.dart index 149a9e24..3e399e41 100644 --- a/lib/dashboard_latest/dashboard_view.dart +++ b/lib/dashboard_latest/dashboard_view.dart @@ -103,7 +103,7 @@ class _DashboardViewState extends State { @override Widget build(BuildContext context) { - bool isNurse = (Provider.of(context, listen: false).user!.type) == UsersTypes.normal_user; + bool isNurse = (Provider.of(context, listen: false).user?.type) == UsersTypes.normal_user; final user = Provider.of(context, listen: false).user; return Stack( children: [ diff --git a/lib/models/user.dart b/lib/models/user.dart index 75045ac0..a1ed40b0 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -42,6 +42,7 @@ class User { bool? enableWifi; bool? enableNFC; bool? enableQR; + bool? isEnabledFaceId; bool? onlySwipe; User({ @@ -79,6 +80,7 @@ class User { this.enableNFC, this.enableQR, this.enableWifi, + this.isEnabledFaceId, this.onlySwipe, }); @@ -86,9 +88,12 @@ class User { Future> toLoginJson() async { String notificationType = (Platform.isAndroid && !(await FirebaseNotificationManger.isGoogleServicesAvailable())) ? "HMC" : "FCM"; + if(FirebaseNotificationManger.token==null){ + //calling this agin to check for token as sometimes token is null fresh install.. + await FirebaseNotificationManger.getToken(); + } return {"username": userName, "password": password, "fireBaseToken": FirebaseNotificationManger?.token ?? "", "notificationType": notificationType}; } - UsersTypes? get type { switch (userRoles?.first.value) { case "R-6": @@ -167,6 +172,7 @@ class User { map['enableNFC'] = enableNFC; map['enableQR'] = enableQR; map['onlySwipe'] = onlySwipe; + map['isEnabledFaceId'] = isEnabledFaceId; return map; } @@ -233,6 +239,7 @@ class User { enableNFC = json['enableNFC']; enableQR = json['enableQR']; onlySwipe = json['onlySwipe']; + isEnabledFaceId = json['isEnabledFaceId']; } } @@ -300,6 +307,14 @@ class AssetGroup { data['enabledEngineerTimer'] = enabledEngineerTimer; return data; } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is AssetGroup && runtimeType == other.runtimeType && id == other.id; + + @override + int get hashCode => id.hashCode; } class UserContactInfoModel { diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index 304daf92..1cc6905f 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -233,8 +233,17 @@ class _LoginPageState extends State { int status = await _userProvider.login(context: context, user: _user); if (status >= 200 && status < 300 && _userProvider.user!.isAuthenticated! ?? false) { await _settingProvider!.setUser(_userProvider.user!); - (await SharedPreferences.getInstance()).remove(ASettings.localAuth); + + // (await SharedPreferences.getInstance()).remove(ASettings.localAuth); await _settingProvider!.setRememberMe(_user.userName!, _user.password!, rememberMe); + //TODO need to verify this here... + if(_userProvider.user?.isEnabledFaceId==true){ + await _settingProvider!.setAuth(_userProvider.user!.isEnabledFaceId!); + }else{ + (await SharedPreferences.getInstance()).remove(ASettings.localAuth); + } + + Navigator.pushReplacementNamed(context, LandPage.routeName); } else { Fluttertoast.showToast(msg: _userProvider.user?.message ?? context.translation.failedToCompleteRequest); diff --git a/lib/new_views/pages/settings_page.dart b/lib/new_views/pages/settings_page.dart index 3cdaad4b..5e6e162d 100644 --- a/lib/new_views/pages/settings_page.dart +++ b/lib/new_views/pages/settings_page.dart @@ -51,6 +51,7 @@ class _SettingsPageState extends State { if (authStatus) { localAuth = !localAuth; await _settingProvider!.setAuth(localAuth); + await _settingProvider!.checkIsEnabledFaceId(status: localAuth); // authController.value = _settingProvider.localAuth == buttonState.toString(); setState(() {}); } else { diff --git a/lib/new_views/pages/splash_page.dart b/lib/new_views/pages/splash_page.dart index ec2bfe10..2823fdef 100644 --- a/lib/new_views/pages/splash_page.dart +++ b/lib/new_views/pages/splash_page.dart @@ -1,6 +1,8 @@ +import 'dart:developer'; import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flare_flutter/flare_actor.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -40,6 +42,7 @@ class _SplashPageState extends State { @override void initState() { Firebase.initializeApp(); + // NotificationManger.initialisation((notificationDetails) { // // todo @sikander, check notifications payload, because notification model is different to need to check from backend // // SystemNotificationModel notification = SystemNotificationModel.fromJson(json.decode(notificationDetails.payload)); @@ -116,8 +119,16 @@ class _SplashPageState extends State { } if (isSuccess) { - _userProvider.setUser(_settingProvider.user!); - + _userProvider.setUser(_settingProvider.user!); + if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); + await _userProvider.getUserInfo(fireBaseToken:FirebaseNotificationManger.token).then((status) async{ + if(status&&_userProvider.refreshedUser!=null){ + _userProvider.refreshedUser!.token = _settingProvider.user?.token; + await _settingProvider.setUser(_userProvider.refreshedUser!); + _userProvider.setUser(_settingProvider.user!); + await _settingProvider.setAuth(_settingProvider.user?.isEnabledFaceId??false); + } + }); if (_userProvider.user!.onlySwipe!) { Navigator.of(context).pushNamedAndRemoveUntil(SwipeView.routeName, (routes) => true); } else { diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart index 470471a1..1bddd87e 100644 --- a/lib/views/widgets/images/multi_image_picker.dart +++ b/lib/views/widgets/images/multi_image_picker.dart @@ -475,10 +475,11 @@ class _AttachmentPickerState extends State { } onFilePicker() async { - if (widget.attachment.length >= 5) { - Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); - return; - } + //TODO removed on request by Backend as they don't have anyissue with large number of files + // if (widget.attachment.length >= 5) { + // Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); + // return; + // } ImageSource? source = await showModalBottomSheet( context: context, builder: (BuildContext context) { From 642d1a908c3f65589ae710ade09c8cd8f889c06f Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 31 Aug 2025 17:39:47 +0300 Subject: [PATCH 5/6] auto login improvement. --- .../providers/api/user_provider.dart | 20 +- .../providers/settings/setting_provider.dart | 1 + lib/main.dart | 2 +- lib/new_views/pages/login_page.dart | 14 +- lib/new_views/pages/splash_page.dart | 51 +- .../requests/create_service_request_page.dart | 814 +++++++++--------- .../widgets/images/multi_image_picker.dart | 554 ++++++------ 7 files changed, 731 insertions(+), 725 deletions(-) diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index 94813149..afc67620 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -121,37 +121,23 @@ class UserProvider extends ChangeNotifier { } } - - Future getUserInfo({ String? fireBaseToken}) async { - // if (_loading == true) return false; - // _loading = true; - notifyListeners(); + Future getUserInfo({String? fireBaseToken}) async { Response response; try { - response = await ApiManager.instance.post(URLs.getUserInfo,body: { - 'fireBaseToken':fireBaseToken, - }); - // _loading = false; + response = await ApiManager.instance.post(URLs.getUserInfo, body: {'fireBaseToken': fireBaseToken}); if (response.statusCode >= 200 && response.statusCode < 300) { _refreshedUser = await User.fromJson(jsonDecode(response.body)); - _refreshedUser!.profilePhotoName = URLs.getFileUrl(_user!.profilePhotoName); - notifyListeners(); + _refreshedUser!.profilePhotoName = URLs.getFileUrl(_refreshedUser!.profilePhotoName); if (response.statusCode == 200) { return true; } } - notifyListeners(); return false; } catch (error) { - print('SSL or Network Error: $error'); - // _loading = false; - notifyListeners(); return false; } } - - Future logout(BuildContext context) async { Response response; try { diff --git a/lib/controllers/providers/settings/setting_provider.dart b/lib/controllers/providers/settings/setting_provider.dart index 2ca13b42..3ff7aabe 100644 --- a/lib/controllers/providers/settings/setting_provider.dart +++ b/lib/controllers/providers/settings/setting_provider.dart @@ -183,6 +183,7 @@ class SettingProvider extends ChangeNotifier { try { final response = await ApiManager.instance.post( URLs.enableFaceId, + showToast: false, body: { 'isEnabled':status, }, diff --git a/lib/main.dart b/lib/main.dart index 88c7bdef..55a3d79a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -312,7 +312,7 @@ class MyApp extends StatelessWidget { //ReportIssuesPage.id: (_) => ReportIssuesPage(), RequestGasRefill.id: (_) => const RequestGasRefill(), UpdateGasRefillRequest.id: (_) => const UpdateGasRefillRequest(), - CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(), + // CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(), CreateNewRequest.id: (_) => const CreateNewRequest(), // SingleHospitalPicker.id: (_) => SingleHospitalPicker(), MyAssetsPage.id: (_) => const MyAssetsPage(), diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index 1cc6905f..35eb9134 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -110,8 +110,8 @@ class _LoginPageState extends State { backgroundColor: AppColor.fieldBgColor(context), validator: (value) => Validator.hasValue(value!) ? null : context.translation.requiredField, labelText: context.translation.username, - style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color:context .isDark?Colors.white: const Color(0xff3B3D4A)), - labelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 11, color:context .isDark?Colors.white:const Color(0xff767676)), + style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: context.isDark ? Colors.white : const Color(0xff3B3D4A)), + labelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 11, color: context.isDark ? Colors.white : const Color(0xff767676)), textInputType: TextInputType.text, showWithoutDecoration: true, contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 12.toScreenHeight), @@ -125,8 +125,8 @@ class _LoginPageState extends State { showWithoutDecoration: true, labelText: context.translation.password, backgroundColor: AppColor.fieldBgColor(context), - style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: context .isDark?Colors.white: const Color(0xff3B3D4A)), - labelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 11, color: context .isDark?Colors.white: const Color(0xff767676)), + style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: context.isDark ? Colors.white : const Color(0xff3B3D4A)), + labelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 11, color: context.isDark ? Colors.white : const Color(0xff767676)), contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 12.toScreenHeight), obscureText: !_passwordVisible, suffixIcon: Icon( @@ -237,13 +237,11 @@ class _LoginPageState extends State { // (await SharedPreferences.getInstance()).remove(ASettings.localAuth); await _settingProvider!.setRememberMe(_user.userName!, _user.password!, rememberMe); //TODO need to verify this here... - if(_userProvider.user?.isEnabledFaceId==true){ + if (_userProvider.user?.isEnabledFaceId == true) { await _settingProvider!.setAuth(_userProvider.user!.isEnabledFaceId!); - }else{ + } else { (await SharedPreferences.getInstance()).remove(ASettings.localAuth); } - - Navigator.pushReplacementNamed(context, LandPage.routeName); } else { Fluttertoast.showToast(msg: _userProvider.user?.message ?? context.translation.failedToCompleteRequest); diff --git a/lib/new_views/pages/splash_page.dart b/lib/new_views/pages/splash_page.dart index 2823fdef..f3954a99 100644 --- a/lib/new_views/pages/splash_page.dart +++ b/lib/new_views/pages/splash_page.dart @@ -9,11 +9,13 @@ import 'package:flutter/material.dart'; import 'package:local_auth/local_auth.dart'; import 'package:provider/provider.dart'; import 'package:safe_device/safe_device.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; import 'package:test_sa/new_views/pages/login_page.dart'; import 'package:test_sa/new_views/pages/unsafe_device_view.dart'; @@ -88,6 +90,7 @@ class _SplashPageState extends State { setState(() { loading = false; }); + if (isValid == false) { showDialog( context: context, @@ -101,11 +104,28 @@ class _SplashPageState extends State { }), ); } else { - if (isValid && _settingProvider.isLocalAuthEnable) { - handleLocalAuth(); - return; - } - Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + ApiManager.instance.user = _settingProvider.user!; + + if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); + setState(() { + loading = true; + }); + await _userProvider.getUserInfo(fireBaseToken: FirebaseNotificationManger.token).then((status) async { + setState(() { + loading = false; + }); + if (status && _userProvider.refreshedUser != null) { + _userProvider.refreshedUser!.token = _settingProvider.user?.token; + await _settingProvider.setUser(_userProvider.refreshedUser!); + _userProvider.setUser(_userProvider.refreshedUser!); + await _settingProvider.setAuth(_settingProvider.user?.isEnabledFaceId ?? false); + } + if (_settingProvider.isLocalAuthEnable) { + handleLocalAuth(); + return; + } + Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + }); } } } @@ -119,16 +139,17 @@ class _SplashPageState extends State { } if (isSuccess) { - _userProvider.setUser(_settingProvider.user!); - if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); - await _userProvider.getUserInfo(fireBaseToken:FirebaseNotificationManger.token).then((status) async{ - if(status&&_userProvider.refreshedUser!=null){ - _userProvider.refreshedUser!.token = _settingProvider.user?.token; - await _settingProvider.setUser(_userProvider.refreshedUser!); - _userProvider.setUser(_settingProvider.user!); - await _settingProvider.setAuth(_settingProvider.user?.isEnabledFaceId??false); - } - }); + // _userProvider.setUser(_settingProvider.user!); + // if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); + // await _userProvider.getUserInfo(fireBaseToken: FirebaseNotificationManger.token).then((status) async { + // if (status && _userProvider.refreshedUser != null) { + // _userProvider.refreshedUser!.token = _settingProvider.user?.token; + // await _settingProvider.setUser(_userProvider.refreshedUser!); + // _userProvider.setUser(_settingProvider.user!); + // await _settingProvider.setAuth(_settingProvider.user?.isEnabledFaceId ?? false); + // } + // }); + if (_userProvider.user!.onlySwipe!) { Navigator.of(context).pushNamedAndRemoveUntil(SwipeView.routeName, (routes) => true); } else { diff --git a/lib/views/pages/user/requests/create_service_request_page.dart b/lib/views/pages/user/requests/create_service_request_page.dart index 4bc0ef98..9fc69f4b 100644 --- a/lib/views/pages/user/requests/create_service_request_page.dart +++ b/lib/views/pages/user/requests/create_service_request_page.dart @@ -1,407 +1,407 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; -import 'package:test_sa/controllers/providers/api/user_provider.dart'; -import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; -import 'package:test_sa/extensions/context_extension.dart'; -import 'package:test_sa/extensions/int_extensions.dart'; -import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/generic_attachment_model.dart'; -import 'package:test_sa/models/service_request/pending_service_request_model.dart'; -import 'package:test_sa/models/service_request/service_request.dart'; -import 'package:test_sa/modules/cm_module/utilities/service_request_utils.dart'; -import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; -import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart'; -import 'package:test_sa/providers/service_request_providers/requested_through_provider.dart'; -import 'package:test_sa/views/pages/user/requests/pending_requests_screen.dart'; -import 'package:test_sa/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart'; -import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; -import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; -import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; -import 'package:test_sa/views/widgets/sound/TextSpeechRecordWidget.dart'; - -import '../../../../new_views/app_style/app_color.dart'; -import '../../../../new_views/common_widgets/default_app_bar.dart'; -import '../../../../providers/service_request_providers/priority_provider.dart'; -import '../../../../providers/service_request_providers/type_of_request_provider.dart'; - -class CreateServiceRequestPage extends StatefulWidget { - static const String id = "/create-request"; - final ServiceRequest? serviceRequest; - - const CreateServiceRequestPage({this.serviceRequest, Key? key}) : super(key: key); - - @override - CreateServiceRequestPageState createState() => CreateServiceRequestPageState(); -} - -class CreateServiceRequestPageState extends State { - late TextEditingController _commentController; - - late double _height; - late UserProvider _userProvider; - late SettingProvider _settingProvider; - late ServiceRequestsProvider _serviceRequestsProvider; - late ServiceRequest _serviceRequest; - final List attachments = []; - final bool _isLoading = false; - bool _showDatePicker = false; - final GlobalKey _formKey = GlobalKey(); - final GlobalKey _scaffoldKey = GlobalKey(); - DateTime? _dateTime; - - bool isFirstActionSubmitted = false; - - @override - void initState() { - _commentController = TextEditingController(); - if (widget.serviceRequest != null) { - _serviceRequest = widget.serviceRequest!; - attachments.addAll(_serviceRequest.devicePhotos!.map((e) => GenericAttachmentModel(name: e)).toList()); - _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction?.name == "Need a visit"; - if (_showDatePicker && _serviceRequest.visitDate != null) { - _dateTime = DateTime.tryParse(_serviceRequest.visitDate!); - } - } else { - _serviceRequest = ServiceRequest(); - } - isFirstActionSubmitted = _serviceRequest.firstAction != null; - super.initState(); - } - - // - // getServiceRequestById(String id) async { - // try { - // ServiceRequest request = await _serviceRequestsProvider.getServiceRequestObjectById(requestId: id) ?? ""; - // _serviceRequest = request; - // _device = _serviceRequest.device; - // attachments.addAll(_serviceRequest.devicePhotos.map((e) { - // return File(e); - // }).toList()); - // _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; - // if (_showDatePicker && _serviceRequest.visitDate != null) { - // _dateTime = DateTime.tryParse(_serviceRequest.visitDate); - // } - // _isLoading = false; - // } catch (ex) { - // _isLoading = false; - // } - // setState(() {}); - // } - - @override - void dispose() { - _commentController.dispose(); - super.dispose(); - } - - bool _isLocalUrl(String url) { - if (url.isEmpty != false) return false; - return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); - } - - // bool priority; - - void getData() { - Provider.of(context).getDate(); - Provider.of(context).getDate(); - Provider.of(context).getDate(); - Provider.of(context).getDate(); - } - - PendingAssetServiceRequest? pendingAssetServiceRequest; - - @override - Widget build(BuildContext context) { - _height = MediaQuery.of(context).size.height; - _userProvider = Provider.of(context); - - _serviceRequestsProvider = Provider.of(context); - - return Scaffold( - key: _scaffoldKey, - appBar: DefaultAppBar(title: context.translation.newServiceRequest), - body: SafeArea( - child: LoadingManager( - isLoading: _isLoading, - isFailedLoading: false, - stateCode: 200, - onRefresh: () async {}, - child: Form( - key: _formKey, - child: Column( - children: [ - SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - AssetPicker( - device: _serviceRequest.device, - showLoading: checkPendingRequest, - onPick: (asset) async { - pendingAssetServiceRequest = null; - _serviceRequest.device = asset; - await checkAssetForPendingServiceRequest(asset.id!.toInt()); - - if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { - showPendingRequestBottomSheet(); - } - }, - ), - if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[ - 8.height, - Row( - children: [ - const Icon(Icons.warning, color: Color(0xffEE404C), size: 14), - 8.width, - Text( - "This asset already have ${pendingAssetServiceRequest!.details!.length} request pending", - style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline), - ).expanded, - ], - ).onPress(() { - showPendingRequests(); - }), - ], - 16.height, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(context.translation.priority, style: Theme.of(context).textTheme.bodyLarge), - Consumer(builder: (cxt, snapshot, _) { - _serviceRequest.priority ??= snapshot.items.firstWhere((element) => element.value == 0, orElse: null); - - return Transform.scale( - scale: 0.8, - child: CupertinoSwitch( - thumbColor: _serviceRequest.priority?.value != 0 ? const Color(0xffF63939) : Colors.blueGrey.withOpacity(.5), - activeColor: AppColor.blueStatus(context).withOpacity(.25), - value: _serviceRequest.priority?.value != 0, - onChanged: (state) { - if (state) { - _serviceRequest.priority = snapshot.items.firstWhere((element) => element.value == 1, orElse: null); - } else { - _serviceRequest.priority = snapshot.items.firstWhere((element) => element.value == 0, orElse: null); - } - setState(() {}); - }).toShimmer(isShow: snapshot.loading,context: context), - ); - }), - ], - ), - 16.height, - Consumer(builder: (cxt, snapshot, _) { - try { - _serviceRequest.defectType ??= snapshot.items.first; - } catch (ex) { - print("snapshot.items:${snapshot.items.length}"); - } - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text(context.translation.equipmentStatus, style: Theme.of(context).textTheme.bodyLarge), - 8.height, - Wrap( - runSpacing: 8, - spacing: 8, - children: [ - for (var element in snapshot.items) - Row( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: 24, - height: 24, - child: Radio( - value: element, - activeColor: Colors.red, - fillColor: WidgetStateColor.resolveWith((states) { - if (states.contains(WidgetState.selected)) return const Color(0xff3DA5E5); - return const Color(0xffE0E0E0); - }), - groupValue: _serviceRequest.defectType, - onChanged: (state) { - setState(() { - _serviceRequest.defectType = element; - }); - }), - ), - 8.width, - Text(element.name!, style: Theme.of(context).textTheme.bodySmall), - ], - ) - ], - ).toShimmer(isShow: snapshot.loading,context: context), - ], - ); - }), - 16.height, - AttachmentPicker(label: context.translation.attachImage, attachment: attachments, showAsGrid: true), - ], - ).toShadowContainer(context), - - // SingleItemDropDownMenu( - // context: context, - // title: context.translation.priority, - // initialValue: _serviceRequest?.priority, - // onSelect: (value) { - // _serviceRequest.priority = value; - // }, - // ), - // 8.height, - // SingleItemDropDownMenu( - // context: context, - // title: context.translation.equipmentStatus, - // initialValue: _serviceRequest?.defectType, - // onSelect: (value) { - // _serviceRequest.defectType = value; - // }, - // ), - - // Consumer(builder: (context, snapshot, _) { - // return SingleItemDropDownMenu( - // context: context, - // enabled: false, - // title: context.translation.source, - // initialValue: snapshot.items?.firstWhere((element) => element.value == 3, orElse: null), - // ); - // }), - // 8.height, - // Consumer(builder: (context, snapshot, _) { - // return SingleItemDropDownMenu( - // context: context, - // title: context.translation.requestType, - // enabled: false, - // initialValue: snapshot.items?.firstWhere((element) => element.value == 1, orElse: null), - // // onSelect: (value) { - // // _serviceRequest.type = value; - // // }, - // ); - // }), - - // Align( - // alignment: AlignmentDirectional.centerStart, - // child: context.translation.callComments.heading5(context), - // ), - 8.height, - // SpeechToTextButton( - // controller: _commentController, - // ), - // 8.height, - // AppTextFormField( - // controller: _commentController, - // labelText: context.translation.problemDesc, - // suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16), - // initialValue: _serviceRequest.callComments, - // onSaved: (text) { - // _serviceRequest.callComments = text; - // }, - // ), - // 8.height, - // RecordSound( - // onRecord: (audio) { - // _serviceRequest.audio = audio; - // }, - // enabled: widget.serviceRequest == null ? true : false, - // ), - 8.height, - TextSpeechRecordWidget( - initialMessage: _serviceRequest.callComments!, - onMessageChange: (message) { - _serviceRequest.callComments = message; - }, - onRecord: (audio) { - _serviceRequest.audio = audio; - }, - enabled: widget.serviceRequest == null ? true : false, - ), - 16.height, - ], - ), - ).expanded, - AppFilledButton( - onPressed: checkPendingRequest ? null : _submit, - loading: checkPendingRequest, - label: (pendingAssetServiceRequest != null && (pendingAssetServiceRequest!.details?.isNotEmpty ?? false)) ? "Submit Duplicate Request" : "Submit New Request", - ), - ], - ), - ).paddingOnly(start: 16, end: 16, bottom: 24, top: 16), - ), - ), - ); - } - - bool checkPendingRequest = false; - - void showPendingRequests() { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => PendingServiceRequestScreen(pendingAssetServiceRequest!))); - } - - void showPendingRequestBottomSheet() async { - bool view = (await showModalBottomSheet( - context: context, - isDismissible: false, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - clipBehavior: Clip.antiAliasWithSaveLayer, - builder: (BuildContext context) => PendingRequestBottomSheet(pendingAssetServiceRequest!, _serviceRequest.device!), - )) as bool; - if (view) { - showPendingRequests(); - } - } - - Future checkAssetForPendingServiceRequest(int assetId) async { - checkPendingRequest = true; - setState(() {}); - - pendingAssetServiceRequest = await _serviceRequestsProvider.checkAssetPendingRequest(assetId); - await Future.delayed(const Duration(milliseconds: 250)); - - checkPendingRequest = false; - setState(() {}); - } - - Future _submit() async { - _serviceRequest.requestedThrough = Provider.of(context, listen: false).items.firstWhere((element) => element.value == 3, orElse: null); - _serviceRequest.type = Provider.of(context, listen: false).items.firstWhere((element) => element.value == 1, orElse: null); - - if (_formKey.currentState!.validate() && await _serviceRequest.validateNewRequest(context)) { - _formKey.currentState!.save(); - - // bool canSubmitRequest = await checkAssetForPendingServiceRequest(_serviceRequest.device.id); - // if (!canSubmitRequest) { - // return; - // } - - - _serviceRequest.devicePhotos = attachments.map((item) => ServiceRequestUtils.isLocalUrl(item.name??'') ? "${item.name?.split("/").last}|${base64Encode(File(item.name??'').readAsBytesSync())}" : item.name??'').toList(); - if (_serviceRequest.audio != null) { - if (_isLocalUrl(_serviceRequest.audio!)) { - final File file = File(_serviceRequest.audio!); - _serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; - } - } - await _serviceRequestsProvider.createRequest( - context: context, - user: _userProvider.user!, - host: _settingProvider.host!, - serviceRequest: _serviceRequest, - ); - } - } -} +// import 'dart:convert'; +// import 'dart:io'; +// +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter/material.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +// import 'package:test_sa/controllers/providers/api/user_provider.dart'; +// import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +// import 'package:test_sa/extensions/context_extension.dart'; +// import 'package:test_sa/extensions/int_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/models/generic_attachment_model.dart'; +// import 'package:test_sa/models/service_request/pending_service_request_model.dart'; +// import 'package:test_sa/models/service_request/service_request.dart'; +// import 'package:test_sa/modules/cm_module/utilities/service_request_utils.dart'; +// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +// import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart'; +// import 'package:test_sa/providers/service_request_providers/requested_through_provider.dart'; +// import 'package:test_sa/views/pages/user/requests/pending_requests_screen.dart'; +// import 'package:test_sa/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart'; +// import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; +// import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +// import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +// import 'package:test_sa/views/widgets/sound/TextSpeechRecordWidget.dart'; +// +// import '../../../../new_views/app_style/app_color.dart'; +// import '../../../../new_views/common_widgets/default_app_bar.dart'; +// import '../../../../providers/service_request_providers/priority_provider.dart'; +// import '../../../../providers/service_request_providers/type_of_request_provider.dart'; +// +// class CreateServiceRequestPage extends StatefulWidget { +// static const String id = "/create-request"; +// final ServiceRequest? serviceRequest; +// +// const CreateServiceRequestPage({this.serviceRequest, Key? key}) : super(key: key); +// +// @override +// CreateServiceRequestPageState createState() => CreateServiceRequestPageState(); +// } +// +// class CreateServiceRequestPageState extends State { +// late TextEditingController _commentController; +// +// late double _height; +// late UserProvider _userProvider; +// late SettingProvider _settingProvider; +// late ServiceRequestsProvider _serviceRequestsProvider; +// late ServiceRequest _serviceRequest; +// final List attachments = []; +// final bool _isLoading = false; +// bool _showDatePicker = false; +// final GlobalKey _formKey = GlobalKey(); +// final GlobalKey _scaffoldKey = GlobalKey(); +// DateTime? _dateTime; +// +// bool isFirstActionSubmitted = false; +// +// @override +// void initState() { +// _commentController = TextEditingController(); +// if (widget.serviceRequest != null) { +// _serviceRequest = widget.serviceRequest!; +// attachments.addAll(_serviceRequest.devicePhotos!.map((e) => GenericAttachmentModel(name: e)).toList()); +// _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction?.name == "Need a visit"; +// if (_showDatePicker && _serviceRequest.visitDate != null) { +// _dateTime = DateTime.tryParse(_serviceRequest.visitDate!); +// } +// } else { +// _serviceRequest = ServiceRequest(); +// } +// isFirstActionSubmitted = _serviceRequest.firstAction != null; +// super.initState(); +// } +// +// // +// // getServiceRequestById(String id) async { +// // try { +// // ServiceRequest request = await _serviceRequestsProvider.getServiceRequestObjectById(requestId: id) ?? ""; +// // _serviceRequest = request; +// // _device = _serviceRequest.device; +// // attachments.addAll(_serviceRequest.devicePhotos.map((e) { +// // return File(e); +// // }).toList()); +// // _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; +// // if (_showDatePicker && _serviceRequest.visitDate != null) { +// // _dateTime = DateTime.tryParse(_serviceRequest.visitDate); +// // } +// // _isLoading = false; +// // } catch (ex) { +// // _isLoading = false; +// // } +// // setState(() {}); +// // } +// +// @override +// void dispose() { +// _commentController.dispose(); +// super.dispose(); +// } +// +// bool _isLocalUrl(String url) { +// if (url.isEmpty != false) return false; +// return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); +// } +// +// // bool priority; +// +// void getData() { +// Provider.of(context).getDate(); +// Provider.of(context).getDate(); +// Provider.of(context).getDate(); +// Provider.of(context).getDate(); +// } +// +// PendingAssetServiceRequest? pendingAssetServiceRequest; +// +// @override +// Widget build(BuildContext context) { +// _height = MediaQuery.of(context).size.height; +// _userProvider = Provider.of(context); +// +// _serviceRequestsProvider = Provider.of(context); +// +// return Scaffold( +// key: _scaffoldKey, +// appBar: DefaultAppBar(title: context.translation.newServiceRequest), +// body: SafeArea( +// child: LoadingManager( +// isLoading: _isLoading, +// isFailedLoading: false, +// stateCode: 200, +// onRefresh: () async {}, +// child: Form( +// key: _formKey, +// child: Column( +// children: [ +// SingleChildScrollView( +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisSize: MainAxisSize.min, +// children: [ +// AssetPicker( +// device: _serviceRequest.device, +// showLoading: checkPendingRequest, +// onPick: (asset) async { +// pendingAssetServiceRequest = null; +// _serviceRequest.device = asset; +// await checkAssetForPendingServiceRequest(asset.id!.toInt()); +// +// if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { +// showPendingRequestBottomSheet(); +// } +// }, +// ), +// if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[ +// 8.height, +// Row( +// children: [ +// const Icon(Icons.warning, color: Color(0xffEE404C), size: 14), +// 8.width, +// Text( +// "This asset already have ${pendingAssetServiceRequest!.details!.length} request pending", +// style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline), +// ).expanded, +// ], +// ).onPress(() { +// showPendingRequests(); +// }), +// ], +// 16.height, +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text(context.translation.priority, style: Theme.of(context).textTheme.bodyLarge), +// Consumer(builder: (cxt, snapshot, _) { +// _serviceRequest.priority ??= snapshot.items.firstWhere((element) => element.value == 0, orElse: null); +// +// return Transform.scale( +// scale: 0.8, +// child: CupertinoSwitch( +// thumbColor: _serviceRequest.priority?.value != 0 ? const Color(0xffF63939) : Colors.blueGrey.withOpacity(.5), +// activeColor: AppColor.blueStatus(context).withOpacity(.25), +// value: _serviceRequest.priority?.value != 0, +// onChanged: (state) { +// if (state) { +// _serviceRequest.priority = snapshot.items.firstWhere((element) => element.value == 1, orElse: null); +// } else { +// _serviceRequest.priority = snapshot.items.firstWhere((element) => element.value == 0, orElse: null); +// } +// setState(() {}); +// }).toShimmer(isShow: snapshot.loading,context: context), +// ); +// }), +// ], +// ), +// 16.height, +// Consumer(builder: (cxt, snapshot, _) { +// try { +// _serviceRequest.defectType ??= snapshot.items.first; +// } catch (ex) { +// print("snapshot.items:${snapshot.items.length}"); +// } +// +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisSize: MainAxisSize.min, +// children: [ +// Text(context.translation.equipmentStatus, style: Theme.of(context).textTheme.bodyLarge), +// 8.height, +// Wrap( +// runSpacing: 8, +// spacing: 8, +// children: [ +// for (var element in snapshot.items) +// Row( +// mainAxisSize: MainAxisSize.min, +// children: [ +// SizedBox( +// width: 24, +// height: 24, +// child: Radio( +// value: element, +// activeColor: Colors.red, +// fillColor: WidgetStateColor.resolveWith((states) { +// if (states.contains(WidgetState.selected)) return const Color(0xff3DA5E5); +// return const Color(0xffE0E0E0); +// }), +// groupValue: _serviceRequest.defectType, +// onChanged: (state) { +// setState(() { +// _serviceRequest.defectType = element; +// }); +// }), +// ), +// 8.width, +// Text(element.name!, style: Theme.of(context).textTheme.bodySmall), +// ], +// ) +// ], +// ).toShimmer(isShow: snapshot.loading,context: context), +// ], +// ); +// }), +// 16.height, +// AttachmentPicker(label: context.translation.attachImage, attachment: attachments, showAsGrid: true), +// ], +// ).toShadowContainer(context), +// +// // SingleItemDropDownMenu( +// // context: context, +// // title: context.translation.priority, +// // initialValue: _serviceRequest?.priority, +// // onSelect: (value) { +// // _serviceRequest.priority = value; +// // }, +// // ), +// // 8.height, +// // SingleItemDropDownMenu( +// // context: context, +// // title: context.translation.equipmentStatus, +// // initialValue: _serviceRequest?.defectType, +// // onSelect: (value) { +// // _serviceRequest.defectType = value; +// // }, +// // ), +// +// // Consumer(builder: (context, snapshot, _) { +// // return SingleItemDropDownMenu( +// // context: context, +// // enabled: false, +// // title: context.translation.source, +// // initialValue: snapshot.items?.firstWhere((element) => element.value == 3, orElse: null), +// // ); +// // }), +// // 8.height, +// // Consumer(builder: (context, snapshot, _) { +// // return SingleItemDropDownMenu( +// // context: context, +// // title: context.translation.requestType, +// // enabled: false, +// // initialValue: snapshot.items?.firstWhere((element) => element.value == 1, orElse: null), +// // // onSelect: (value) { +// // // _serviceRequest.type = value; +// // // }, +// // ); +// // }), +// +// // Align( +// // alignment: AlignmentDirectional.centerStart, +// // child: context.translation.callComments.heading5(context), +// // ), +// 8.height, +// // SpeechToTextButton( +// // controller: _commentController, +// // ), +// // 8.height, +// // AppTextFormField( +// // controller: _commentController, +// // labelText: context.translation.problemDesc, +// // suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16), +// // initialValue: _serviceRequest.callComments, +// // onSaved: (text) { +// // _serviceRequest.callComments = text; +// // }, +// // ), +// // 8.height, +// // RecordSound( +// // onRecord: (audio) { +// // _serviceRequest.audio = audio; +// // }, +// // enabled: widget.serviceRequest == null ? true : false, +// // ), +// 8.height, +// TextSpeechRecordWidget( +// initialMessage: _serviceRequest.callComments!, +// onMessageChange: (message) { +// _serviceRequest.callComments = message; +// }, +// onRecord: (audio) { +// _serviceRequest.audio = audio; +// }, +// enabled: widget.serviceRequest == null ? true : false, +// ), +// 16.height, +// ], +// ), +// ).expanded, +// AppFilledButton( +// onPressed: checkPendingRequest ? null : _submit, +// loading: checkPendingRequest, +// label: (pendingAssetServiceRequest != null && (pendingAssetServiceRequest!.details?.isNotEmpty ?? false)) ? "Submit Duplicate Request" : "Submit New Request", +// ), +// ], +// ), +// ).paddingOnly(start: 16, end: 16, bottom: 24, top: 16), +// ), +// ), +// ); +// } +// +// bool checkPendingRequest = false; +// +// void showPendingRequests() { +// Navigator.of(context).push(MaterialPageRoute(builder: (_) => PendingServiceRequestScreen(pendingAssetServiceRequest!))); +// } +// +// void showPendingRequestBottomSheet() async { +// bool view = (await showModalBottomSheet( +// context: context, +// isDismissible: false, +// shape: const RoundedRectangleBorder( +// borderRadius: BorderRadius.vertical( +// top: Radius.circular(20), +// ), +// ), +// clipBehavior: Clip.antiAliasWithSaveLayer, +// builder: (BuildContext context) => PendingRequestBottomSheet(pendingAssetServiceRequest!, _serviceRequest.device!), +// )) as bool; +// if (view) { +// showPendingRequests(); +// } +// } +// +// Future checkAssetForPendingServiceRequest(int assetId) async { +// checkPendingRequest = true; +// setState(() {}); +// +// pendingAssetServiceRequest = await _serviceRequestsProvider.checkAssetPendingRequest(assetId); +// await Future.delayed(const Duration(milliseconds: 250)); +// +// checkPendingRequest = false; +// setState(() {}); +// } +// +// Future _submit() async { +// _serviceRequest.requestedThrough = Provider.of(context, listen: false).items.firstWhere((element) => element.value == 3, orElse: null); +// _serviceRequest.type = Provider.of(context, listen: false).items.firstWhere((element) => element.value == 1, orElse: null); +// +// if (_formKey.currentState!.validate() && await _serviceRequest.validateNewRequest(context)) { +// _formKey.currentState!.save(); +// +// // bool canSubmitRequest = await checkAssetForPendingServiceRequest(_serviceRequest.device.id); +// // if (!canSubmitRequest) { +// // return; +// // } +// +// +// _serviceRequest.devicePhotos = attachments.map((item) => ServiceRequestUtils.isLocalUrl(item.name??'') ? "${item.name?.split("/").last}|${base64Encode(File(item.name??'').readAsBytesSync())}" : item.name??'').toList(); +// if (_serviceRequest.audio != null) { +// if (_isLocalUrl(_serviceRequest.audio!)) { +// final File file = File(_serviceRequest.audio!); +// _serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; +// } +// } +// await _serviceRequestsProvider.createRequest( +// context: context, +// user: _userProvider.user!, +// host: _settingProvider.host!, +// serviceRequest: _serviceRequest, +// ); +// } +// } +// } diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart index 1bddd87e..e7fb963a 100644 --- a/lib/views/widgets/images/multi_image_picker.dart +++ b/lib/views/widgets/images/multi_image_picker.dart @@ -14,279 +14,279 @@ import 'package:test_sa/new_views/app_style/app_color.dart'; import '../../../new_views/common_widgets/app_dashed_button.dart'; import 'multi_image_picker_item.dart'; -class MultiFilesPicker extends StatefulWidget { - final String label; - final bool error; - final List files; - final List attachment; - - final bool enabled, onlyImages; - double? buttonHeight; - Widget? buttonIcon; - Color? buttonColor; - final Function(List)? onChange; - final bool showAsGrid; - - MultiFilesPicker( - {Key? key, - this.files = const [], - this.attachment = const [], - required this.label, - this.error = false, - this.buttonHeight, - this.buttonIcon, - this.enabled = true, - this.onlyImages = false, - this.onChange, - this.showAsGrid = false, - this.buttonColor}) - : super(key: key); - - @override - State createState() => _MultiFilesPickerState(); -} - -class _MultiFilesPickerState extends State { - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.enabled) ...[ - AppDashedButton( - title: widget.label, - height: widget.buttonHeight, - buttonColor: widget.buttonColor, - icon: widget.buttonIcon, - onPressed: (widget.enabled == false) - ? () {} - : widget.showAsGrid - ? showFileSourceSheet - : onFilePicker), - 16.height, - ], - if (widget.files.isNotEmpty) - Wrap( - spacing: 8.toScreenWidth, - children: List.generate( - widget.files!.length, - (index) { - File image = widget.files![index]; - return MultiFilesPickerItem( - file: image, - enabled: widget.enabled, - onRemoveTap: (image) { - if (!widget.enabled) { - return; - } - widget.files.remove(image); - if (widget.onChange != null) { - widget.onChange!(widget.files); - } - setState(() {}); - }, - ); - }, - ), - ), - ], - ); - } - - fromFilePicker() async { - FilePickerResult? result = await FilePicker.platform.pickFiles( - type: FileType.custom, - allowMultiple: true, - allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], - ); - if (result != null) { - for (var path in result.paths) { - widget.files.add(File(path!)); - if (widget.onChange != null) { - widget.onChange!(widget.files); - } - } - setState(() {}); - } - } - - void showFileSourceSheet() async { - if (widget.files.length >= 5) { - Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); - return; - } - - ImageSource? source = (await showModalBottomSheet( - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - clipBehavior: Clip.antiAliasWithSaveLayer, - builder: (BuildContext context) => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Attach File".heading4(context), - 12.height, - GridView( - padding: const EdgeInsets.all(0), - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), - children: [ - gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), - gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)), - gridItem(Icons.file_present_rounded, context.translation.pickFromFiles).onPress(() async { - await fromFilePicker(); - Navigator.pop(context); - }), - ], - ), - 12.height, - ], - ).paddingAll(21), - )) as ImageSource?; - if (source == null) return; - final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); - - if (pickedFile != null) { - File fileImage = File(pickedFile.path); - widget.files.add(fileImage); - if (widget.onChange != null) { - widget.onChange!(widget.files); - } - setState(() {}); - } - } - - Widget gridItem(IconData iconData, String title) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xffF1F1F1), width: 1), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Icon(iconData, color: const Color(0xff7D859A), size: 36), - Text( - title, - style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), - ), - ], - ), - ); - } - - onFilePicker() async { - if (widget.files.length >= 5) { - Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); - return; - } - ImageSource? source = await showModalBottomSheet( - context: context, - builder: (BuildContext context) { - Widget listCard({required String icon, required String label, required VoidCallback onTap}) { - return GestureDetector( - onTap: onTap, - child: Container( - constraints: BoxConstraints(minWidth: 111.toScreenWidth, minHeight: 111.toScreenHeight), - padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 12.toScreenHeight), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), border: Border.all(width: 1, color: AppColor.white70)), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - icon.toSvgAsset(), - 24.height, - label.bodyText2(context).custom(color: AppColor.black20), - ], - ), - ), - ); - } - - return Container( - padding: const EdgeInsets.all(16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - listCard( - icon: 'camera_icon', - label: '${context.translation.open}\n${context.translation.camera}', - onTap: () { - Navigator.of(context).pop(ImageSource.camera); - }, - ), - listCard( - icon: 'gallery_icon', - label: '${context.translation.open}\n${context.translation.gallery}', - onTap: () { - Navigator.of(context).pop(ImageSource.gallery); - }, - ), - listCard( - icon: 'file_icon', - label: '${context.translation.open}\n${context.translation.files}', - onTap: () async { - await fromFilePicker(); - Navigator.pop(context); - }, - ), - ], - ), - ); - }, - ); - // ImageSource source = await showDialog( - // context: context, - // builder: (dialogContext) => CupertinoAlertDialog( - // actions: [ - // TextButton( - // child: Text(context.translation.pickFromCamera), - // onPressed: () { - // Navigator.of(dialogContext).pop(ImageSource.camera); - // }, - // ), - // TextButton( - // child: Text(context.translation.pickFromGallery), - // onPressed: () { - // Navigator.of(dialogContext).pop(ImageSource.gallery); - // }, - // ), - // TextButton( - // child: Text(context.translation.pickFromFiles), - // onPressed: () async { - // await fromFilePicker(); - // Navigator.pop(context); - // }, - // ), - // ], - // ), - // ); - if (source == null) return; - - final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); - - if (pickedFile != null) { - File fileImage = File(pickedFile.path); - if (fileImage != null) { - widget.files.add(fileImage); - if (widget.onChange != null) { - widget.onChange!(widget.files); - } - setState(() {}); - } - } - - setState(() {}); - } -} +// class MultiFilesPicker extends StatefulWidget { +// final String label; +// final bool error; +// final List files; +// final List attachment; +// +// final bool enabled, onlyImages; +// double? buttonHeight; +// Widget? buttonIcon; +// Color? buttonColor; +// final Function(List)? onChange; +// final bool showAsGrid; +// +// MultiFilesPicker( +// {Key? key, +// this.files = const [], +// this.attachment = const [], +// required this.label, +// this.error = false, +// this.buttonHeight, +// this.buttonIcon, +// this.enabled = true, +// this.onlyImages = false, +// this.onChange, +// this.showAsGrid = false, +// this.buttonColor}) +// : super(key: key); +// +// @override +// State createState() => _MultiFilesPickerState(); +// } +// +// class _MultiFilesPickerState extends State { +// @override +// Widget build(BuildContext context) { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// if (widget.enabled) ...[ +// AppDashedButton( +// title: widget.label, +// height: widget.buttonHeight, +// buttonColor: widget.buttonColor, +// icon: widget.buttonIcon, +// onPressed: (widget.enabled == false) +// ? () {} +// : widget.showAsGrid +// ? showFileSourceSheet +// : onFilePicker), +// 16.height, +// ], +// if (widget.files.isNotEmpty) +// Wrap( +// spacing: 8.toScreenWidth, +// children: List.generate( +// widget.files!.length, +// (index) { +// File image = widget.files![index]; +// return MultiFilesPickerItem( +// file: image, +// enabled: widget.enabled, +// onRemoveTap: (image) { +// if (!widget.enabled) { +// return; +// } +// widget.files.remove(image); +// if (widget.onChange != null) { +// widget.onChange!(widget.files); +// } +// setState(() {}); +// }, +// ); +// }, +// ), +// ), +// ], +// ); +// } +// +// fromFilePicker() async { +// FilePickerResult? result = await FilePicker.platform.pickFiles( +// type: FileType.custom, +// allowMultiple: true, +// allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], +// ); +// if (result != null) { +// for (var path in result.paths) { +// widget.files.add(File(path!)); +// if (widget.onChange != null) { +// widget.onChange!(widget.files); +// } +// } +// setState(() {}); +// } +// } +// +// void showFileSourceSheet() async { +// if (widget.files.length >= 5) { +// Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); +// return; +// } +// +// ImageSource? source = (await showModalBottomSheet( +// context: context, +// shape: const RoundedRectangleBorder( +// borderRadius: BorderRadius.vertical( +// top: Radius.circular(20), +// ), +// ), +// clipBehavior: Clip.antiAliasWithSaveLayer, +// builder: (BuildContext context) => Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// "Attach File".heading4(context), +// 12.height, +// GridView( +// padding: const EdgeInsets.all(0), +// shrinkWrap: true, +// physics: const NeverScrollableScrollPhysics(), +// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), +// children: [ +// gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), +// gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)), +// gridItem(Icons.file_present_rounded, context.translation.pickFromFiles).onPress(() async { +// await fromFilePicker(); +// Navigator.pop(context); +// }), +// ], +// ), +// 12.height, +// ], +// ).paddingAll(21), +// )) as ImageSource?; +// if (source == null) return; +// final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); +// +// if (pickedFile != null) { +// File fileImage = File(pickedFile.path); +// widget.files.add(fileImage); +// if (widget.onChange != null) { +// widget.onChange!(widget.files); +// } +// setState(() {}); +// } +// } +// +// Widget gridItem(IconData iconData, String title) { +// return Container( +// padding: const EdgeInsets.all(12), +// decoration: BoxDecoration( +// color: Colors.white, +// borderRadius: BorderRadius.circular(12), +// border: Border.all(color: const Color(0xffF1F1F1), width: 1), +// ), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Icon(iconData, color: const Color(0xff7D859A), size: 36), +// Text( +// title, +// style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), +// ), +// ], +// ), +// ); +// } +// +// onFilePicker() async { +// if (widget.files.length >= 5) { +// Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); +// return; +// } +// ImageSource? source = await showModalBottomSheet( +// context: context, +// builder: (BuildContext context) { +// Widget listCard({required String icon, required String label, required VoidCallback onTap}) { +// return GestureDetector( +// onTap: onTap, +// child: Container( +// constraints: BoxConstraints(minWidth: 111.toScreenWidth, minHeight: 111.toScreenHeight), +// padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 12.toScreenHeight), +// decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), border: Border.all(width: 1, color: AppColor.white70)), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// icon.toSvgAsset(), +// 24.height, +// label.bodyText2(context).custom(color: AppColor.black20), +// ], +// ), +// ), +// ); +// } +// +// return Container( +// padding: const EdgeInsets.all(16.0), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// listCard( +// icon: 'camera_icon', +// label: '${context.translation.open}\n${context.translation.camera}', +// onTap: () { +// Navigator.of(context).pop(ImageSource.camera); +// }, +// ), +// listCard( +// icon: 'gallery_icon', +// label: '${context.translation.open}\n${context.translation.gallery}', +// onTap: () { +// Navigator.of(context).pop(ImageSource.gallery); +// }, +// ), +// listCard( +// icon: 'file_icon', +// label: '${context.translation.open}\n${context.translation.files}', +// onTap: () async { +// await fromFilePicker(); +// Navigator.pop(context); +// }, +// ), +// ], +// ), +// ); +// }, +// ); +// // ImageSource source = await showDialog( +// // context: context, +// // builder: (dialogContext) => CupertinoAlertDialog( +// // actions: [ +// // TextButton( +// // child: Text(context.translation.pickFromCamera), +// // onPressed: () { +// // Navigator.of(dialogContext).pop(ImageSource.camera); +// // }, +// // ), +// // TextButton( +// // child: Text(context.translation.pickFromGallery), +// // onPressed: () { +// // Navigator.of(dialogContext).pop(ImageSource.gallery); +// // }, +// // ), +// // TextButton( +// // child: Text(context.translation.pickFromFiles), +// // onPressed: () async { +// // await fromFilePicker(); +// // Navigator.pop(context); +// // }, +// // ), +// // ], +// // ), +// // ); +// if (source == null) return; +// +// final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); +// +// if (pickedFile != null) { +// File fileImage = File(pickedFile.path); +// if (fileImage != null) { +// widget.files.add(fileImage); +// if (widget.onChange != null) { +// widget.onChange!(widget.files); +// } +// setState(() {}); +// } +// } +// +// setState(() {}); +// } +// } class AttachmentModel { int id = 0; @@ -402,10 +402,10 @@ class _AttachmentPickerState extends State { } void showFileSourceSheet() async { - if (widget.attachment.length >= 5) { - Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); - return; - } + // if (widget.attachment.length >= 5) { + // Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); + // return; + // } ImageSource source = (await showModalBottomSheet( context: context, From 79fa949ba28f67752e0f0678adbf211ec653c74c Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 1 Sep 2025 10:33:11 +0300 Subject: [PATCH 6/6] 1.3.8+27 uploaded. --- lib/controllers/api_routes/urls.dart | 14 +++-- .../providers/settings/setting_provider.dart | 1 + lib/extensions/widget_extensions.dart | 62 +++++++++++-------- pubspec.yaml | 2 +- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 11a2ecc0..f8226e55 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -1,16 +1,16 @@ class URLs { URLs._(); - static const String appReleaseBuildNumber = "23"; + static const String appReleaseBuildNumber = "24"; - // static const host1 = "https://atomsm.hmg.com"; // production url + static const host1 = "https://atomsm.hmg.com"; // production url // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url - static const host1 = "https://atomsmuat.hmg.com"; // local UAT url + // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url // static String _baseUrl = "$_host/mobile"; // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis - static final String _baseUrl = "$_host/mobile"; // host local UAT - // static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM + // static final String _baseUrl = "$_host/mobile"; // host local UAT + static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM static String _host = host1; @@ -22,9 +22,13 @@ class URLs { // API Routes static get login => "$_baseUrl/MobileAuth/Login"; + static get getUserInfo => "$_baseUrl/MobileAuth/GetUserInfo"; + static get logout => "$_baseUrl/MobileAuth/Logout"; + static get enableFaceId => "$_baseUrl/MobileAuth/EnabledFaceId"; + static get checkLoginValidation => "$_baseUrl/Account/Authenticate"; // web login static get checkAppVersion => "$_baseUrl/Account/CheckAppVersion"; // web login //Reset Password Apis... diff --git a/lib/controllers/providers/settings/setting_provider.dart b/lib/controllers/providers/settings/setting_provider.dart index 3ff7aabe..6fa7687e 100644 --- a/lib/controllers/providers/settings/setting_provider.dart +++ b/lib/controllers/providers/settings/setting_provider.dart @@ -75,6 +75,7 @@ class SettingProvider extends ChangeNotifier { } void selectAssetGroup(User user) { + if(user.assetGroups ==null) return; if (user.assetGroups!.length == 1) { _assetGroup = user.assetGroups!.first; } else { diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index b9770dda..ee646b3e 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -55,30 +55,31 @@ extension WidgetExtensions on Widget { Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); - Widget handlePopScope({required BuildContext cxt, required VoidCallback onSave, bool? showPopUp =true}) { - return showPopUp! ? PopScope( - canPop: false, - onPopInvokedWithResult: (didPop, result) { - if (didPop) { - return; - } - showDialog( - context: cxt, - builder: (BuildContext cxt) => AcknowledgeWorkDialog( - onSave: () => onSave(), - onDiscard: () { - Navigator.of(cxt).pop(); - }, - ), - ); - }, - child: this): this; + Widget handlePopScope({required BuildContext cxt, required VoidCallback onSave, bool? showPopUp = true}) { + return showPopUp! + ? PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (didPop) { + return; + } + showDialog( + context: cxt, + builder: (BuildContext cxt) => AcknowledgeWorkDialog( + onSave: () => onSave(), + onDiscard: () { + Navigator.of(cxt).pop(); + }, + ), + ); + }, + child: this) + : this; } - Widget toShimmer({bool isShow = true, double radius = 20,required BuildContext context}) => isShow + Widget toShimmer({bool isShow = true, double radius = 20, required BuildContext context}) => isShow ? Shimmer.fromColors( - // baseColor: const Color(0xffe8eff0), - baseColor: Theme.of(context).scaffoldBackgroundColor, + baseColor: context.isDark ? AppColor.backgroundDark : const Color(0xffe8eff0), highlightColor: AppColor.background(context), child: ClipRRect( borderRadius: BorderRadius.circular(radius), @@ -94,17 +95,26 @@ extension WidgetExtensions on Widget { ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox(width: 250, height: 24).toShimmer(isShow: isShow,context: context), + const SizedBox(width: 250, height: 24).toShimmer(isShow: isShow, context: context), 8.height, - const SizedBox(width: 160, height: 16).toShimmer(isShow: isShow,context: context), + const SizedBox(width: 160, height: 16).toShimmer(isShow: isShow, context: context), 8.height, - const SizedBox(width: 120, height: 18).toShimmer(isShow: isShow,context: context).toShimmer(isShow: isShow,context: context), + const SizedBox(width: 120, height: 18).toShimmer(isShow: isShow, context: context).toShimmer(isShow: isShow, context: context), ], ).toShadowContainer(context) : this; - Widget toShadowContainer(BuildContext context, - {bool showShadow = true, double borderRadius = 14, bool withShadow = true, Color? backgroundColor, Color borderColor = Colors.transparent, double padding = 16, EdgeInsets? paddingObject, EdgeInsets? margin,}) => + Widget toShadowContainer( + BuildContext context, { + bool showShadow = true, + double borderRadius = 14, + bool withShadow = true, + Color? backgroundColor, + Color borderColor = Colors.transparent, + double padding = 16, + EdgeInsets? paddingObject, + EdgeInsets? margin, + }) => withShadow ? Container( padding: paddingObject ?? EdgeInsets.all(padding), diff --git a/pubspec.yaml b/pubspec.yaml index e7b9aadf..b3a11d0c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.3.7+26 +version: 1.3.8+27 environment: sdk: ">=3.5.0 <4.0.0"