diff --git a/assets/images/ic_done.png b/assets/images/ic_done.png new file mode 100644 index 00000000..5b802855 Binary files /dev/null and b/assets/images/ic_done.png differ diff --git a/assets/images/ic_nfc.png b/assets/images/ic_nfc.png new file mode 100644 index 00000000..274e1b8c Binary files /dev/null and b/assets/images/ic_nfc.png differ diff --git a/assets/images/nfc_icon.svg b/assets/images/nfc_icon.svg new file mode 100644 index 00000000..11e61f7c --- /dev/null +++ b/assets/images/nfc_icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/images/success_swipe.svg b/assets/images/success_swipe.svg new file mode 100644 index 00000000..499c58c7 --- /dev/null +++ b/assets/images/success_swipe.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/images/swipe.svg b/assets/images/swipe.svg new file mode 100644 index 00000000..d389f93a --- /dev/null +++ b/assets/images/swipe.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/swipe_success.svg b/assets/images/swipe_success.svg new file mode 100644 index 00000000..68021f2e --- /dev/null +++ b/assets/images/swipe_success.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/images/wifi_icon.svg b/assets/images/wifi_icon.svg new file mode 100644 index 00000000..645396d9 --- /dev/null +++ b/assets/images/wifi_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/lib/controllers/api_routes/api_manager.dart b/lib/controllers/api_routes/api_manager.dart index 3dd80f7c..cefbbe9f 100644 --- a/lib/controllers/api_routes/api_manager.dart +++ b/lib/controllers/api_routes/api_manager.dart @@ -50,7 +50,7 @@ class ApiManager { return response; } - Future post(String url, {Map? headers, required Map body}) async { + Future post(String url, {Map? headers, required Map body, bool ?showToast = true}) async { headers ??= {}; headers.addAll(_headers); @@ -74,7 +74,7 @@ class ApiManager { } else { if (jsonDecode(response.body) is Map) { final message = jsonDecode(response.body)["message"]; - if (message != null && message.toString().isNotEmpty) { + if (message != null && message.toString().isNotEmpty&&showToast!) { Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG); } } @@ -117,7 +117,7 @@ class ApiManager { return response; } - Future postWithOutBody(String url, {Map? headers}) async { + Future postWithOutBody(String url, {Map? headers,bool showLoading = true}) async { headers ??= {}; headers.addAll(_headers); @@ -139,7 +139,7 @@ class ApiManager { } else { if (jsonDecode(response.body) is Map) { final message = jsonDecode(response.body)["message"]; - if (message != null && message.toString().isNotEmpty) { + if (message != null && message.toString().isNotEmpty&&showLoading) { Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG); } } diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 2062185b..45d4f56b 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -76,9 +76,10 @@ class URLs { static get sendOtpUrl=> '$_baseUrl/SmsNotification/SendOTP/'; static get verifyOtpUrl=> '$_baseUrl/SmsNotification/VerifyOTP/'; // 08051 - //Swipe module Apis need to ask backend why base url changed for this api.. + //Swipe module Api.. static get swipeUrl=> '$_baseUrl/Swipe/Swipe'; static get getSwipeLastTransactionUrl=> '$_baseUrl/Swipe/GetLastTransaction'; + static get getSwipeTransactionHistoryUrl=> '$_baseUrl/Swipe/GetTransactions'; //service request..... static get getServiceRequests => "$_baseUrl/CallRequest/GetCallRequests"; // get diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index eacef64d..53ba507b 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -6,7 +6,12 @@ import 'package:http/http.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/new_models/general_response_model.dart'; +import 'package:test_sa/models/new_models/update_password.dart'; +import 'package:test_sa/models/new_models/verify_otp_model.dart'; import 'package:test_sa/models/user.dart'; +import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart'; +import 'package:test_sa/new_views/swipe_module/models/swipe_transaction_history.dart'; +import 'package:test_sa/new_views/swipe_module/models/swipe_transaction_model.dart'; import '../../../new_views/common_widgets/app_lazy_loading.dart'; @@ -26,6 +31,31 @@ class UserProvider extends ChangeNotifier { File? profileImage; + VerifyOtpModel _verifyOtpModel= VerifyOtpModel(); + SwipeTransaction _swipeTransactionModel = SwipeTransaction(); + List _swipeHistory = []; + + SwipeTransaction get swipeTransactionModel => _swipeTransactionModel; + + List get swipeHistory => _swipeHistory; + + set swipeHistory(List value) { + _swipeHistory = value; + notifyListeners(); + } + + set swipeTransactionModel(SwipeTransaction value) { + _swipeTransactionModel = value; + notifyListeners(); + } + + VerifyOtpModel get verifyOtpModel => _verifyOtpModel; + + set verifyOtpModel(VerifyOtpModel value) { + _verifyOtpModel = value; + notifyListeners(); + } + void setUser(User user) { _user = user; ApiManager.instance.user = user; @@ -118,93 +148,91 @@ class UserProvider extends ChangeNotifier { // return response.statusCode; // } Future sendForgetPasswordOtp({required BuildContext context, required String employeeId}) async { - GeneralResponseModel responseModel= GeneralResponseModel(responseCode: -1) ; - if (_loading == true) return responseModel; + GeneralResponseModel generalResponseModel = GeneralResponseModel(responseCode: -1); + if (_loading == true) return generalResponseModel; _loading = true; notifyListeners(); Response response; try { - showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.postWithOutBody( - URLs.sendOtpUrl + '?$employeeId', - ); - responseModel = GeneralResponseModel.fromJson(json.decode(response.body)); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + response = await ApiManager.instance.postWithOutBody(URLs.sendForgetPasswordOtp + '?employeeId=$employeeId', showLoading: false); + generalResponseModel = GeneralResponseModel.fromJson(json.decode(response.body)); _loading = false; if (response.statusCode >= 200 && response.statusCode < 300) { notifyListeners(); Navigator.pop(context); - return responseModel; + return generalResponseModel; } notifyListeners(); Navigator.pop(context); - return responseModel; + return generalResponseModel; } catch (error) { // debugPrint(error); Navigator.pop(context); _loading = false; notifyListeners(); - return responseModel; + return generalResponseModel; } } - Future forgetPasswordValidateOtp({required BuildContext context, required String employeeId, required String otp}) async { - GeneralResponseModel responseModel= GeneralResponseModel(responseCode: -1) ; - if (_loading == true) return responseModel; + GeneralResponseModel generalResponseModel = GeneralResponseModel(responseCode: -1); + // if (_loading == true) return generalResponseModel; _loading = true; notifyListeners(); Response response; try { - showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); response = await ApiManager.instance.postWithOutBody( - URLs.sendOtpUrl + '?employeeId=$employeeId&otp=$otp', + URLs.sendForgetPasswordValidateOtp + '?employeeId=$employeeId&otp=$otp', ); - responseModel = GeneralResponseModel.fromJson(json.decode(response.body)); + generalResponseModel = GeneralResponseModel.fromJson(json.decode(response.body)); _loading = false; if (response.statusCode >= 200 && response.statusCode < 300) { + if (generalResponseModel.data != null) { + verifyOtpModel = VerifyOtpModel.fromJson(generalResponseModel.data); + } notifyListeners(); Navigator.pop(context); - return responseModel; + return generalResponseModel; } notifyListeners(); Navigator.pop(context); - return responseModel; + return generalResponseModel; } catch (error) { // debugPrint(error); Navigator.pop(context); _loading = false; notifyListeners(); - return responseModel; + return generalResponseModel; } } - Future updateNewPassword({required BuildContext context, required String userId}) async { - GeneralResponseModel responseModel= GeneralResponseModel(responseCode: -1) ; - if (_loading == true) return responseModel; + Future updateNewPassword({required BuildContext context, required UpdatePasswordModel updatePasswordModel}) async { + GeneralResponseModel generalResponseModel = GeneralResponseModel(responseCode: -1); + if (_loading == true) return generalResponseModel; _loading = true; notifyListeners(); Response response; try { - showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.postWithOutBody( - URLs.sendOtpUrl + userId, - ); - responseModel = GeneralResponseModel.fromJson(json.decode(response.body)); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + response = await ApiManager.instance.post(URLs.updateNewPassword, body: updatePasswordModel.toJson()); + generalResponseModel = GeneralResponseModel.fromJson(json.decode(response.body)); _loading = false; if (response.statusCode >= 200 && response.statusCode < 300) { notifyListeners(); Navigator.pop(context); - return responseModel; + return generalResponseModel; } notifyListeners(); Navigator.pop(context); - return responseModel; + return generalResponseModel; } catch (error) { // debugPrint(error); Navigator.pop(context); _loading = false; notifyListeners(); - return responseModel; + return generalResponseModel; } } Future uploadProfileImage(String userId, File image) async { @@ -233,6 +261,75 @@ class UserProvider extends ChangeNotifier { return -1; } } + Future makeSwipe({required Swipe model}) async { + isLoading = true; + SwipeModel swipeResponse = SwipeModel(data: false, message: '', responseCode: 0, isSuccess: false); + notifyListeners(); + Response response; + // try { + response = await ApiManager.instance.post(URLs.swipeUrl, body: model.toJson(), showToast: false); + swipeResponse = SwipeModel.fromJson(json.decode(response.body)); + + if (response.statusCode >= 200 && response.statusCode < 300) { + isUserConfirmSwipe = true; + await getSwipeLastTransaction(userId: user!.userID!); + notifyListeners(); + } + + notifyListeners(); + return swipeResponse; + // } catch (error) { + // notifyListeners(); + // return swipeResponse; + // } + } + + Future getSwipeLastTransaction({required String userId}) async { + isLoading = true; + notifyListeners(); + Response response; + var body = { + "userId": userId, + }; + try { + response = await ApiManager.instance.post(URLs.getSwipeLastTransactionUrl, body: body); + + if (response.statusCode >= 200 && response.statusCode < 300) { + swipeTransactionModel = SwipeTransaction.fromJson(json.decode(response.body)['data']); + } + notifyListeners(); + return response.statusCode; + } catch (error) { + notifyListeners(); + return -1; + } + } + + Future getSwipeTransactionHistory({required String userId, required DateTime dateFrom,required DateTime dateTo}) async { + isLoading = true; + notifyListeners(); + Response response; + var body = { + "userId": userId, + "dateFrom": dateFrom.toIso8601String(), + "dateTo": dateTo.toIso8601String(), + }; + try { + response = await ApiManager.instance.post(URLs.getSwipeTransactionHistoryUrl, body: body); + + if (response.statusCode >= 200 && response.statusCode < 300) { + List dataList = GeneralResponseModel.fromJson(json.decode(response.body)).data; + swipeHistory = List.generate(dataList.length, (index) => SwipeHistory.fromJson(dataList[index])); + } + isLoading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + isLoading = false; + notifyListeners(); + return -1; + } + } // Future updateProfile({ // required String host, diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart index 0e24590d..ff6df398 100644 --- a/lib/dashboard_latest/dashboard_provider.dart +++ b/lib/dashboard_latest/dashboard_provider.dart @@ -270,6 +270,7 @@ class DashBoardProvider extends ChangeNotifier { if (isHighPriority) body["isHighPriority"] = true; if (isOverdue) body["isOverdue"] = true; response = await ApiManager.instance.post(url, body: body); + print('data i got is ${response.body}'); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { diff --git a/lib/dashboard_latest/dashboard_view.dart b/lib/dashboard_latest/dashboard_view.dart index 881b0cda..3caa6abf 100644 --- a/lib/dashboard_latest/dashboard_view.dart +++ b/lib/dashboard_latest/dashboard_view.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:nfc_manager/nfc_manager.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; import 'package:test_sa/controllers/notification/notification_manger.dart'; @@ -12,10 +13,14 @@ import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart'; import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart'; import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/user.dart'; -import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/swipe_module/circular_animated_widget.dart'; +import 'package:test_sa/new_views/swipe_module/utils/swipe_general_utils.dart'; import 'widgets/request_category_fragment.dart'; @@ -79,28 +84,12 @@ class _DashboardViewState extends State { }); } - // Future getAllRequests() async { - // allRequestsProvider.isAllLoading = true; - // allRequestsProvider.isFilterRequestLoading = true; - // allRequestsProvider.currentListIndex = 0; - // allRequestsProvider.filterRequest = null; - // var tabs = RequestUtils.getTabs(userType: userProvider.user!.type!, context: context); - // allRequestsProvider.status = tabs[0]['status']; - // allRequestsProvider.getRequests(); - // allRequestsProvider.pageNum = 1; - // dashBoardProvider.getRequestDetail(usersType: userProvider.user!.type!, status: tabs[0]['status']); - // allRequestsProvider.getFilterRequests(showLoader: true, status: tabs[0]['status']).whenComplete(() { - // allRequestsProvider.requestDetailList = allRequestsProvider.filterRequest; - // }); - // allRequestsProvider.isAllLoading = false; - // notificationsProvider.getSystemNotifications(user: userProvider.user!, resetProvider: true); - // } + void handleScroll() async { _scrollController = ScrollController(); _scrollController.addListener(() async { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_dashBoardProvider.isDetailLoading) { - print('handle scroll called..'); _dashBoardProvider.pageNum = _dashBoardProvider.pageNum + 1; _dashBoardProvider.getRequestDetail( usersType: user.type!, showLoader: false, status: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex].tag, tabId: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex].id); @@ -117,30 +106,73 @@ class _DashboardViewState extends State { @override Widget build(BuildContext context) { bool isNurse = (Provider.of(context, listen: false).user!.type) == UsersTypes.normal_user; + final user = Provider.of(context, listen: false).user; return Scaffold( - // backgroundColor: AppColor.background(context), appBar: PreferredSize( preferredSize: const Size.fromHeight(kToolbarHeight), child: AppBarWidget( onDrawerPress: widget.onDrawerPress, )), - body: RefreshIndicator( - onRefresh: () async { - getRequests(); - return Future.delayed(const Duration(milliseconds: 250)); - }, - child: Scrollbar( - controller: _scrollController, - child: SingleChildScrollView( - // physics: AlwaysScrollableScrollPhysics(), - controller: _scrollController, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [16.height, ProgressFragment(), 16.height, if (!isNurse) const RequestsFragment(), const RequestCategoryFragment()], + body: Stack( + children: [ + RefreshIndicator( + onRefresh: () async { + getRequests(); + return Future.delayed(const Duration(milliseconds: 250)); + }, + child: Scrollbar( + controller: _scrollController, + child: SingleChildScrollView( + // physics: AlwaysScrollableScrollPhysics(), + controller: _scrollController, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [16.height, ProgressFragment(), 16.height, if (!isNurse) const RequestsFragment(), const RequestCategoryFragment()], + ), + ), ), ), - ), + //TODO need to fix the alignment when no data is found + if (user!=null&&user.employeeIsHMG==false) + Positioned( + right: user.type == UsersTypes.engineer ? 20.toScreenWidth : null, + left: user.type != UsersTypes.engineer ? 20.toScreenWidth : null, + bottom: 20.toScreenHeight, + child: GestureDetector( + onTap: () async { + bool isNfcSupported = await NfcManager.instance.isAvailable(); + SwipeGeneralUtils.instance.showSwipeTypeBottomSheetSheet(isNfcSupported: isNfcSupported); + }, + child: CircularAnimatedContainer(child: Container( + width: 100.toScreenWidth, + height: 100.toScreenHeight, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white10, + border: Border.all(color: AppColor.primary10.withOpacity(0.5), width: 2), + ), + child: Consumer( + builder: (context, userProvider,child) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + 'swipe'.toSvgAsset(width: 32, height: 32), + 8.height, + Text( + ("${context.translation.checkIn}\n${userProvider.swipeTransactionModel.swipeTime != null ? SwipeGeneralUtils.instance.formatTimeOnly(userProvider.swipeTransactionModel.swipeTime!) : '--:--'}"), + style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936, fontWeight: FontWeight.w500, fontFamily: "Poppins"), + ), + + ], + ); + } + ), + ),), + ), + ), + ], ), ); } diff --git a/lib/dashboard_latest/widgets/request_category_fragment.dart b/lib/dashboard_latest/widgets/request_category_fragment.dart index 9c6d4bf5..cf77a2e4 100644 --- a/lib/dashboard_latest/widgets/request_category_fragment.dart +++ b/lib/dashboard_latest/widgets/request_category_fragment.dart @@ -21,6 +21,8 @@ class RequestCategoryFragment extends StatelessWidget { Widget build(BuildContext context) { return Consumer(builder: (context, dashboardProvider, child) { bool isNurse = (Provider.of(context, listen: false).user?.type) == UsersTypes.normal_user; + debugPrint('condition i got is ${dashboardProvider.requestDetailList }'); + return Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ //TODO uncommit this to get the calendar card.. !isNurse && dashboardProvider.tabs.isNotEmpty && dashboardProvider.tabs[dashboardProvider.currentListIndex].tag == 0 @@ -53,7 +55,7 @@ class RequestCategoryFragment extends StatelessWidget { context: context, userType: Provider.of(context, listen: false).user?.type!, ), - dashboardProvider.isDetailLoading || dashboardProvider.requestDetailList == null + dashboardProvider.isDetailLoading ? Column( mainAxisSize: MainAxisSize.max, children: List.generate(3, (index) { @@ -62,7 +64,7 @@ class RequestCategoryFragment extends StatelessWidget { child: const SizedBox().toRequestShimmer(context, dashboardProvider.isDetailLoading), ); })).paddingOnly(start: 16, end: 16, top: 16) - : (dashboardProvider.requestDetailList?.data?.isEmpty ?? true) + : (dashboardProvider.requestDetailList==null||dashboardProvider.requestDetailList?.data?.isEmpty==true) ? const NoDataFound().paddingOnly(top: 50).center : RequestCategoryList(dashboardProvider.requestDetailList?.data ?? [], dashboardProvider.isDetailLoading, dashboardProvider.requestDetailList?.totalRows ?? 0), ]); diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 1c26a336..8ce8856c 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -511,5 +511,20 @@ "youCanSetTheReminderInAlarmToRemindYouBeforeVisit": "يمكنك تعيين التذكير في المنبه لتذكيرك قبل الزيارة. الرجاء اختيار الوقت أدناه", "setReminder": "تعيين التذكير", "provideQrCodeToEngineer": "قدم رمز الاستجابة السريعة أدناه للمهندس للتحقق من وصوله", - "callResponse": "استجابة الاتصال" + "callResponse": "استجابة الاتصال", + "newPassword": "كلمة المرور الجديدة", + "otpVerification": "التحقق من OTP", + "pleaseEnterTheOtpSentTo": "يرجى إدخال OTP المرسل إلى", + "resetPassword": "إعادة تعيين كلمة المرور", + "pleaseEnterTheNewPassword": "يرجى إدخال كلمة المرور الجديدة", + "verify": "تحقق", + "employeeIdIsRequired": "رقم الموظف مطلوب", + "youHaveSuccessfullyMarkedYourAttendance": "لقد قمت بتسجيل حضورك بنجاح", + "markAttendance": "تسجيل الحضور", + "selectMethodToMarkAttendance": "اختر الطريقة لتسجيل الحضور", + "swipeTypeName": "اسم نوع السحب", + "userName": "اسم المستخدم", + "siteName": "اسم الموقع", + "pointName": "اسم النقطة", + "checkIn": "تسجيل الدخول" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index fe1a160a..74f488b9 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -514,5 +514,21 @@ "doYouWantToSetReminder": "Do you want to set reminder?", "youCanSetTheReminderInAlarmToRemindYouBeforeVisit": "You can set the reminder in alarm to remind you before visit. Please select the time below", "setReminder": "Set Reminder", - "searchAsset" : "Search Asset" + "searchAsset" : "Search Asset", + "newPassword": "New Password", + "resetPassword": "Reset Password", + "otpVerification": "OTP Verification", + "pleaseEnterTheOtpSentTo": "Please enter the OTP sent to", + "pleaseEnterTheNewPassword": "Please enter the new password", + "markAttendance": "Mark Attendance", + "selectMethodToMarkAttendance": "Select the method to mark the attendance", + "verify": "Verify", + "employeeIdIsRequired": "Employee Id is required", + "successful": "Successful", + "youHaveSuccessfullyMarkedYourAttendance": "You have successfully marked your attendance", + "swipeTypeName": "Swipe Type Name", + "userName": "User Name", + "siteName": "Site Name", + "pointName": "Point Name", + "checkIn": "Check in" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index c3079aec..cff76122 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -30,6 +30,8 @@ import 'package:test_sa/new_views/pages/login_page.dart'; import 'package:test_sa/new_views/pages/report_bug_page.dart'; import 'package:test_sa/new_views/pages/settings_page.dart'; import 'package:test_sa/new_views/pages/splash_page.dart'; +import 'package:test_sa/new_views/swipe_module/swipe_history_view.dart'; +import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart'; import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; import 'package:test_sa/providers/department_provider.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart'; @@ -251,6 +253,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => CommentsProvider()), ChangeNotifierProvider(create: (_) => GasRefillCommentsProvider()), + ///todo deleted //ChangeNotifierProvider(create: (_) => RequestStatusProvider()), ChangeNotifierProvider(create: (_) => VendorProvider()), @@ -309,6 +312,8 @@ class MyApp extends StatelessWidget { ProfilePage.id: (_) => const ProfilePage(), ReportBugPage.id: (_) => const ReportBugPage(), HelpCenterPage.id: (_) => const HelpCenterPage(), + SwipeSuccessView.routeName: (_) => const SwipeSuccessView(), + SwipeHistoryView.routeName: (_) => const SwipeHistoryView(), }, ), ), diff --git a/lib/models/new_models/general_response_model.dart b/lib/models/new_models/general_response_model.dart index 64c7d031..97f202a8 100644 --- a/lib/models/new_models/general_response_model.dart +++ b/lib/models/new_models/general_response_model.dart @@ -1,10 +1,10 @@ class GeneralResponseModel { - bool? data; + dynamic data; String? message; - String? title; - String? innerMessage; - int? responseCode; - bool? isSuccess; + String ?title; + String ?innerMessage; + int ?responseCode; + bool ?isSuccess; GeneralResponseModel({this.data, this.message, this.title, this.innerMessage, this.responseCode, this.isSuccess}); diff --git a/lib/models/new_models/swipe_model.dart b/lib/models/new_models/swipe_model.dart index 54868703..030ac00a 100644 --- a/lib/models/new_models/swipe_model.dart +++ b/lib/models/new_models/swipe_model.dart @@ -1,27 +1,29 @@ +import 'package:flutter/material.dart'; + class SwipeModel { - final bool data; - final String message; - final String? title; - final String? innerMessage; - final int responseCode; - final bool isSuccess; + final bool? data; + final String? message; + final String ?title; + final String ?innerMessage; + final int ?responseCode; + final bool ?isSuccess; SwipeModel({ - required this.data, - required this.message, + this.data, + this.message, this.title, this.innerMessage, - required this.responseCode, - required this.isSuccess, + this.responseCode, + this.isSuccess, }); factory SwipeModel.fromJson(Map json) { return SwipeModel( data: json['data'] as bool, message: json['message'] as String, - title: json['title'] as String?, - innerMessage: json['innerMessage'] as String?, + title: json['title'] as String, + innerMessage: json['innerMessage'] as String, responseCode: json['responseCode'] as int, isSuccess: json['isSuccess'] as bool, ); @@ -42,16 +44,16 @@ class SwipeModel { } class Swipe { - final int swipeTypeValue; - final String value; - final double ?latitude; - final double ?longitude; + final int ?swipeTypeValue; + final String? value; + final double? latitude; + final double? longitude; Swipe({ - required this.swipeTypeValue, - required this.value, - required this.latitude, - required this.longitude, + this.swipeTypeValue, + this.value, + this.latitude, + this.longitude, }); Map toJson() { diff --git a/lib/models/new_models/swipe_transaction_history.dart b/lib/models/new_models/swipe_transaction_history.dart new file mode 100644 index 00000000..7bb0137a --- /dev/null +++ b/lib/models/new_models/swipe_transaction_history.dart @@ -0,0 +1,47 @@ +class SwipeHistory { + final int ?id; + final String? swipeTypeName; + final String? userName; + final String ?siteName; + final String ?pointName; + final String ?swipeTime; + final bool ?isSuccess; + final String? errorMessage; + + SwipeHistory({ + this.id, + this.swipeTypeName, + this.userName, + this.siteName, + this.pointName, + this.swipeTime, + this.isSuccess, + this.errorMessage, + }); + + factory SwipeHistory.fromJson(Map json) { + return SwipeHistory( + id: json['id'], + swipeTypeName: json['swipeTypeName'], + userName: json['userName'], + siteName: json['siteName'], + pointName: json['pointName'], + swipeTime: json['swipeTime']!=null? DateTime.parse(json['swipeTime']).toIso8601String():'', + isSuccess: json['isSuccess'], + errorMessage: json['errorMessage'], + ); + } + + Map toJson() { + return { + 'id': id, + 'swipeTypeName': swipeTypeName, + 'userName': userName, + 'siteName': siteName, + 'pointName': pointName, + 'swipeTime': swipeTime, + 'isSuccess': isSuccess, + 'errorMessage': errorMessage, + }; + } +} diff --git a/lib/models/new_models/swipe_transaction_model.dart b/lib/models/new_models/swipe_transaction_model.dart new file mode 100644 index 00000000..ff1d82fd --- /dev/null +++ b/lib/models/new_models/swipe_transaction_model.dart @@ -0,0 +1,47 @@ +class SwipeTransaction { + final int ?id; + final String? swipeTypeName; + final String ?userName; + final String? siteName; + final String? pointName; + final DateTime? swipeTime; + final bool? isSuccess; + final String? errorMessage; + + SwipeTransaction({ + this.id, + this.swipeTypeName, + this.userName, + this.siteName, + this.pointName, + this.swipeTime, + this.isSuccess, + this.errorMessage, + }); + + factory SwipeTransaction.fromJson(Map json) { + return SwipeTransaction( + id: json['id'] as int, + swipeTypeName: json['swipeTypeName'] , + userName: json['userName'] , + siteName: json['siteName'] , + pointName: json['pointName'] , + swipeTime: DateTime.parse(json['swipeTime']), + isSuccess: json['isSuccess'] , + errorMessage: json['errorMessage'] , + ); + } + + // Map toJson() { + // return { + // 'id': id, + // 'swipeTypeName': swipeTypeName, + // 'userName': userName, + // 'siteName': siteName, + // 'pointName': pointName, + // 'swipeTime': swipeTime.toIso8601String(), + // 'isSuccess': isSuccess, + // 'errorMessage': errorMessage, + // }; + // } +} diff --git a/lib/models/new_models/update_password.dart b/lib/models/new_models/update_password.dart index 34d7ec52..e66d7361 100644 --- a/lib/models/new_models/update_password.dart +++ b/lib/models/new_models/update_password.dart @@ -1,30 +1,23 @@ -class UpdatePassword { - final String password; - final String confirmPassword; - final String email; - final String token; +import 'package:flutter/material.dart'; - UpdatePassword({ +class UpdatePasswordModel { + final String? password; + final String ?confirmPassword; + final String ?userId; + final String ?token; + + UpdatePasswordModel({ required this.password, required this.confirmPassword, - required this.email, + required this.userId, required this.token, }); - factory UpdatePassword.fromJson(Map json) { - return UpdatePassword( - password: json['password'] as String, - confirmPassword: json['confirmPassword'] as String, - email: json['email'] as String, - token: json['token'] as String, - ); - } - Map toJson() { return { 'password': password, 'confirmPassword': confirmPassword, - 'email': email, + 'userId': userId, 'token': token, }; } diff --git a/lib/models/new_models/verify_otp_model.dart b/lib/models/new_models/verify_otp_model.dart new file mode 100644 index 00000000..a1dfbb49 --- /dev/null +++ b/lib/models/new_models/verify_otp_model.dart @@ -0,0 +1,41 @@ + + +import 'package:flutter/material.dart'; + +class VerifyOtpModel { + final String ?userId; + final String ?userName; + final String ?email; + final String ?token; + final DateTime? validTo; + + VerifyOtpModel({ + this.userId, + this.userName, + this.email, + this.token, + this.validTo, + }); + + // Factory constructor to create an instance from a JSON map + factory VerifyOtpModel.fromJson(Map json) { + return VerifyOtpModel( + userId: json['userId'], + userName: json['userName'], + email: json['email'], + token: json['token'], + validTo: DateTime.parse(json['validTo']), + ); + } + + // Convert the instance to a JSON map + Map toJson() { + return { + 'userId': userId, + 'userName': userName, + 'email': email, + 'token': token, + 'validTo': validTo?.toIso8601String(), + }; + } +} diff --git a/lib/models/user.dart b/lib/models/user.dart index 40e95b58..ac3ace61 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -36,6 +36,10 @@ class User { bool? lockoutEnabled; int? accessFailedCount; List? assetGroups; + bool? employeeIsHMG; + bool? enableWifi; + bool? enableNFC; + bool?enableQR; User({ this.clientId, @@ -68,6 +72,10 @@ class User { this.lockoutEnd, this.lockoutEnabled, this.accessFailedCount, + this.employeeIsHMG, + this.enableNFC, + this.enableQR, + this.enableWifi, }); bool get isLiveToken => tokenlife != null && (DateTime.tryParse(tokenlife!)?.isAfter(DateTime.now()) ?? false); @@ -150,6 +158,10 @@ class User { map['lockoutEnd'] = lockoutEnd; map['lockoutEnabled'] = lockoutEnabled; map['accessFailedCount'] = accessFailedCount; + map['employeeIsHMG'] = employeeIsHMG; + map['enableWifi'] = enableWifi; + map['enableNFC'] = enableNFC; + map['enableQR'] = enableQR; return map; } @@ -207,6 +219,10 @@ class User { lockoutEnd = json['lockoutEnd']; lockoutEnabled = json['lockoutEnabled']; accessFailedCount = json['accessFailedCount']; + employeeIsHMG = json['employeeIsHMG']; + enableWifi = json['enableWifi']; + enableNFC = json['enableNFC']; + enableQR = json['enableQR']; } } diff --git a/lib/new_views/common_widgets/app_drawer.dart b/lib/new_views/common_widgets/app_drawer.dart index 034f427c..0558822d 100644 --- a/lib/new_views/common_widgets/app_drawer.dart +++ b/lib/new_views/common_widgets/app_drawer.dart @@ -6,6 +6,7 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/pages/login_page.dart'; +import 'package:test_sa/new_views/swipe_module/swipe_history_view.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; @@ -71,6 +72,9 @@ class AppDrawer extends StatelessWidget { // drawerItem("rate_us", context.translation.rateUs, context), // 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)), // 18.height, // drawerItem("report", context.translation.reportBg, context) /*.onPress(() => Navigator.of(context).pushNamed(ReportBugPage.id))*/, // 18.height, diff --git a/lib/new_views/common_widgets/app_text_form_field.dart b/lib/new_views/common_widgets/app_text_form_field.dart index f811e452..dd8bc5f7 100644 --- a/lib/new_views/common_widgets/app_text_form_field.dart +++ b/lib/new_views/common_widgets/app_text_form_field.dart @@ -37,6 +37,7 @@ class AppTextFormField extends StatefulWidget { final Color? backgroundColor; final bool alignLabelWithHint; final bool showShadow; + final bool showBorder; final EdgeInsets? contentPadding; final bool showWithoutDecoration; final VoidCallback? onTap; @@ -57,6 +58,7 @@ class AppTextFormField extends StatefulWidget { this.initialValue, // Provide default value this.enable = true, this.showSpeechToText = false, + this.showBorder = false, this.style, this.contentPadding, this.textAlign, @@ -243,6 +245,7 @@ class _AppTextFormFieldState extends State { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), + border: widget.showBorder?Border.all(color: AppColor.white10,width: 1):null, boxShadow: widget.showShadow ? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)] : null, ), child: textField); diff --git a/lib/new_views/forget_password_module/forget_passwod_verify_otp.dart b/lib/new_views/forget_password_module/forget_passwod_verify_otp.dart new file mode 100644 index 00000000..e6c81c27 --- /dev/null +++ b/lib/new_views/forget_password_module/forget_passwod_verify_otp.dart @@ -0,0 +1,166 @@ + + +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:pinput/pinput.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/new_models/general_response_model.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/forget_password_module/reset_password_view.dart'; + +class ForgetPasswordVerifyOtpView extends StatefulWidget { + Map data={}; + + ForgetPasswordVerifyOtpView({Key ?key,required this.data}) : super(key: key); + + @override + State createState() => _ForgetPasswordVerifyOtpViewState(); +} + +class _ForgetPasswordVerifyOtpViewState extends State { + String otp = ''; + Timer? _timer; + int _remainingSeconds = 180; // 3 minutes in seconds + + @override + void initState() { + super.initState(); + _startTimer(); + } + + @override + void dispose() { + _timer?.cancel(); + super.dispose(); + } + + void _startTimer() { + setState(() { + _remainingSeconds = 180; + }); + + _timer = Timer.periodic(const Duration(seconds: 1), (timer) { + if (_remainingSeconds > 0) { + setState(() { + _remainingSeconds--; + }); + } else { + _timer?.cancel(); + } + }); + } + + @override + Widget build(BuildContext context) { + final defaultPinTheme = PinTheme( + width: 68.toScreenWidth, + height: 86.toScreenHeight, + textStyle: const TextStyle( + fontSize: 22, + color: Colors.black, + ), + decoration: BoxDecoration( + color: AppColor.white10, + borderRadius: BorderRadius.circular(15), + border: Border.all(color: AppColor.white10, width: 1), + ), + ); + + final minutes = (_remainingSeconds ~/ 60).toString().padLeft(2, '0'); + final seconds = (_remainingSeconds % 60).toString().padLeft(2, '0'); + + return Scaffold( + body: Column( + children: [ + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + context.translation.otpVerification.heading2(context).custom(color: AppColor.white936, fontWeight: FontWeight.w500), + 8.height, + '${context.translation.pleaseEnterTheOtpSentTo} ${widget.data['phoneNumber']}'.bodyText2(context).custom(color: AppColor.neutral120, fontWeight: FontWeight.w500), + 40.height, + Center( + child: Pinput( + length: 4, + defaultPinTheme: defaultPinTheme, + focusedPinTheme: defaultPinTheme.copyWith( + decoration: defaultPinTheme.decoration?.copyWith( + border: Border.all(color: AppColor.neutral40, width: 1), + ), + ), + onCompleted: (pin) { + // setState(() { + otp = pin; + //}); + verifyOtp(); + }, + ), + ), + 18.height, + Row( + // mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + InkWell( + onTap: _remainingSeconds == 0 + ? () async { + UserProvider _userProvider = Provider.of(context, listen: false); + String employeeId = widget.data['employeeId']; + GeneralResponseModel response = await _userProvider.sendForgetPasswordOtp( + context: context, + employeeId: employeeId, + ); + print('Response of send OTP: ${response.toJson()}'); + + // Restart the timer + _startTimer(); + } + : null, + child: Text( + 'Resend', + style: TextStyle( + color: _remainingSeconds == 0 ? AppColor.blueStatus(context) : AppColor.neutral40, + fontWeight: FontWeight.w500, + fontSize: 16.toScreenWidth, + decorationColor: AppColor.primary30, + decoration: _remainingSeconds == 0 ? TextDecoration.underline : null, + ), + ), + ), + 7.width, + '$minutes:$seconds'.bodyText(context).custom(color: AppColor.neutral10), + ], + ), + ], + ), + ).center.expanded, + AppFilledButton( + label: context.translation.verify, + maxWidth: true, + onPressed: verifyOtp, + ), + ], + ).paddingOnly(start: 20, end: 20, bottom: 16), + ); + } + void verifyOtp() async{ + if (otp.isNotEmpty) { + UserProvider _userProvider = Provider.of(context, listen: false); + GeneralResponseModel generalResponseModel = await _userProvider.forgetPasswordValidateOtp( + context: context, + employeeId:widget.data['employeeId'], + otp: otp, + ); + if (generalResponseModel.isSuccess==true) { + Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => ResetPasswordView())); + } + } + } +} diff --git a/lib/new_views/forget_password_module/reset_password_view.dart b/lib/new_views/forget_password_module/reset_password_view.dart new file mode 100644 index 00000000..13197c9e --- /dev/null +++ b/lib/new_views/forget_password_module/reset_password_view.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/new_models/general_response_model.dart'; +import 'package:test_sa/models/new_models/update_password.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/new_views/pages/login_page.dart'; + +import '../../controllers/providers/api/user_provider.dart'; +import '../../controllers/validator/validator.dart'; + +class ResetPasswordView extends StatefulWidget { + static const String routeName = "/resetPassword"; + + ResetPasswordView({Key? key}) : super(key: key); + + @override + State createState() => _ResetPasswordViewState(); +} + +class _ResetPasswordViewState extends State { + bool _passwordVisible = false; + bool _confirmPasswordVisible = false; + + String newPassword = ""; + String confirmPassword = ""; + + final GlobalKey _formKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Form( + key: _formKey, + child: Scaffold( + body: Column( + children: [ + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + context.translation.resetPassword.heading2(context).custom(color: AppColor.white936, fontWeight: FontWeight.w500), + 8.height, + context.translation.pleaseEnterTheNewPassword.bodyText2(context).custom(color: AppColor.neutral120, fontWeight: FontWeight.w500), + 32.height, + AppTextFormField( + initialValue: "", + showBorder: true, + validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField, + labelText: context.translation.password, + obscureText: !_passwordVisible, + suffixIcon: Icon( + // Based on passwordVisible state choose the icon + _passwordVisible ? Icons.visibility : Icons.visibility_off, + color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, + ).paddingOnly(end: 12).onPress(() { + setState(() { + _passwordVisible = !_passwordVisible; + }); + }), + onSaved: (value) { + newPassword = value; + }, + ), + 16.height, + AppTextFormField( + initialValue: "", + labelText: context.translation.confirmPassword, + obscureText: !_confirmPasswordVisible, + showBorder: true, + validator: (value) => Validator.isValidPassword(value!) + ? null + : value.isEmpty + ? context.translation.requiredField + : context.translation.passwordLengthMessage, + onSaved: (value) { + confirmPassword = value; + }, + suffixIcon: Icon( + _confirmPasswordVisible ? Icons.visibility : Icons.visibility_off, + color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, + ).paddingOnly(end: 12).onPress(() { + setState(() { + _confirmPasswordVisible = !_confirmPasswordVisible; + }); + }), + ), + ], + ), + ).center.expanded, + AppFilledButton(label: context.translation.resetPassword, maxWidth: true, onPressed: () => _resetPassword(context)), + ], + ).paddingOnly(start: 16, end: 16, bottom: 24, top: 24), + ), + ); + } + + Future _resetPassword(BuildContext context) async { + if (!_formKey.currentState!.validate()) return; + _formKey.currentState?.save(); + if (newPassword != confirmPassword) { + Fluttertoast.showToast(msg: 'Password not matched try again'); + } else { + UserProvider userProvider = Provider.of(context,listen: false); + UpdatePasswordModel updatePasswordModel = + UpdatePasswordModel(password: newPassword, confirmPassword: confirmPassword, userId: userProvider.verifyOtpModel.userId, token: userProvider.verifyOtpModel.token); + GeneralResponseModel generalResponseModel = await userProvider.updateNewPassword(context: context, updatePasswordModel: updatePasswordModel); + if (generalResponseModel.isSuccess==true) { + newPassword = ''; + confirmPassword = ''; + Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); + } + } + } +} diff --git a/lib/new_views/pages/land_page/land_page.dart b/lib/new_views/pages/land_page/land_page.dart index 4b021818..282963ed 100644 --- a/lib/new_views/pages/land_page/land_page.dart +++ b/lib/new_views/pages/land_page/land_page.dart @@ -103,7 +103,11 @@ class _LandPageState extends State { Widget build(BuildContext context) { if (_userProvider == null) { _userProvider = Provider.of(context, listen: false); - if (_userProvider!.isUserConfirmSwipe) { + if (_userProvider!.user != null && _userProvider!.user!.employeeIsHMG==false) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _userProvider!.getSwipeLastTransaction(userId: _userProvider!.user!.userID!); + }); + } _pages = [ DashboardView(onDrawerPress: (() { _scaffoldKey.currentState!.isDrawerOpen ? _scaffoldKey.currentState!.closeDrawer() : _scaffoldKey.currentState!.openDrawer(); @@ -114,7 +118,7 @@ class _LandPageState extends State { // if (_userProvider!.user!.type != UsersTypes.engineer) const CalendarPage(), const MyAssetsPage(fromBottomBar: true), ]; - } + checkLocalAuth(); } @@ -144,7 +148,7 @@ class _LandPageState extends State { )) : null, drawer: const AppDrawer(), - body: _pages.isEmpty ? MarkAttendanceWidget() : _pages[currentPageIndex], + body: _pages[currentPageIndex], bottomNavigationBar: _pages.isEmpty ? null : AppBottomNavigationBar( diff --git a/lib/new_views/pages/land_page/mark_attendance_widget.dart b/lib/new_views/pages/land_page/mark_attendance_widget.dart index ab5769b1..1ab12c67 100644 --- a/lib/new_views/pages/land_page/mark_attendance_widget.dart +++ b/lib/new_views/pages/land_page/mark_attendance_widget.dart @@ -1,866 +1,866 @@ -import 'dart:async'; -import 'dart:developer'; -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:geolocator/geolocator.dart'; -import 'package:huawei_location/huawei_location.dart'; -import 'package:nfc_manager/nfc_manager.dart'; -import 'package:permission_handler/permission_handler.dart'; -import 'package:provider/provider.dart'; -import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; -// import 'package:platform_device_id/platform_device_id.dart'; -import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart'; -import 'package:test_sa/extensions/enum_extensions.dart'; -import 'package:test_sa/extensions/text_extensions.dart'; -import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/helper/utils.dart'; -import 'package:test_sa/models/enums/swipe_type.dart'; -import 'package:test_sa/models/lookup.dart'; -import 'package:test_sa/models/new_models/swipe_model.dart'; -import 'package:test_sa/nfc/nfc_reader_sheet.dart'; -import 'package:test_sa/utilities/Location.dart' as location; -import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart'; -import 'package:test_sa/views/widgets/dialogs/success_dialog.dart'; -import 'package:test_sa/views/widgets/qr_scanner_dialog.dart'; -import 'package:wifi_iot/wifi_iot.dart'; - -import '../../app_style/app_color.dart'; - -class MarkAttendanceWidget extends StatefulWidget { - // DashboardProviderModel model; - double topPadding; - bool isFromDashboard; - - MarkAttendanceWidget( {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key); - // todo MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key); - - @override - _MarkAttendanceWidgetState createState() { - return _MarkAttendanceWidgetState(); - } -} - -class _MarkAttendanceWidgetState extends State { - bool isNfcEnabled = false, isNfcLocationEnabled = false, isQrEnabled = false, isQrLocationEnabled = false, isWifiEnabled = false, isWifiLocationEnabled = false; - - int _locationUpdateCbId = 0; - - @override - void initState() { - super.initState(); - checkAttendanceAvailability(); - } - - void checkAttendanceAvailability() async { - bool isAvailable = await NfcManager.instance.isAvailable(); - // setState(() { - // AppState().privilegeListModel!.forEach((PrivilegeListModel element) { - // if (element.serviceName == "enableNFC") { - // if (isAvailable) if (element.previlege ?? false) isNfcEnabled = true; - // } else if (element.serviceName == "enableQR") { - // if (element.previlege ?? false) isQrEnabled = true; - // } else if (element.serviceName == "enableWIFI") { - // if (element.previlege ?? false) isWifiEnabled = true; - // } else if (element.serviceName!.trim() == "enableLocationNFC") { - // if (element.previlege ?? false) isNfcLocationEnabled = true; - // } else if (element.serviceName == "enableLocationQR") { - // if (element.previlege ?? false) isQrLocationEnabled = true; - // } else if (element.serviceName == "enableLocationWIFI") { - // if (element.previlege ?? false) isWifiLocationEnabled = true; - // } - // }); - // }); - } - - void checkHuaweiLocationPermission(String attendanceType) async { - // Permission_Handler permissionHandler = PermissionHandler(); - location.Location.isEnabled((bool isEnabled) async { - if (isEnabled) { - location.Location.havePermission((bool permission) async { - if (permission) { - getHuaweiCurrentLocation(attendanceType); - } else { - bool has = await requestPermissions(); - if (has) { - getHuaweiCurrentLocation(attendanceType); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to give location permission to mark attendance", - onTap: () { - Navigator.pop(context); - }, - ), - ); - } - } - }); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to enable location services to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openLocationSettings(); - }, - ), - ); - } - }); - - // if (await permissionHandler.hasLocationPermission()) { - // getHuaweiCurrentLocation(attendanceType); - // } else { - // bool has = await requestPermissions(); - // if (has) { - // getHuaweiCurrentLocation(attendanceType); - // } else { - // showDialog( - // context: context, - // builder: (BuildContext cxt) => ConfirmDialog( - // message: "You need to give location permission to mark attendance", - // onTap: () { - // Navigator.pop(context); - // }, - // ), - // ); - // } - // } - } - - Future requestPermissions() async { - var result = await [ - Permission.location, - ].request(); - return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted); - } - - @override - void dispose() { - super.dispose(); - // Stop Session - NfcManager.instance.stopSession(); - } - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: widget.topPadding), - decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white), - width: double.infinity, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - // LocaleKeys.markAttendance.tr().toSectionHeading(), - // LocaleKeys.selectMethodOfAttendance.tr().toText11(color: const Color(0xff535353)), - GridView( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: const EdgeInsets.only(bottom: 0, top: 21), - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8), - children: [ - attendanceMethod(SwipeTypeEnum.NFC.name, Icons.nfc, true, () { - log('i am here...nfc'); - handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: true); - return; - // if (AppState().getIsHuawei) { - if (false) { - checkHuaweiLocationPermission("NFC"); - } else { - location.Location.isEnabled((bool isEnabled) { - if (isEnabled) { - location.Location.havePermission((bool permission) { - if (permission) { - Utils.showLoading(context); - location.Location.getCurrentLocation( - (Position position, bool isMocked) { - if (isMocked) { - Utils.hideLoading(context); - markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); - } else { - Utils.hideLoading(context); - //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); - } - }, - () { - Utils.hideLoading(context); - Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); - }, - context, - ); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to give location permission to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openAppSettings(); - }, - ), - ); - } - }); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to enable location services to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openLocationSettings(); - }, - ), - ); - } - }); - } - }), - //if (isWifiEnabled) //todo - attendanceMethod("Wifi", Icons.wifi, isWifiEnabled, () { - // if (AppState().getIsHuawei) { - if (false) { - checkHuaweiLocationPermission("WIFI"); - } else { - location.Location.isEnabled((bool isEnabled) { - if (isEnabled) { - location.Location.havePermission((bool permission) { - if (permission) { - Utils.showLoading(context); - location.Location.getCurrentLocation( - (Position position, bool isMocked) { - if (isMocked) { - Utils.hideLoading(context); - markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); - } else { - Utils.hideLoading(context); - //todo performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); - } - }, - () { - Utils.hideLoading(context); - Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); - }, - context, - ); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to give location permission to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openAppSettings(); - }, - ), - ); - } - }); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to enable location services to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openLocationSettings(); - }, - ), - ); - } - }); - } - }), - // if (isQrEnabled) //todo - attendanceMethod(SwipeTypeEnum.QR.name, Icons.qr_code_2, true, () async { - handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: true); - return; - // if (AppState().getIsHuawei) { - if (false) { - checkHuaweiLocationPermission("QR"); - } else { - location.Location.isEnabled((bool isEnabled) { - if (isEnabled) { - location.Location.havePermission((bool permission) { - if (permission) { - Utils.showLoading(context); - location.Location.getCurrentLocation( - (Position position, bool isMocked) { - if (isMocked) { - Utils.hideLoading(context); - markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); - } else { - Utils.hideLoading(context); - //todo performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); - } - }, - () { - Utils.hideLoading(context); - Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); - }, - context, - ); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to give location permission to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openAppSettings(); - }, - ), - ); - } - }); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to enable location services to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openLocationSettings(); - }, - ), - ); - } - }); - } - }), - ], - ) - ], - ), - ); - } - - void handleSwipe({required SwipeTypeEnum swipeType,required bool isEnable,}){ - log('handle swipe value is ${swipeType.name}'); - // if (AppState().getIsHuawei) { - if (false) { - checkHuaweiLocationPermission("NFC"); - } else { - location.Location.isEnabled((bool isEnabled) { - if (isEnabled) { - location.Location.havePermission((bool permission) { - if (permission) { - Utils.showLoading(context); - location.Location.getCurrentLocation( - (Position position, bool isMocked) { - if (isMocked) { - Utils.hideLoading(context); - markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? ""); - } else { - Utils.hideLoading(context); - //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); - handleSwipeOperation(swipeType: swipeType,lat: position.latitude,lang: position.longitude); - } - }, - () { - Utils.hideLoading(context); - Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); - }, - context, - ); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to give location permission to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openAppSettings(); - }, - ), - ); - } - }); - } else { - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: "You need to enable location services to mark attendance", - onTap: () async { - Navigator.pop(context); - await Geolocator.openLocationSettings(); - }, - ), - ); - } - }); - } - } - - void handleSwipeOperation({required SwipeTypeEnum swipeType,double ?lat, double ?lang}){ - switch(swipeType){ - case SwipeTypeEnum.NFC: - handleNfcAttendance(latitude: lat,longitude: lang); - return; - case SwipeTypeEnum.QR: - performQrCodeAttendance(latitude: lat,longitude: lang); - return; - case SwipeTypeEnum.Wifi: - return; - - } - } - - void getHuaweiCurrentLocation(String attendanceType) async { - try { - Utils.showLoading(context); - FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService(); - LocationRequest locationRequest = LocationRequest(); - locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; - locationRequest.interval = 500; - List locationRequestList = [locationRequest]; - LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList); - - late StreamSubscription _streamSubscription; - int requestCode = (await (locationService.requestLocationUpdates(locationRequest)))!; - - _streamSubscription = locationService.onLocationData!.listen( - (Location location) async { - Utils.hideLoading(context); - await locationService.removeLocationUpdates(requestCode); - if (attendanceType == "QR") { - // todo performQrCodeAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); - } - if (attendanceType == "WIFI") { - // todo performWifiAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); - } - if (attendanceType == "NFC") { - //todo performNfcAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); - } - requestCode = 0; - }, - ); - - // locationService.checkLocationSettings(locationSettingsRequest).then((settings) async { - // await locationService.getLastLocation().then((value) { - // if (value.latitude == null || value.longitude == null) { - // showDialog( - // context: context, - // builder: (BuildContext cxt) => ConfirmDialog( - // message: "Unable to get your location, Please check your location settings & try again.", - // onTap: () { - // Navigator.pop(context); - // }, - // ), - // ); - // } else { - // if (attendanceType == "QR") { - // performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); - // } - // if (attendanceType == "WIFI") { - // performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); - // } - // if (attendanceType == "NFC") { - // performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); - // } - // } - // }).catchError((error) { - // log("HUAWEI LOCATION getLastLocation ERROR!!!!!"); - // log(error); - // }); - // }).catchError((error) { - // log("HUAWEI LOCATION checkLocationSettings ERROR!!!!!"); - // log(error); - // if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") { - // // Location service not enabled. - // } - // }); - } catch (error) { - log("HUAWEI LOCATION ERROR!!!!!"); - log('$error'); - Utils.hideLoading(context); - // Utils.handleException(error, context, null); - } - } - - Future handleNfcAttendance({double? latitude = 0, double? longitude = 0}) async { - final dashBoardProvider = Provider.of(context, listen: false); - - if (Platform.isIOS) { - Utils.readNFc(onRead: (String nfcId) async { - await _processNfcAttendance(dashBoardProvider, nfcId, latitude, longitude); - }); - } else { - showNfcReader(context, onNcfScan: (String? nfcId) async { - await _processNfcAttendance(dashBoardProvider, nfcId ?? '', latitude, longitude); - }); - } - } - - - Future _processNfcAttendance( - DashBoardProvider dashBoardProvider, - String nfcId, - double? latitude, - double? longitude, - ) async { - Utils.showLoading(context); - try { - final swipeModel = Swipe( - swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), - value: nfcId, - latitude: latitude, - longitude: longitude, - ); - - final swipeResponse = await dashBoardProvider.makeSwipe(model: swipeModel); - log('swipe response i got is ${swipeResponse.toJson()}'); - - if (swipeResponse.responseCode != 1) { - Utils.hideLoading(context); - _showErrorDialog(swipeResponse.message ?? "Unexpected error occurred"); - } else { - final isSuccess = swipeResponse.data; - log('nfc swipe response is ${isSuccess}'); - if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); - Utils.hideLoading(context); - _showSuccessDialog(); - } - } catch (error) { - Utils.hideLoading(context); - // Uncomment below line for error handling if needed - // Utils.handleException(error, context, null); - } - } - - - void _showErrorDialog(String message) { - showDialog( - context: context, - builder: (context) => ConfirmDialog( - message: message, - onTap: () => Navigator.pop(context), - ), - ); - } - - void _showSuccessDialog() { - showMDialog( - context, - backgroundColor: Colors.transparent, - isDismissable: true, - child: SuccessDialog(widget.isFromDashboard), - ); - } - - - //older code.... - Future performNfcAttendance({double? lat = 0, double ?lng = 0}) async { - DashBoardProvider dashBoardProvider = Provider.of(context,listen:false); - if (Platform.isIOS) { - Utils.readNFc(onRead: (String nfcId) async { - Utils.showLoading(context); - try { - SwipeModel? swipeResponse = await dashBoardProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '', latitude: lat, longitude: lng)); - if (swipeResponse.responseCode != 1) { - Utils.hideLoading(context); - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: swipeResponse.message ?? "Unexpected error occurred", - onTap: () { - Navigator.pop(context); - }, - ), - ); - } else { - bool status = swipeResponse.data; - if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); - Utils.hideLoading(context); - showMDialog( - context, - backgroundColor: Colors.transparent, - isDismissable: true, - child: SuccessDialog(widget.isFromDashboard), - ); - } - } catch (ex) { - Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - } - }); - } else { - showNfcReader(context, onNcfScan: (String? nfcId) async { - Utils.showLoading(context); - try { - SwipeModel? swipeResponse = await dashBoardProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId??'', latitude: lat, longitude: lng)); - log('api response i got is ${swipeResponse.toJson()}'); - if (swipeResponse.responseCode != 1) { - Utils.hideLoading(context); - showDialog( - context: context, - builder: (BuildContext cxt) => ConfirmDialog( - message: swipeResponse.message ?? "Unexpected error occurred", - onTap: () { - Navigator.pop(context); - }, - ), - ); - } else { - bool status = swipeResponse.data; //use this status to get transactions. - if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); - Utils.hideLoading(context); - showMDialog( - context, - backgroundColor: Colors.transparent, - isDismissable: true, - child: SuccessDialog(widget.isFromDashboard), - ); - } - } catch (ex) { - Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - } - // Utils.showLoading(context); - // try { - // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); - // if (g?.messageStatus != 1) { - // Utils.hideLoading(context); - // showDialog( - // context: context, - // builder: (BuildContext cxt) => ConfirmDialog( - // message: g?.errorEndUserMessage ?? "Unexpected error occurred", - // onTap: () { - // Navigator.pop(context); - // }, - // ), - // ); - // } else { - // bool status = await model.fetchAttendanceTracking(context); - // Utils.hideLoading(context); - // showMDialog( - // context, - // backgroundColor: Colors.transparent, - // isDismissable: false, - // child: SuccessDialog(widget.isFromDashboard), - // ); - // } - // } catch (ex) { - // log(ex); - // Utils.hideLoading(context); - // // Utils.handleException(ex, context, (String msg) { - // // Utils.confirmDialog(context, msg); - // // }); - // } - }); - } - } - - - - void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true, bool isBusniessCard = false}) async { - return showDialog( - context: context, - barrierDismissible: isDismissable, - builder: (context) { - return Dialog( - shape: isBusniessCard - ? const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(15.0), - ), - ) - : null, - backgroundColor: backgroundColor, - child: child, - ); - }, - ); - } - // - // Future checkSession() async { - // try { - // Utils.showLoading(context); - // await DashboardApiClient().getOpenMissingSwipes(); - // Utils.hideLoading(context); - // return true; - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // return false; - // } - // } - - - //TODO need to confirm .... - // Future performWifiAttendance({double? latitude, double? lng}) async { - // // if (Platform.isAndroid) { - // // if (!(await checkSession())) { - // // return; - // // } - // // } - // Utils.showLoading(context); - // bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "", - // password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false); - // - // if (Platform.isIOS) { - // if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) { - // isConnected = true; - // } else { - // isConnected = false; - // } - // } - // - // if (isConnected && AppState().isAuthenticated) { - // await WiFiForIoTPlugin.forceWifiUsage(true); - // await Future.delayed(const Duration(seconds: 6)); - // try { - // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng); - // bool status = await model.fetchAttendanceTracking(context); - // Utils.hideLoading(context); - // await closeWifiRequest(); - // if (g?.messageStatus == 2) { - // showDialog( - // barrierDismissible: true, - // context: context, - // builder: (cxt) => ConfirmDialog( - // message: g?.errorEndUserMessage ?? "", - // onTap: () { - // Navigator.pop(context); - // }, - // onCloseTap: () {}, - // ), - // ); - // } else { - // showMDialog( - // context, - // backgroundColor: Colors.transparent, - // isDismissable: false, - // child: SuccessDialog(widget.isFromDashboard), - // ); - // } - // } catch (ex) { - // await closeWifiRequest(); - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } - // } else { - // if (AppState().isAuthenticated) { - // Utils.hideLoading(context); - // Utils.confirmDialog(context, "LocaleKeys.comeNearHMGWifi.tr()"); - // } else { - // await closeWifiRequest(); - // } - // } - // } - - Future closeWifiRequest() async { - if (Platform.isAndroid) { - await WiFiForIoTPlugin.forceWifiUsage(false); - } - return await WiFiForIoTPlugin.disconnect(); - } - - Future performQrCodeAttendance( {double ? latitude , double ?longitude}) async { - DashBoardProvider dashBoardProvider = Provider.of(context,listen: false); - var qrCodeValue = await Navigator.of(context).push( - MaterialPageRoute( - builder: (BuildContext context) => QrScannerDialog(), - ), - ); - if (qrCodeValue != null) { - Utils.showLoading(context); - try { - final swipeModel = Swipe( - swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(), - value: qrCodeValue, - latitude: latitude, - longitude: longitude, - ); - log('model i got to scan qr is ${swipeModel.toJson()}'); - final swipeResponse = await dashBoardProvider.makeSwipe(model: swipeModel); - log('response of swipe is ${swipeResponse.toJson()}'); - - bool status = await swipeResponse.data; - Utils.hideLoading(context); - if (swipeResponse.responseCode == 2) { - showDialog( - barrierDismissible: true, - context: context, - builder: (cxt) => ConfirmDialog( - message: swipeResponse.message ?? "", - onTap: () { - Navigator.pop(context); - }, - onCloseTap: () {}, - ), - ); - } else { - showMDialog( - context, - backgroundColor: Colors.transparent, - isDismissable: true, - child: SuccessDialog(widget.isFromDashboard), - ); - } - } catch (ex) { - log('$ex'); - Utils.hideLoading(context); - //this need to confirm where it comes.. - // Utils.handleException(ex, context, null); - } - } - } - - void markFakeAttendance(dynamic sourceName, String lat, String long) async { - Utils.showLoading(context); - try { - // await DashboardApiClient().markFakeLocation(sourceName: sourceName, lat: lat, long: long); - Utils.hideLoading(context); - Utils.confirmDialog(context, "LocaleKeys.fakeLocation.tr()"); - } catch (ex) { - log('$ex'); - Utils.hideLoading(context); - //Utils.handleException(ex, context, null); - } - } - - Widget attendanceMethod(String title, IconData iconData, bool isEnabled, VoidCallback onPress) => Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(15), - color: isEnabled ? null : Colors.grey.withOpacity(.5), - gradient: isEnabled - ? const LinearGradient( - transform: GradientRotation(.64), - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [ - //ToDo set Colors according to design provided by designer... - Colors.blue, - Colors.green, - // AppColor.gradiantEndColor, - // MyColors.gradiantStartColor, - ], - ) - : null, - ), - clipBehavior: Clip.antiAlias, - padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // SvgPicture.asset(image, color: Colors.white, alignment: Alignment.topLeft).expanded, - Icon(iconData, color: isEnabled ? AppColor.black35 : Colors.grey), - title.heading6(context), - // title.toText17(isBold: true, color: Colors.white), - ], - ), - ).onPress( - () { - log('isEnabled is ${!isEnabled}'); - if (!isEnabled) return; - onPress(); - }, - ); -} +// import 'dart:async'; +// import 'dart:developer'; +// import 'dart:io'; +// +// import 'package:flutter/material.dart'; +// import 'package:flutter_svg/flutter_svg.dart'; +// import 'package:geolocator/geolocator.dart'; +// import 'package:huawei_location/huawei_location.dart'; +// import 'package:nfc_manager/nfc_manager.dart'; +// import 'package:permission_handler/permission_handler.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; +// // import 'package:platform_device_id/platform_device_id.dart'; +// import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart'; +// import 'package:test_sa/extensions/enum_extensions.dart'; +// import 'package:test_sa/extensions/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/helper/utils.dart'; +// import 'package:test_sa/models/enums/swipe_type.dart'; +// import 'package:test_sa/models/lookup.dart'; +// import 'package:test_sa/models/new_models/swipe_model.dart'; +// import 'package:test_sa/nfc/nfc_reader_sheet.dart'; +// import 'package:test_sa/utilities/Location.dart' as location; +// import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart'; +// import 'package:test_sa/views/widgets/dialogs/success_dialog.dart'; +// import 'package:test_sa/views/widgets/qr_scanner_dialog.dart'; +// import 'package:wifi_iot/wifi_iot.dart'; +// +// import '../../app_style/app_color.dart'; +// +// class MarkAttendanceWidget extends StatefulWidget { +// // DashboardProviderModel model; +// double topPadding; +// bool isFromDashboard; +// +// MarkAttendanceWidget( {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key); +// // todo MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key); +// +// @override +// _MarkAttendanceWidgetState createState() { +// return _MarkAttendanceWidgetState(); +// } +// } +// +// class _MarkAttendanceWidgetState extends State { +// bool isNfcEnabled = false, isNfcLocationEnabled = false, isQrEnabled = false, isQrLocationEnabled = false, isWifiEnabled = false, isWifiLocationEnabled = false; +// +// int _locationUpdateCbId = 0; +// +// @override +// void initState() { +// super.initState(); +// checkAttendanceAvailability(); +// } +// +// void checkAttendanceAvailability() async { +// bool isAvailable = await NfcManager.instance.isAvailable(); +// // setState(() { +// // AppState().privilegeListModel!.forEach((PrivilegeListModel element) { +// // if (element.serviceName == "enableNFC") { +// // if (isAvailable) if (element.previlege ?? false) isNfcEnabled = true; +// // } else if (element.serviceName == "enableQR") { +// // if (element.previlege ?? false) isQrEnabled = true; +// // } else if (element.serviceName == "enableWIFI") { +// // if (element.previlege ?? false) isWifiEnabled = true; +// // } else if (element.serviceName!.trim() == "enableLocationNFC") { +// // if (element.previlege ?? false) isNfcLocationEnabled = true; +// // } else if (element.serviceName == "enableLocationQR") { +// // if (element.previlege ?? false) isQrLocationEnabled = true; +// // } else if (element.serviceName == "enableLocationWIFI") { +// // if (element.previlege ?? false) isWifiLocationEnabled = true; +// // } +// // }); +// // }); +// } +// +// void checkHuaweiLocationPermission(String attendanceType) async { +// // Permission_Handler permissionHandler = PermissionHandler(); +// location.Location.isEnabled((bool isEnabled) async { +// if (isEnabled) { +// location.Location.havePermission((bool permission) async { +// if (permission) { +// getHuaweiCurrentLocation(attendanceType); +// } else { +// bool has = await requestPermissions(); +// if (has) { +// getHuaweiCurrentLocation(attendanceType); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to give location permission to mark attendance", +// onTap: () { +// Navigator.pop(context); +// }, +// ), +// ); +// } +// } +// }); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to enable location services to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openLocationSettings(); +// }, +// ), +// ); +// } +// }); +// +// // if (await permissionHandler.hasLocationPermission()) { +// // getHuaweiCurrentLocation(attendanceType); +// // } else { +// // bool has = await requestPermissions(); +// // if (has) { +// // getHuaweiCurrentLocation(attendanceType); +// // } else { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "You need to give location permission to mark attendance", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // ), +// // ); +// // } +// // } +// } +// +// Future requestPermissions() async { +// var result = await [ +// Permission.location, +// ].request(); +// return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted); +// } +// +// @override +// void dispose() { +// super.dispose(); +// // Stop Session +// NfcManager.instance.stopSession(); +// } +// +// @override +// Widget build(BuildContext context) { +// return Container( +// padding: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: widget.topPadding), +// decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white), +// width: double.infinity, +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisSize: MainAxisSize.min, +// children: [ +// // LocaleKeys.markAttendance.tr().toSectionHeading(), +// // LocaleKeys.selectMethodOfAttendance.tr().toText11(color: const Color(0xff535353)), +// GridView( +// physics: const NeverScrollableScrollPhysics(), +// shrinkWrap: true, +// padding: const EdgeInsets.only(bottom: 0, top: 21), +// gridDelegate: +// SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8), +// children: [ +// attendanceMethod(SwipeTypeEnum.NFC.name, Icons.nfc, true, () { +// log('i am here...nfc'); +// handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: true); +// return; +// // if (AppState().getIsHuawei) { +// if (false) { +// checkHuaweiLocationPermission("NFC"); +// } else { +// location.Location.isEnabled((bool isEnabled) { +// if (isEnabled) { +// location.Location.havePermission((bool permission) { +// if (permission) { +// Utils.showLoading(context); +// location.Location.getCurrentLocation( +// (Position position, bool isMocked) { +// if (isMocked) { +// Utils.hideLoading(context); +// markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); +// } else { +// Utils.hideLoading(context); +// //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); +// } +// }, +// () { +// Utils.hideLoading(context); +// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); +// }, +// context, +// ); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to give location permission to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openAppSettings(); +// }, +// ), +// ); +// } +// }); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to enable location services to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openLocationSettings(); +// }, +// ), +// ); +// } +// }); +// } +// }), +// //if (isWifiEnabled) //todo +// attendanceMethod("Wifi", Icons.wifi, isWifiEnabled, () { +// // if (AppState().getIsHuawei) { +// if (false) { +// checkHuaweiLocationPermission("WIFI"); +// } else { +// location.Location.isEnabled((bool isEnabled) { +// if (isEnabled) { +// location.Location.havePermission((bool permission) { +// if (permission) { +// Utils.showLoading(context); +// location.Location.getCurrentLocation( +// (Position position, bool isMocked) { +// if (isMocked) { +// Utils.hideLoading(context); +// markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); +// } else { +// Utils.hideLoading(context); +// //todo performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); +// } +// }, +// () { +// Utils.hideLoading(context); +// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); +// }, +// context, +// ); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to give location permission to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openAppSettings(); +// }, +// ), +// ); +// } +// }); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to enable location services to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openLocationSettings(); +// }, +// ), +// ); +// } +// }); +// } +// }), +// // if (isQrEnabled) //todo +// attendanceMethod(SwipeTypeEnum.QR.name, Icons.qr_code_2, true, () async { +// handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: true); +// return; +// // if (AppState().getIsHuawei) { +// if (false) { +// checkHuaweiLocationPermission("QR"); +// } else { +// location.Location.isEnabled((bool isEnabled) { +// if (isEnabled) { +// location.Location.havePermission((bool permission) { +// if (permission) { +// Utils.showLoading(context); +// location.Location.getCurrentLocation( +// (Position position, bool isMocked) { +// if (isMocked) { +// Utils.hideLoading(context); +// markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); +// } else { +// Utils.hideLoading(context); +// //todo performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); +// } +// }, +// () { +// Utils.hideLoading(context); +// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); +// }, +// context, +// ); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to give location permission to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openAppSettings(); +// }, +// ), +// ); +// } +// }); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to enable location services to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openLocationSettings(); +// }, +// ), +// ); +// } +// }); +// } +// }), +// ], +// ) +// ], +// ), +// ); +// } +// +// void handleSwipe({required SwipeTypeEnum swipeType,required bool isEnable,}){ +// log('handle swipe value is ${swipeType.name}'); +// // if (AppState().getIsHuawei) { +// if (false) { +// checkHuaweiLocationPermission("NFC"); +// } else { +// location.Location.isEnabled((bool isEnabled) { +// if (isEnabled) { +// location.Location.havePermission((bool permission) { +// if (permission) { +// Utils.showLoading(context); +// location.Location.getCurrentLocation( +// (Position position, bool isMocked) { +// if (isMocked) { +// Utils.hideLoading(context); +// markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? ""); +// } else { +// Utils.hideLoading(context); +// //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); +// handleSwipeOperation(swipeType: swipeType,lat: position.latitude,lang: position.longitude); +// } +// }, +// () { +// Utils.hideLoading(context); +// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); +// }, +// context, +// ); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to give location permission to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openAppSettings(); +// }, +// ), +// ); +// } +// }); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to enable location services to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openLocationSettings(); +// }, +// ), +// ); +// } +// }); +// } +// } +// +// void handleSwipeOperation({required SwipeTypeEnum swipeType,double ?lat, double ?lang}){ +// switch(swipeType){ +// case SwipeTypeEnum.NFC: +// handleNfcAttendance(latitude: lat,longitude: lang); +// return; +// case SwipeTypeEnum.QR: +// performQrCodeAttendance(latitude: lat,longitude: lang); +// return; +// case SwipeTypeEnum.Wifi: +// return; +// +// } +// } +// +// void getHuaweiCurrentLocation(String attendanceType) async { +// try { +// Utils.showLoading(context); +// FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService(); +// LocationRequest locationRequest = LocationRequest(); +// locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; +// locationRequest.interval = 500; +// List locationRequestList = [locationRequest]; +// LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList); +// +// late StreamSubscription _streamSubscription; +// int requestCode = (await (locationService.requestLocationUpdates(locationRequest)))!; +// +// _streamSubscription = locationService.onLocationData!.listen( +// (Location location) async { +// Utils.hideLoading(context); +// await locationService.removeLocationUpdates(requestCode); +// if (attendanceType == "QR") { +// // todo performQrCodeAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); +// } +// if (attendanceType == "WIFI") { +// // todo performWifiAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); +// } +// if (attendanceType == "NFC") { +// //todo performNfcAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? ""); +// } +// requestCode = 0; +// }, +// ); +// +// // locationService.checkLocationSettings(locationSettingsRequest).then((settings) async { +// // await locationService.getLastLocation().then((value) { +// // if (value.latitude == null || value.longitude == null) { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "Unable to get your location, Please check your location settings & try again.", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // ), +// // ); +// // } else { +// // if (attendanceType == "QR") { +// // performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); +// // } +// // if (attendanceType == "WIFI") { +// // performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); +// // } +// // if (attendanceType == "NFC") { +// // performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); +// // } +// // } +// // }).catchError((error) { +// // log("HUAWEI LOCATION getLastLocation ERROR!!!!!"); +// // log(error); +// // }); +// // }).catchError((error) { +// // log("HUAWEI LOCATION checkLocationSettings ERROR!!!!!"); +// // log(error); +// // if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") { +// // // Location service not enabled. +// // } +// // }); +// } catch (error) { +// log("HUAWEI LOCATION ERROR!!!!!"); +// log('$error'); +// Utils.hideLoading(context); +// // Utils.handleException(error, context, null); +// } +// } +// +// Future handleNfcAttendance({double? latitude = 0, double? longitude = 0}) async { +// final dashBoardProvider = Provider.of(context, listen: false); +// +// if (Platform.isIOS) { +// Utils.readNFc(onRead: (String nfcId) async { +// await _processNfcAttendance(dashBoardProvider, nfcId, latitude, longitude); +// }); +// } else { +// showNfcReader(context, onNcfScan: (String? nfcId) async { +// await _processNfcAttendance(dashBoardProvider, nfcId ?? '', latitude, longitude); +// }); +// } +// } +// +// +// Future _processNfcAttendance( +// DashBoardProvider dashBoardProvider, +// String nfcId, +// double? latitude, +// double? longitude, +// ) async { +// Utils.showLoading(context); +// try { +// final swipeModel = Swipe( +// swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), +// value: nfcId, +// latitude: latitude, +// longitude: longitude, +// ); +// +// final swipeResponse = await dashBoardProvider.makeSwipe(model: swipeModel); +// log('swipe response i got is ${swipeResponse.toJson()}'); +// +// if (swipeResponse.responseCode != 1) { +// Utils.hideLoading(context); +// _showErrorDialog(swipeResponse.message ?? "Unexpected error occurred"); +// } else { +// final isSuccess = swipeResponse.data; +// log('nfc swipe response is ${isSuccess}'); +// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); +// Utils.hideLoading(context); +// _showSuccessDialog(); +// } +// } catch (error) { +// Utils.hideLoading(context); +// // Uncomment below line for error handling if needed +// // Utils.handleException(error, context, null); +// } +// } +// +// +// void _showErrorDialog(String message) { +// showDialog( +// context: context, +// builder: (context) => ConfirmDialog( +// message: message, +// onTap: () => Navigator.pop(context), +// ), +// ); +// } +// +// void _showSuccessDialog() { +// showMDialog( +// context, +// backgroundColor: Colors.transparent, +// isDismissable: true, +// child: SuccessDialog(widget.isFromDashboard), +// ); +// } +// +// +// //older code.... +// Future performNfcAttendance({double? lat = 0, double ?lng = 0}) async { +// DashBoardProvider dashBoardProvider = Provider.of(context,listen:false); +// if (Platform.isIOS) { +// Utils.readNFc(onRead: (String nfcId) async { +// Utils.showLoading(context); +// try { +// SwipeModel? swipeResponse = await dashBoardProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '', latitude: lat, longitude: lng)); +// if (swipeResponse.responseCode != 1) { +// Utils.hideLoading(context); +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: swipeResponse.message ?? "Unexpected error occurred", +// onTap: () { +// Navigator.pop(context); +// }, +// ), +// ); +// } else { +// bool status = swipeResponse.data; +// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); +// Utils.hideLoading(context); +// showMDialog( +// context, +// backgroundColor: Colors.transparent, +// isDismissable: true, +// child: SuccessDialog(widget.isFromDashboard), +// ); +// } +// } catch (ex) { +// Utils.hideLoading(context); +// // Utils.handleException(ex, context, null); +// } +// }); +// } else { +// showNfcReader(context, onNcfScan: (String? nfcId) async { +// Utils.showLoading(context); +// try { +// SwipeModel? swipeResponse = await dashBoardProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId??'', latitude: lat, longitude: lng)); +// log('api response i got is ${swipeResponse.toJson()}'); +// if (swipeResponse.responseCode != 1) { +// Utils.hideLoading(context); +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: swipeResponse.message ?? "Unexpected error occurred", +// onTap: () { +// Navigator.pop(context); +// }, +// ), +// ); +// } else { +// bool status = swipeResponse.data; //use this status to get transactions. +// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); +// Utils.hideLoading(context); +// showMDialog( +// context, +// backgroundColor: Colors.transparent, +// isDismissable: true, +// child: SuccessDialog(widget.isFromDashboard), +// ); +// } +// } catch (ex) { +// Utils.hideLoading(context); +// // Utils.handleException(ex, context, null); +// } +// // Utils.showLoading(context); +// // try { +// // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); +// // if (g?.messageStatus != 1) { +// // Utils.hideLoading(context); +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: g?.errorEndUserMessage ?? "Unexpected error occurred", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // ), +// // ); +// // } else { +// // bool status = await model.fetchAttendanceTracking(context); +// // Utils.hideLoading(context); +// // showMDialog( +// // context, +// // backgroundColor: Colors.transparent, +// // isDismissable: false, +// // child: SuccessDialog(widget.isFromDashboard), +// // ); +// // } +// // } catch (ex) { +// // log(ex); +// // Utils.hideLoading(context); +// // // Utils.handleException(ex, context, (String msg) { +// // // Utils.confirmDialog(context, msg); +// // // }); +// // } +// }); +// } +// } +// +// +// +// void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true, bool isBusniessCard = false}) async { +// return showDialog( +// context: context, +// barrierDismissible: isDismissable, +// builder: (context) { +// return Dialog( +// shape: isBusniessCard +// ? const RoundedRectangleBorder( +// borderRadius: BorderRadius.all( +// Radius.circular(15.0), +// ), +// ) +// : null, +// backgroundColor: backgroundColor, +// child: child, +// ); +// }, +// ); +// } +// // +// // Future checkSession() async { +// // try { +// // Utils.showLoading(context); +// // await DashboardApiClient().getOpenMissingSwipes(); +// // Utils.hideLoading(context); +// // return true; +// // } catch (ex) { +// // Utils.hideLoading(context); +// // Utils.handleException(ex, context, null); +// // return false; +// // } +// // } +// +// +// //TODO need to confirm .... +// // Future performWifiAttendance({double? latitude, double? lng}) async { +// // // if (Platform.isAndroid) { +// // // if (!(await checkSession())) { +// // // return; +// // // } +// // // } +// // Utils.showLoading(context); +// // bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "", +// // password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false); +// // +// // if (Platform.isIOS) { +// // if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) { +// // isConnected = true; +// // } else { +// // isConnected = false; +// // } +// // } +// // +// // if (isConnected && AppState().isAuthenticated) { +// // await WiFiForIoTPlugin.forceWifiUsage(true); +// // await Future.delayed(const Duration(seconds: 6)); +// // try { +// // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng); +// // bool status = await model.fetchAttendanceTracking(context); +// // Utils.hideLoading(context); +// // await closeWifiRequest(); +// // if (g?.messageStatus == 2) { +// // showDialog( +// // barrierDismissible: true, +// // context: context, +// // builder: (cxt) => ConfirmDialog( +// // message: g?.errorEndUserMessage ?? "", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // onCloseTap: () {}, +// // ), +// // ); +// // } else { +// // showMDialog( +// // context, +// // backgroundColor: Colors.transparent, +// // isDismissable: false, +// // child: SuccessDialog(widget.isFromDashboard), +// // ); +// // } +// // } catch (ex) { +// // await closeWifiRequest(); +// // Utils.hideLoading(context); +// // Utils.handleException(ex, context, null); +// // } +// // } else { +// // if (AppState().isAuthenticated) { +// // Utils.hideLoading(context); +// // Utils.confirmDialog(context, "LocaleKeys.comeNearHMGWifi.tr()"); +// // } else { +// // await closeWifiRequest(); +// // } +// // } +// // } +// +// Future closeWifiRequest() async { +// if (Platform.isAndroid) { +// await WiFiForIoTPlugin.forceWifiUsage(false); +// } +// return await WiFiForIoTPlugin.disconnect(); +// } +// +// Future performQrCodeAttendance( {double ? latitude , double ?longitude}) async { +// DashBoardProvider dashBoardProvider = Provider.of(context,listen: false); +// var qrCodeValue = await Navigator.of(context).push( +// MaterialPageRoute( +// builder: (BuildContext context) => QrScannerDialog(), +// ), +// ); +// if (qrCodeValue != null) { +// Utils.showLoading(context); +// try { +// final swipeModel = Swipe( +// swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(), +// value: qrCodeValue, +// latitude: latitude, +// longitude: longitude, +// ); +// log('model i got to scan qr is ${swipeModel.toJson()}'); +// final swipeResponse = await dashBoardProvider.makeSwipe(model: swipeModel); +// log('response of swipe is ${swipeResponse.toJson()}'); +// +// bool status = await swipeResponse.data; +// Utils.hideLoading(context); +// if (swipeResponse.responseCode == 2) { +// showDialog( +// barrierDismissible: true, +// context: context, +// builder: (cxt) => ConfirmDialog( +// message: swipeResponse.message ?? "", +// onTap: () { +// Navigator.pop(context); +// }, +// onCloseTap: () {}, +// ), +// ); +// } else { +// showMDialog( +// context, +// backgroundColor: Colors.transparent, +// isDismissable: true, +// child: SuccessDialog(widget.isFromDashboard), +// ); +// } +// } catch (ex) { +// log('$ex'); +// Utils.hideLoading(context); +// //this need to confirm where it comes.. +// // Utils.handleException(ex, context, null); +// } +// } +// } +// +// void markFakeAttendance(dynamic sourceName, String lat, String long) async { +// Utils.showLoading(context); +// try { +// // await DashboardApiClient().markFakeLocation(sourceName: sourceName, lat: lat, long: long); +// Utils.hideLoading(context); +// Utils.confirmDialog(context, "LocaleKeys.fakeLocation.tr()"); +// } catch (ex) { +// log('$ex'); +// Utils.hideLoading(context); +// //Utils.handleException(ex, context, null); +// } +// } +// +// Widget attendanceMethod(String title, IconData iconData, bool isEnabled, VoidCallback onPress) => Container( +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(15), +// color: isEnabled ? null : Colors.grey.withOpacity(.5), +// gradient: isEnabled +// ? const LinearGradient( +// transform: GradientRotation(.64), +// begin: Alignment.topRight, +// end: Alignment.bottomLeft, +// colors: [ +// //ToDo set Colors according to design provided by designer... +// Colors.blue, +// Colors.green, +// // AppColor.gradiantEndColor, +// // MyColors.gradiantStartColor, +// ], +// ) +// : null, +// ), +// clipBehavior: Clip.antiAlias, +// padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// // SvgPicture.asset(image, color: Colors.white, alignment: Alignment.topLeft).expanded, +// Icon(iconData, color: isEnabled ? AppColor.black35 : Colors.grey), +// title.heading6(context), +// // title.toText17(isBold: true, color: Colors.white), +// ], +// ), +// ).onPress( +// () { +// log('isEnabled is ${!isEnabled}'); +// if (!isEnabled) return; +// onPress(); +// }, +// ); +// } diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index 7b0de848..86cf1d63 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -149,7 +149,9 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/new_models/general_response_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/forget_password_module/forget_passwod_verify_otp.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; import '../../controllers/providers/api/user_provider.dart'; @@ -173,7 +175,8 @@ class _LoginPageState extends State { late UserProvider _userProvider; SettingProvider? _settingProvider; final GlobalKey _formKey = GlobalKey(); - + TextEditingController userNameController = TextEditingController(); + bool _passwordVisible = false; bool rememberMe = false; @override @@ -190,6 +193,7 @@ class _LoginPageState extends State { rememberMe = _settingProvider!.rememberMe; if (rememberMe) { _user.userName = _settingProvider!.username; + userNameController.text=_user.userName??''; _user.password = _settingProvider!.password; } } @@ -239,6 +243,7 @@ class _LoginPageState extends State { children: [ AppTextFormField( initialValue: _user.userName ?? "", + controller: userNameController, backgroundColor: AppColor.white20, validator: (value) => Validator.hasValue(value!) ? null : context.translation.requiredField, labelText: context.translation.username, @@ -260,7 +265,14 @@ class _LoginPageState extends State { style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: Color(0xff3B3D4A)), labelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 11, color: Color(0xff767676)), contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 12.toScreenHeight), - obscureText: true, + obscureText: !_passwordVisible, + suffixIcon: Icon( + // Based on passwordVisible state choose the icon + _passwordVisible ? Icons.visibility : Icons.visibility_off, + color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, + ).paddingOnly(end: 12).onPress(() { setState(() { + _passwordVisible = !_passwordVisible; + }); }), validator: (value) => Validator.isValidPassword(value!) ? null : value.isEmpty @@ -274,8 +286,18 @@ class _LoginPageState extends State { Align( alignment: AlignmentDirectional.centerEnd, child: InkWell( - onTap: () { - print('i am here...'); + onTap: () async { + if(userNameController.text.isNotEmpty){ + GeneralResponseModel response = await _userProvider.sendForgetPasswordOtp(context: context, employeeId: userNameController.text); + if( response.isSuccess==true){ + Navigator.push(context, MaterialPageRoute(builder: (context)=>ForgetPasswordVerifyOtpView(data: {'employeeId':userNameController.text,'phoneNumber':response.data},))); + // Navigator.push(context, ForgetPasswordVerifyOtpView.routeName); + }else{ + Fluttertoast.showToast(msg: response.message ?? context.translation.failedToCompleteRequest); + } + }else{ + Fluttertoast.showToast(msg: context.translation.employeeIdIsRequired); + } }, child: context.translation.forgotPassword.bodyText(context).custom(color: AppColor.primary10, fontWeight: FontWeight.w500), ), diff --git a/lib/new_views/swipe_module/circular_animated_widget.dart b/lib/new_views/swipe_module/circular_animated_widget.dart new file mode 100644 index 00000000..14ee20e1 --- /dev/null +++ b/lib/new_views/swipe_module/circular_animated_widget.dart @@ -0,0 +1,99 @@ +import 'package:flutter/animation.dart'; +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; + + +class CircularAnimatedContainer extends StatefulWidget { + Widget child; + + CircularAnimatedContainer({Key? key, required this.child}) : super(key: key); + @override + _CircularAnimatedContainerState createState() => _CircularAnimatedContainerState(); +} + +class _CircularAnimatedContainerState extends State + with SingleTickerProviderStateMixin { + AnimationController ?_controller; + Animation? _animation; + + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: const Duration(seconds: 2), + vsync: this, + )..repeat(); + + _animation = CurvedAnimation( + parent: _controller!, + curve: Curves.easeInOut, // Applies the ease-in-out effect + ); + // Repeats animation + } + + @override + void dispose() { + _controller!.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Center( + child: Stack( + alignment: Alignment.center, + children: [ + widget.child, + AnimatedBuilder( + animation: _animation!, + builder: (context, child) { + return CustomPaint( + painter: CircularProgressPainter( + progress: _animation!.value), + size: Size(100.toScreenHeight, 100.toScreenWidth), + ); + }, + ), + ], + ), + ); + } +} + +class CircularProgressPainter extends CustomPainter { + final double progress; + + CircularProgressPainter({ required this.progress}); + @override + void paint(Canvas canvas, Size size) { + + + final Paint paint = Paint() + ..color = AppColor.primary10 + ..style = PaintingStyle.stroke + ..strokeWidth = 3 + ..strokeCap = StrokeCap.round; + + final center = Offset(size.width / 2, size.height / 2); + final radius = size.width / 2.05; + final double startAngle = 2.5 * 3.141592653589793 * progress; + final double sweepAngle = 2 * 3.141592653589793 * progress; + // const double startAngle = -90 * (3.141592653589793 / 180); + // final double sweepAngle = 2.05 * 3.141592653589793 * progress; + + canvas.drawArc( + Rect.fromCircle(center: center, radius: radius), + startAngle, + sweepAngle, + false, + paint, + ); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return true; + } +} \ No newline at end of file diff --git a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart new file mode 100644 index 00000000..3e07310f --- /dev/null +++ b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; + +class ConfirmDialog extends StatelessWidget { + final String ?title; + final String ?message; + final String ?okTitle; + final VoidCallback ?onTap; + final VoidCallback ?onCloseTap; + + const ConfirmDialog({Key ?key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder(), + insetPadding: const EdgeInsets.only(left: 21, right: 21), + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + title ?? "Confirm", + style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black87, height: 35 / 24, letterSpacing: -0.96), + ).paddingOnly(top: 16), + ), + IconButton( + padding: EdgeInsets.zero, + icon: const Icon(Icons.close), + color: Colors.black87, + constraints: const BoxConstraints(), + onPressed: () => onCloseTap ?? Navigator.pop(context), + // onPressed: () => Navigator.pop(context), + ) + ], + ), + message!=null?message!.heading5(context).custom(color: AppColor.neutral70):const SizedBox(), + 28.height, + AppFilledButton( + label: okTitle ?? "OK", + onPressed: onTap ?? () => Navigator.pop(context), + textColor: Colors.white, + //color: Ap.green, + ), + ], + ), + ), + ); + } +} diff --git a/lib/new_views/swipe_module/dialoge/nfc_reader_sheet.dart b/lib/new_views/swipe_module/dialoge/nfc_reader_sheet.dart new file mode 100644 index 00000000..76e108a3 --- /dev/null +++ b/lib/new_views/swipe_module/dialoge/nfc_reader_sheet.dart @@ -0,0 +1,203 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:nfc_manager/nfc_manager.dart'; +import 'package:nfc_manager/platform_tags.dart'; + +void showNfcReader(BuildContext context, { Function(String nfcId) ?onNcfScan}) { + showModalBottomSheet( + context: context, + enableDrag: false, + isDismissible: false, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)), + ), + backgroundColor: Colors.white, + builder: (context) { + return NfcLayout( + onNcfScan: onNcfScan, + ); + }, + ); +} + +class NfcLayout extends StatefulWidget { + Function(String nfcId) ?onNcfScan; + + NfcLayout({this.onNcfScan}); + + @override + _NfcLayoutState createState() => _NfcLayoutState(); +} + +class _NfcLayoutState extends State { + bool _reading = false; + Widget? mainWidget; + String? nfcId; + + @override + void initState() { + super.initState(); + + NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async { + var f; + if (Platform.isAndroid) { + f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } else { + f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } + String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + nfcId = identifier; + + setState(() { + _reading = true; + mainWidget = doneNfc(); + }); + + Future.delayed(const Duration(seconds: 1), () { + NfcManager.instance.stopSession(); + Navigator.pop(context); + // if (Platform.isAndroid) { + // Navigator.pop(context); + // } else { + // Navigator.pop(context); + // Navigator.pop(context); + // } + widget.onNcfScan!(nfcId!); + }); + }).catchError((err) { + print(err); + }); + } + + @override + Widget build(BuildContext context) { + (mainWidget == null && !_reading) ? mainWidget = scanNfc() : mainWidget = doneNfc(); + return AnimatedSwitcher(duration: Duration(milliseconds: 500), child: mainWidget); + } + + Widget scanNfc() { + return Container( + key: ValueKey(1), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 30, + ), + const Text( + "Ready To Scan", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + ), + ), + SizedBox( + height: 30, + ), + + Image.asset( + "assets/images/ic_nfc.png", + height: MediaQuery.of(context).size.width / 3, + width: double.infinity, + ), + const SizedBox( + height: 30, + ), + const Text( + "Approach an NFC Tag", + style: TextStyle( + fontSize: 18, + ), + ), + const SizedBox( + height: 30, + ), + ButtonTheme( + minWidth: MediaQuery.of(context).size.width / 1.2, + height: 45.0, + buttonColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + child: TextButton( + onPressed: () { + NfcManager.instance.stopSession(); + Navigator.pop(context); + }, + // elevation: 0, + child: const Text("CANCEL"), + ), + ), + SizedBox( + height: 30, + ), + ], + ), + ); + } + + Widget doneNfc() { + return Container( + key: ValueKey(2), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 30, + ), + Text( + "Successfully Scanned", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + ), + ), + SizedBox( + height: 30, + ), + Image.asset( + // "assets/icons/nfc/ic_done.png", + "assets/images/ic_done.png", + height: MediaQuery.of(context).size.width / 3, + width: double.infinity, + ), + SizedBox( + height: 30, + ), + Text( + "Approach an NFC Tag", + style: TextStyle( + fontSize: 18, + ), + ), + SizedBox( + height: 30, + ), + ButtonTheme( + minWidth: MediaQuery.of(context).size.width / 1.2, + height: 45.0, + buttonColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + child: TextButton( + // onPressed: () { + // _stream?.cancel(); + // widget.onNcfScan(nfcId); + // Navigator.pop(context); + // }, + onPressed: null, + // elevation: 0, + child: Text("DONE"), + ), + ), + SizedBox( + height: 30, + ), + ], + ), + ); + } +} diff --git a/lib/new_views/swipe_module/dialoge/success_dialog.dart b/lib/new_views/swipe_module/dialoge/success_dialog.dart new file mode 100644 index 00000000..e03472c5 --- /dev/null +++ b/lib/new_views/swipe_module/dialoge/success_dialog.dart @@ -0,0 +1,76 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:just_audio/just_audio.dart'; +import 'package:lottie/lottie.dart'; + +class SuccessDialog extends StatefulWidget { + bool isFromDashboard; + + SuccessDialog(this.isFromDashboard); + + @override + State createState() => _SuccessDialogState(); +} + +class _SuccessDialogState extends State with TickerProviderStateMixin { + AnimationController? _controller; + + @override + void initState() { + _controller = AnimationController(vsync: this); + + super.initState(); + } + + Future playSuccessSound() async { + AudioPlayer player = AudioPlayer(); + String audioAsset = ""; + if (Platform.isAndroid) { + audioAsset = "assets/audio/success_tone_android.mp3"; + } else { + audioAsset = "assets/audio/success_tone_ios.caf"; + } + await player.setAsset(audioAsset); + await player.load(); + player.play(); + } + + @override + Widget build(BuildContext context) { + double size = MediaQuery.of(context).size.width / 1.8; + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: size, + height: size, + child: Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(25.0), + ), + child: Lottie.asset( + //TODO replace with original lottie file... + 'assets/lottie/done.json', + repeat: false, + reverse: false, + controller: _controller, + frameRate: FrameRate(60.0), + onLoaded: (LottieComposition v) async { + await playSuccessSound(); + _controller + !..duration = v.duration + ..forward().whenComplete(() async { + Navigator.pop(context); + if (widget.isFromDashboard) Navigator.pop(context); + }); + }, + ), + ), + ), + ], + ); + } +} diff --git a/lib/new_views/swipe_module/enums/swipe_type.dart b/lib/new_views/swipe_module/enums/swipe_type.dart new file mode 100644 index 00000000..8c4ff449 --- /dev/null +++ b/lib/new_views/swipe_module/enums/swipe_type.dart @@ -0,0 +1,18 @@ +enum SwipeTypeEnum { + NFC, // 1 + QR, // 2 + Wifi, // 3 +} + +extension EnumExtensionsSwipeType on SwipeTypeEnum { + int getIntFromSwipeTypeEnum() { + switch (this) { + case SwipeTypeEnum.NFC: + return 1; + case SwipeTypeEnum.QR: + return 2; + case SwipeTypeEnum.Wifi: + return 3; + } + } +} \ No newline at end of file diff --git a/lib/new_views/swipe_module/mark_attendance_widget.dart b/lib/new_views/swipe_module/mark_attendance_widget.dart new file mode 100644 index 00000000..6a6740e8 --- /dev/null +++ b/lib/new_views/swipe_module/mark_attendance_widget.dart @@ -0,0 +1,821 @@ +// import 'dart:async'; +// import 'dart:developer'; +// import 'dart:io'; +// +// import 'package:flutter/material.dart'; +// import 'package:geolocator/geolocator.dart'; +// import 'package:huawei_location/huawei_location.dart'; +// import 'package:nfc_manager/nfc_manager.dart'; +// import 'package:permission_handler/permission_handler.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/providers/api/user_provider.dart'; +// import 'package:test_sa/extensions/int_extensions.dart'; +// import 'package:test_sa/extensions/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/new_views/app_style/app_color.dart'; +// import 'package:test_sa/new_views/pages/land_page/nfc/nfc_reader_sheet.dart'; +// import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart'; +// import 'package:test_sa/new_views/swipe_module/dialoge/qr_scanner_dialog.dart'; +// import 'package:test_sa/new_views/swipe_module/dialoge/success_dialog.dart'; +// import 'package:test_sa/new_views/swipe_module/enums/swipe_type.dart'; +// import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart'; +// import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart'; +// import 'package:test_sa/new_views/swipe_module/utils/location_utils.dart'; +// import 'package:test_sa/new_views/swipe_module/utils/swipe_general_utils.dart'; +// import 'package:wifi_iot/wifi_iot.dart'; +// todo @sikander delete this file after compelte +// class MarkAttendanceWidget extends StatefulWidget { +// double topPadding; +// bool isFromDashboard; +// +// MarkAttendanceWidget({Key key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key); +// +// // todo MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key); +// +// @override +// _MarkAttendanceWidgetState createState() { +// return _MarkAttendanceWidgetState(); +// } +// } +// +// class _MarkAttendanceWidgetState extends State { +// bool isNfcEnabled = false, isQrEnabled = false, isWifiEnabled = false; +// UserProvider _userProvider; +// +// int _locationUpdateCbId = 0; +// +// @override +// void initState() { +// super.initState(); +// checkAttendanceAvailability(); +// } +// +// void checkAttendanceAvailability() async { +// _userProvider = Provider.of(context, listen: false); +// bool isAvailable = await NfcManager.instance.isAvailable(); +// log('backend enabled values are nfc ${_userProvider.user.enableNFC} qr ${_userProvider.user.enableQR} wifi ${_userProvider.user.enableWifi}'); +// setState(() { +// if (isAvailable && _userProvider.user.enableNFC) isNfcEnabled = true; +// if (_userProvider.user.enableQR) isQrEnabled = true; +// if (_userProvider.user.enableWifi) isWifiEnabled = true; +// }); +// } +// +// void checkHuaweiLocationPermission(SwipeTypeEnum attendanceType, BuildContext context) async { +// // Permission_Handler permissionHandler = PermissionHandler(); +// LocationUtilities.isEnabled((bool isEnabled) async { +// if (isEnabled) { +// LocationUtilities.havePermission((bool permission) async { +// if (permission) { +// getHuaweiCurrentLocation(attendanceType, context); +// } else { +// bool has = await requestPermissions(); +// if (has) { +// getHuaweiCurrentLocation(attendanceType, context); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to give location permission to mark attendance", +// onTap: () { +// Navigator.pop(context); +// }, +// ), +// ); +// } +// } +// }); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to enable location services to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openLocationSettings(); +// }, +// ), +// ); +// } +// }); +// +// // if (await permissionHandler.hasLocationPermission()) { +// // getHuaweiCurrentLocation(attendanceType); +// // } else { +// // bool has = await requestPermissions(); +// // if (has) { +// // getHuaweiCurrentLocation(attendanceType); +// // } else { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "You need to give location permission to mark attendance", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // ), +// // ); +// // } +// // } +// } +// +// Future requestPermissions() async { +// var result = await [ +// Permission.location, +// ].request(); +// return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted); +// } +// +// @override +// void dispose() { +// super.dispose(); +// // Stop Session +// NfcManager.instance.stopSession(); +// } +// +// @override +// Widget build(BuildContext context) { +// return Container( +// padding: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: widget.topPadding), +// decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white), +// width: double.infinity, +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisSize: MainAxisSize.min, +// children: [ +// 20.height, +// 'click me '.heading5(context), +// // LocaleKeys.markAttendance.tr().toSectionHeading(), +// // LocaleKeys.selectMethodOfAttendance.tr().toText11(color: const Color(0xff535353)), +// GridView( +// physics: const NeverScrollableScrollPhysics(), +// shrinkWrap: true, +// padding: const EdgeInsets.only(bottom: 0, top: 21), +// gridDelegate: +// SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8), +// children: availableAttendanceMethodList(context: context), +// ) +// ], +// ), +// ); +// } +// +// void handleSwipe({ +// SwipeTypeEnum swipeType, +// @required bool isEnable, +// @required BuildContext context, +// }) { +// // if (AppState().getIsHuawei) { +// if (false) { +// checkHuaweiLocationPermission(swipeType, context); +// } else { +// LocationUtilities.isEnabled((bool isEnabled) { +// if (isEnabled) { +// LocationUtilities.havePermission((bool permission) { +// if (permission) { +// SwipeGeneralUtils.showLoading(context); +// LocationUtilities.getCurrentLocation( +// (Position position, bool isMocked) { +// if (isMocked) { +// SwipeGeneralUtils.hideLoading(context); +// SwipeGeneralUtils.markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? "", context); +// } else { +// SwipeGeneralUtils.hideLoading(context); +// //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); +// handleSwipeOperation(swipeType: swipeType, lat: position.latitude, lang: position.longitude); +// } +// }, +// () { +// SwipeGeneralUtils.hideLoading(context); +// SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); +// }, +// context, +// ); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to give location permission to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openAppSettings(); +// }, +// ), +// ); +// } +// }); +// } else { +// showDialog( +// context: context, +// builder: (BuildContext cxt) => ConfirmDialog( +// message: "You need to enable location services to mark attendance", +// onTap: () async { +// Navigator.pop(context); +// await Geolocator.openLocationSettings(); +// }, +// ), +// ); +// } +// }); +// } +// } +// +// void handleSwipeOperation({@required SwipeTypeEnum swipeType, double lat, double lang, BuildContext context}) { +// switch (swipeType) { +// case SwipeTypeEnum.NFC: +// handleNfcAttendance(latitude: lat, longitude: lang, context: context); +// return; +// case SwipeTypeEnum.QR: +// performQrCodeAttendance(latitude: lat, longitude: lang, context: context); +// return; +// case SwipeTypeEnum.Wifi: +// //TODO need to implement. +// return; +// } +// } +// +// void getHuaweiCurrentLocation(SwipeTypeEnum attendanceType, BuildContext context) async { +// try { +// SwipeGeneralUtils.showLoading(context); +// FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService(); +// LocationRequest locationRequest = LocationRequest(); +// locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; +// locationRequest.interval = 500; +// List locationRequestList = [locationRequest]; +// LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList); +// +// StreamSubscription _streamSubscription; +// int requestCode = (await (locationService.requestLocationUpdates(locationRequest))); +// +// _streamSubscription = locationService.onLocationData.listen( +// (Location location) async { +// SwipeGeneralUtils.hideLoading(context); +// await locationService.removeLocationUpdates(requestCode); +// handleSwipeOperation(swipeType: attendanceType); +// requestCode = 0; +// }, +// ); +// +// // locationService.checkLocationSettings(locationSettingsRequest).then((settings) async { +// // await locationService.getLastLocation().then((value) { +// // if (value.latitude == null || value.longitude == null) { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "Unable to get your location, Please check your location settings & try again.", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // ), +// // ); +// // } else { +// // if (attendanceType == "QR") { +// // performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); +// // } +// // if (attendanceType == "WIFI") { +// // performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); +// // } +// // if (attendanceType == "NFC") { +// // performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? ""); +// // } +// // } +// // }).catchError((error) { +// // log("HUAWEI LOCATION getLastLocation ERROR!!!!!"); +// // log(error); +// // }); +// // }).catchError((error) { +// // log("HUAWEI LOCATION checkLocationSettings ERROR!!!!!"); +// // log(error); +// // if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") { +// // // Location service not enabled. +// // } +// // }); +// } catch (error) { +// log("HUAWEI LOCATION ERROR!!!!!"); +// log('$error'); +// SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.handleException(error, context, null); +// } +// } +// +// Future handleNfcAttendance({double latitude = 0, double longitude = 0, BuildContext context}) async { +// final userProvider = Provider.of(context, listen: false); +// +// if (Platform.isIOS) { +// SwipeGeneralUtils.readNFc(onRead: (String nfcId) async { +// await _processNfcAttendance(userProvider, nfcId, latitude, longitude, context); +// }); +// } else { +// showNfcReader(context, onNcfScan: (String nfcId) async { +// await _processNfcAttendance(userProvider, nfcId ?? '', latitude, longitude, context); +// }); +// } +// } +// +// Future _processNfcAttendance( +// UserProvider userProvider, +// String nfcId, +// double latitude, +// double longitude, +// BuildContext context, +// ) async { +// SwipeGeneralUtils.showLoading(context); +// try { +// // final swipeModel = Swipe( +// // swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), +// // value: nfcId, +// // latitude: latitude, +// // longitude: longitude, +// // ); +// //Test model... +// final swipeModel = Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '123', latitude: 24.70865415364271, longitude: 46.66600861881879); +// final swipeResponse = await userProvider.makeSwipe(model: swipeModel); +// if (swipeResponse.isSuccess) { +// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); +// SwipeGeneralUtils.hideLoading(context); +// Navigator.pushNamed(context, SwipeSuccessView.routeName); +// } else { +// SwipeGeneralUtils.hideLoading(context); +// SwipeGeneralUtils.showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context); +// } +// } catch (errSwipeGeneralUtilsor) { +// SwipeGeneralUtils.hideLoading(context); +// // Uncomment below line for error handling if needed +// // SwipeGeneralUtils.handleException(error, context, null); +// } +// } +// +// Future closeWifiRequest() async { +// if (Platform.isAndroid) { +// await WiFiForIoTPlugin.forceWifiUsage(false); +// } +// return await WiFiForIoTPlugin.disconnect(); +// } +// +// Future performQrCodeAttendance({double latitude, double longitude, BuildContext context}) async { +// UserProvider userProvider = Provider.of(context, listen: false); +// var qrCodeValue = await Navigator.of(context).push( +// MaterialPageRoute( +// builder: (BuildContext context) => QrScannerDialog(), +// ), +// ); +// if (qrCodeValue != null) { +// SwipeGeneralUtils.showLoading(context); +// try { +// //test model.. +// final swipeModel = Swipe( +// swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(), +// value: '2323', +// latitude: 24.70865415364271, +// longitude: 46.66600861881879, +// ); +// final swipeResponse = await userProvider.makeSwipe(model: swipeModel); +// if (swipeResponse.isSuccess) { +// SwipeGeneralUtils.hideLoading(context); +// SwipeGeneralUtils.showMDialog(context, backgroundColor: Colors.transparent, isDismissable: true, child: SuccessDialog(widget.isFromDashboard)); +// } else { +// SwipeGeneralUtils.hideLoading(context); +// showDialog( +// barrierDismissible: true, +// context: context, +// builder: (cxt) => ConfirmDialog( +// message: swipeResponse.message ?? "", +// onTap: () { +// Navigator.pop(context); +// }, +// onCloseTap: () {} +// ), +// ); +// } +// } catch (ex) { +// SwipeGeneralUtils.hideLoading(context); +// } +// } +// } +// +// List availableAttendanceMethodList({@required BuildContext context}) { +// List availableMethods = []; +// if (isNfcEnabled) { +// availableMethods.add(attendanceMethod(SwipeTypeEnum.NFC.name, 'nfc_icon', isNfcEnabled, () { +// handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: isNfcEnabled, context: context); +// })); +// } +// if (isQrEnabled) { +// availableMethods.add(attendanceMethod(SwipeTypeEnum.QR.name, 'wifi_icon', isQrEnabled, () { +// handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: isQrEnabled, context: context); +// })); +// } +// if (isWifiEnabled) { +// availableMethods.add(attendanceMethod(SwipeTypeEnum.Wifi.name, 'wifi_icon', isWifiEnabled, () { +// handleSwipe(swipeType: SwipeTypeEnum.Wifi, isEnable: isWifiEnabled, context: context); +// })); +// } +// return availableMethods; +// } +// +// Widget attendanceMethod(String title, String icon, bool isEnabled, VoidCallback onPress) { +// return Container( +// padding: EdgeInsets.all(12), +// decoration: BoxDecoration( +// color: Colors.white, +// borderRadius: BorderRadius.circular(18), +// border: Border.all(color: AppColor.white40, width: 2), +// ), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// icon.toSvgAsset(), +// title.heading5(context).custom(color: AppColor.neutral50), +// // Text( +// // title, +// // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500), +// // ), +// ], +// ), +// ).onPress( +// () { +// log('isEnabled is ${!isEnabled}'); +// if (!isEnabled) return; +// onPress(); +// }, +// ); +// // return Container( +// // decoration: BoxDecoration( +// // borderRadius: BorderRadius.circular(15), +// // color: isEnabled ? null : Colors.grey.withOpacity(.5), +// // gradient: isEnabled +// // ? const LinearGradient( +// // transform: GradientRotation(.64), +// // begin: Alignment.topRight, +// // end: Alignment.bottomLeft, +// // colors: [ +// // //ToDo set Colors according to design provided by designer... +// // Colors.blue, +// // Colors.green, +// // // AppColor.gradiantEndColor, +// // // MyColors.gradiantStartColor, +// // ], +// // ) +// // : null, +// // ), +// // clipBehavior: Clip.antiAlias, +// // padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14), +// // child: Column( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // children: [ +// // // SvgPicture.asset(image, color: Colors.white, alignment: Alignment.topLeft).expanded, +// // Icon(iconData, color: isEnabled ? AppColor.black35 : Colors.grey), +// // title.heading6(context), +// // // title.toText17(isBold: true, color: Colors.white), +// // ], +// // ), +// // ).onPress( +// // () { +// // log('isEnabled is ${!isEnabled}'); +// // if (!isEnabled) return; +// // onPress(); +// // }, +// // ); +// } +// } +// +// // Widget customListItem({required String icon, required String heading, required String subHeading, required VoidCallback onTap}) { +// // return GestureDetector( +// // onTap: onTap, // Handles the tap +// // child: Card( +// // shape: RoundedRectangleBorder( +// // borderRadius: BorderRadius.circular(14), // Circular border radius +// // ), +// // color: Colors.white, +// // child: Row( +// // crossAxisAlignment: CrossAxisAlignment.start, // Align items at the top +// // children: [ +// // // Icon Section +// // icon +// // .toSvgAsset( +// // width: 32, +// // color: AppColor.neutral120, +// // height: 29, +// // ) +// // .paddingOnly(top: 8), +// // 14.width, +// // Expanded( +// // child: Column( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // children: [ +// // Text( +// // heading, +// // style: AppTextStyles.heading6.copyWith(color: AppColor.neutral50), +// // ), +// // 7.height, +// // Text( +// // subHeading, +// // style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), +// // ), +// // ], +// // ).paddingOnly(end: 50), +// // ), +// // ], +// // ).paddingAll(12), +// // ), +// // ); +// // } +// +// //qr older code... +// +// //nfc older code widget +// +// // // if (AppState().getIsHuawei) { +// // if (false) { +// // checkHuaweiLocationPermission(SwipeTypeEnum.NFC); +// // } else { +// // LocationUtilities.isEnabled((bool isEnabled) { +// // if (isEnabled) { +// // LocationUtilities.havePermission((bool permission) { +// // if (permission) { +// // SwipeGeneralUtils.showLoading(context); +// // LocationUtilities.getCurrentLocation( +// // (Position position, bool isMocked) { +// // if (isMocked) { +// // SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? "",context); +// // } else { +// // SwipeGeneralUtils.hideLoading(context); +// // //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); +// // } +// // }, +// // () { +// // SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); +// // }, +// // context, +// // ); +// // } else { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "You need to give location permission to mark attendance", +// // onTap: () async { +// // Navigator.pop(context); +// // await Geolocator.openAppSettings(); +// // }, +// // ), +// // ); +// // } +// // }); +// // } else { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "You need to enable location services to mark attendance", +// // onTap: () async { +// // Navigator.pop(context); +// // await Geolocator.openLocationSettings(); +// // }, +// // ), +// // ); +// // } +// // }); +// // } +// +// //older code.... +// // Future performNfcAttendance({double lat = 0, double lng = 0}) async { +// // UserProvider userProvider = Provider.of(context,listen:false); +// // if (Platform.isIOS) { +// // SwipeGeneralUtils.readNFc(onRead: (String nfcId) async { +// // SwipeGeneralUtils.showLoading(context); +// // try { +// // SwipeModel swipeResponse = await userProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '', latitude: lat, longitude: lng)); +// // if (swipeResponse.responseCode != 1) { +// // SwipeGeneralUtils.hideLoading(context); +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: swipeResponse.message ?? "Unexpected error occurred", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // ), +// // ); +// // } else { +// // bool status = swipeResponse.data; +// // if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); +// // SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.showMDialog( +// // context, +// // backgroundColor: Colors.transparent, +// // isDismissable: true, +// // child: SuccessDialog(widget.isFromDashboard), +// // ); +// // } +// // } catch (ex) { +// // SwipeGeneralUtils.hideLoading(context); +// // // SwipeGeneralUtils.handleException(ex, context, null); +// // } +// // }); +// // } else { +// // showNfcReader(context, onNcfScan: (String nfcId) async { +// // SwipeGeneralUtils.showLoading(context); +// // try { +// // SwipeModel swipeResponse = await userProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId??'', latitude: lat, longitude: lng)); +// // log('api response i got is ${swipeResponse.toJson()}'); +// // if (swipeResponse.responseCode != 1) { +// // SwipeGeneralUtils.hideLoading(context); +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: swipeResponse.message ?? "Unexpected error occurred", +// // onTap: () { +// // Navigator.pop(context); +// // }, +// // ), +// // ); +// // } else { +// // bool status = swipeResponse.data; //use this status to get transactions. +// // if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3)); +// // SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.showMDialog( +// // context, +// // backgroundColor: Colors.transparent, +// // isDismissable: true, +// // child: SuccessDialog(widget.isFromDashboard), +// // ); +// // } +// // } catch (ex) { +// // SwipeGeneralUtils.hideLoading(context); +// // // SwipeGeneralUtils.handleException(ex, context, null); +// // } +// // // SwipeGeneralUtils.showLoading(context); +// // // try { +// // // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); +// // // if (g?.messageStatus != 1) { +// // // SwipeGeneralUtils.hideLoading(context); +// // // showDialog( +// // // context: context, +// // // builder: (BuildContext cxt) => ConfirmDialog( +// // // message: g?.errorEndUserMessage ?? "Unexpected error occurred", +// // // onTap: () { +// // // Navigator.pop(context); +// // // }, +// // // ), +// // // ); +// // // } else { +// // // bool status = await model.fetchAttendanceTracking(context); +// // // SwipeGeneralUtils.hideLoading(context); +// // // showMDialog( +// // // context, +// // // backgroundColor: Colors.transparent, +// // // isDismissable: false, +// // // child: SuccessDialog(widget.isFromDashboard), +// // // ); +// // // } +// // // } catch (ex) { +// // // log(ex); +// // // SwipeGeneralUtils.hideLoading(context); +// // // // SwipeGeneralUtils.handleException(ex, context, (String msg) { +// // // // SwipeGeneralUtils.confirmDialog(context, msg); +// // // // }); +// // // } +// // }); +// // } +// // } +// +// // +// // Future checkSession() async { +// // try { +// // SwipeGeneralUtils.showLoading(context); +// // await DashboardApiClient().getOpenMissingSwipes(); +// // SwipeGeneralUtils.hideLoading(context); +// // return true; +// // } catch (ex) { +// // SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.handleException(ex, context, null); +// // return false; +// // } +// // } +// +// //TODO need to confirm .... +// Future performWifiAttendance({double? latitude, double? lng}) async { +// // if (Platform.isAndroid) { +// // if (!(await checkSession())) { +// // return; +// // } +// // } +// SwipeGeneralUtils.showLoading(context); +// bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "", +// password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false); +// +// if (Platform.isIOS) { +// if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) { +// isConnected = true; +// } else { +// isConnected = false; +// } +// } +// +// if (isConnected && AppState().isAuthenticated) { +// await WiFiForIoTPlugin.forceWifiUsage(true); +// await Future.delayed(const Duration(seconds: 6)); +// try { +// GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng); +// bool status = await model.fetchAttendanceTracking(context); +// SwipeGeneralUtils.hideLoading(context); +// await closeWifiRequest(); +// if (g?.messageStatus == 2) { +// showDialog( +// barrierDismissible: true, +// context: context, +// builder: (cxt) => ConfirmDialog( +// message: g?.errorEndUserMessage ?? "", +// onTap: () { +// Navigator.pop(context); +// }, +// onCloseTap: () {}, +// ), +// ); +// } else { +// showMDialog( +// context, +// backgroundColor: Colors.transparent, +// isDismissable: false, +// child: SuccessDialog(widget.isFromDashboard), +// ); +// } +// } catch (ex) { +// await closeWifiRequest(); +// SwipeGeneralUtils.hideLoading(context); +// SwipeGeneralUtils.handleException(ex, context, null); +// } +// } else { +// if (AppState().isAuthenticated) { +// SwipeGeneralUtils.hideLoading(context); +// SwipeGeneralUtils.confirmDialog(context, "LocaleKeys.comeNearHMGWifi.tr()"); +// } else { +// await closeWifiRequest(); +// } +// } +// } +// +// // older grid widget.. +// // attendanceMethod(SwipeTypeEnum.NFC.name, Icons.nfc, isNfcEnabled, () { +// // handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: isNfcEnabled); +// // }), +// // attendanceMethod(SwipeTypeEnum.QR.name, Icons.qr_code_2, isQrEnabled, () async { +// // handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: true); +// // }), +// // //if (isWifiEnabled) //todo +// // attendanceMethod(SwipeTypeEnum.Wifi.name, Icons.wifi, isWifiEnabled, () { +// // // if (AppState().getIsHuawei) { +// // if (false) { +// // checkHuaweiLocationPermission(SwipeTypeEnum.Wifi); +// // } else { +// // LocationUtilities.isEnabled((bool isEnabled) { +// // if (isEnabled) { +// // LocationUtilities.havePermission((bool permission) { +// // if (permission) { +// // SwipeGeneralUtils.showLoading(context); +// // LocationUtilities.getCurrentLocation( +// // (Position position, bool isMocked) { +// // if (isMocked) { +// // SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? "", context); +// // } else { +// // SwipeGeneralUtils.hideLoading(context); +// // //todo performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); +// // } +// // }, +// // () { +// // SwipeGeneralUtils.hideLoading(context); +// // SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); +// // }, +// // context, +// // ); +// // } else { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "You need to give location permission to mark attendance", +// // onTap: () async { +// // Navigator.pop(context); +// // await Geolocator.openAppSettings(); +// // }, +// // ), +// // ); +// // } +// // }); +// // } else { +// // showDialog( +// // context: context, +// // builder: (BuildContext cxt) => ConfirmDialog( +// // message: "You need to enable location services to mark attendance", +// // onTap: () async { +// // Navigator.pop(context); +// // await Geolocator.openLocationSettings(); +// // }, +// // ), +// // ); +// // } +// // }); +// // } +// // }), diff --git a/lib/new_views/swipe_module/models/swipe_model.dart b/lib/new_views/swipe_module/models/swipe_model.dart new file mode 100644 index 00000000..7251a838 --- /dev/null +++ b/lib/new_views/swipe_module/models/swipe_model.dart @@ -0,0 +1,68 @@ + +import 'package:flutter/material.dart'; + +class SwipeModel { + final bool? data; + final String? message; + final String ?title; + final String ?innerMessage; + final int ?responseCode; + final bool ?isSuccess; + + SwipeModel({ + this.data, + this.message, + this.title, + this.innerMessage, + this.responseCode, + this.isSuccess, + }); + + factory SwipeModel.fromJson(Map json) { + return SwipeModel( + data: json['data'], + message: json['message'] , + title: json['title'] , + innerMessage: json['innerMessage'] , + responseCode: json['responseCode'], + isSuccess: json['isSuccess'] , + ); + } + + Map toJson() { + return { + 'data': data, + 'message': message, + 'title': title, + 'innerMessage': innerMessage, + 'responseCode': responseCode, + 'isSuccess': isSuccess, + }; + } + + +} + +class Swipe { + final int ?swipeTypeValue; + final String? value; + final double? latitude; + final double? longitude; + + Swipe({ + this.swipeTypeValue, + this.value, + this.latitude, + this.longitude, + }); + + Map toJson() { + return { + 'swipeTypeValue': swipeTypeValue, + 'value': value, + 'latitude': latitude, + 'longitude': longitude, + }; + } +} + diff --git a/lib/new_views/swipe_module/models/swipe_transaction_history.dart b/lib/new_views/swipe_module/models/swipe_transaction_history.dart new file mode 100644 index 00000000..7bb0137a --- /dev/null +++ b/lib/new_views/swipe_module/models/swipe_transaction_history.dart @@ -0,0 +1,47 @@ +class SwipeHistory { + final int ?id; + final String? swipeTypeName; + final String? userName; + final String ?siteName; + final String ?pointName; + final String ?swipeTime; + final bool ?isSuccess; + final String? errorMessage; + + SwipeHistory({ + this.id, + this.swipeTypeName, + this.userName, + this.siteName, + this.pointName, + this.swipeTime, + this.isSuccess, + this.errorMessage, + }); + + factory SwipeHistory.fromJson(Map json) { + return SwipeHistory( + id: json['id'], + swipeTypeName: json['swipeTypeName'], + userName: json['userName'], + siteName: json['siteName'], + pointName: json['pointName'], + swipeTime: json['swipeTime']!=null? DateTime.parse(json['swipeTime']).toIso8601String():'', + isSuccess: json['isSuccess'], + errorMessage: json['errorMessage'], + ); + } + + Map toJson() { + return { + 'id': id, + 'swipeTypeName': swipeTypeName, + 'userName': userName, + 'siteName': siteName, + 'pointName': pointName, + 'swipeTime': swipeTime, + 'isSuccess': isSuccess, + 'errorMessage': errorMessage, + }; + } +} diff --git a/lib/new_views/swipe_module/models/swipe_transaction_model.dart b/lib/new_views/swipe_module/models/swipe_transaction_model.dart new file mode 100644 index 00000000..ff1d82fd --- /dev/null +++ b/lib/new_views/swipe_module/models/swipe_transaction_model.dart @@ -0,0 +1,47 @@ +class SwipeTransaction { + final int ?id; + final String? swipeTypeName; + final String ?userName; + final String? siteName; + final String? pointName; + final DateTime? swipeTime; + final bool? isSuccess; + final String? errorMessage; + + SwipeTransaction({ + this.id, + this.swipeTypeName, + this.userName, + this.siteName, + this.pointName, + this.swipeTime, + this.isSuccess, + this.errorMessage, + }); + + factory SwipeTransaction.fromJson(Map json) { + return SwipeTransaction( + id: json['id'] as int, + swipeTypeName: json['swipeTypeName'] , + userName: json['userName'] , + siteName: json['siteName'] , + pointName: json['pointName'] , + swipeTime: DateTime.parse(json['swipeTime']), + isSuccess: json['isSuccess'] , + errorMessage: json['errorMessage'] , + ); + } + + // Map toJson() { + // return { + // 'id': id, + // 'swipeTypeName': swipeTypeName, + // 'userName': userName, + // 'siteName': siteName, + // 'pointName': pointName, + // 'swipeTime': swipeTime.toIso8601String(), + // 'isSuccess': isSuccess, + // 'errorMessage': errorMessage, + // }; + // } +} diff --git a/lib/new_views/swipe_module/non_hmg_employee_swipe_view.dart b/lib/new_views/swipe_module/non_hmg_employee_swipe_view.dart new file mode 100644 index 00000000..8f392199 --- /dev/null +++ b/lib/new_views/swipe_module/non_hmg_employee_swipe_view.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:nfc_manager/nfc_manager.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; + +class NonHmgEmployeeSwipeView extends StatefulWidget { + NonHmgEmployeeSwipeView({Key? key}) : super(key: key); + + @override + _NonHmgEmployeeSwipeViewState createState() { + return _NonHmgEmployeeSwipeViewState(); + } +} + +class _NonHmgEmployeeSwipeViewState extends State { + bool isNfcEnabled = false; + + @override + void initState() { + super.initState(); + checkForNfcAndLocationPermission(); + } + + void checkForNfcAndLocationPermission() async { + isNfcEnabled = await NfcManager.instance.isAvailable(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.only(top: 21), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(30), color: Colors.white, border: Border.all(color: AppColor.white936.withOpacity(.05), width: 1)), + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Mark Attendance", + style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + GridView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: const EdgeInsets.only(bottom: 0, top: 16), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 16, mainAxisSpacing: 16), + children: [ + gridItem("Nfc", Icons.nfc, isNfcEnabled).onPress(isNfcEnabled ? () {} : null), + gridItem("Qr Scan", Icons.qr_code, true).onPress(() {}), + ], + ) + ], + ), + ); + } + + Widget gridItem(String label, IconData iconData, bool enable) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(25), color: AppColor.white30, border: Border.all(color: AppColor.white936.withOpacity(.03), width: 1)), + alignment: Alignment.center, + child: Column( + //mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Icon(iconData, color: enable ? AppColor.black35 : Colors.grey), + Text( + label, + style: AppTextStyles.heading6.copyWith(color: enable ? AppColor.black35 : Colors.grey), + ), + ], + ), + ); + } +} diff --git a/lib/new_views/swipe_module/swipe_history_view.dart b/lib/new_views/swipe_module/swipe_history_view.dart new file mode 100644 index 00000000..84169833 --- /dev/null +++ b/lib/new_views/swipe_module/swipe_history_view.dart @@ -0,0 +1,189 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; +import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; + + +import 'models/swipe_transaction_history.dart'; + +class SwipeHistoryView extends StatefulWidget { + static const routeName = '/swipe_list_view'; + + const SwipeHistoryView({Key? key}) : super(key: key); + + @override + State createState() => _SwipeHistoryViewState(); +} + + +class _SwipeHistoryViewState extends State { + DateTime dateFrom = DateTime.now(); + DateTime dateTo = DateTime.now(); + UserProvider? _userProvider; + @override + void initState() { + getSwipeHistory(); + super.initState(); + } + + void getSwipeHistory () { + _userProvider = Provider.of(context,listen:false); + WidgetsBinding.instance.addPostFrameCallback((_) async { + await _userProvider!.getSwipeTransactionHistory(userId: _userProvider!.user!.userID!,dateFrom: dateFrom,dateTo: dateTo); + }); + } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const DefaultAppBar(title: 'Swipe History',), + body: Column( + crossAxisAlignment:CrossAxisAlignment.start, + children: [ + + 8.height, + Row( + children: [ + ADatePicker( + label: context.translation.from, + date: dateFrom, + from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + setState(() { + dateFrom = selectedDateTime; + }); + } + } + }); + } + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.to, + date: dateTo, + from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + setState(() { + dateTo = selectedDateTime; + + }); + + } + } + }); + } + }, + ).expanded, + ], + ), + 12.height, + + AppFilledButton(label: context.translation.search, maxWidth: false, onPressed: getSwipeHistory), + 8.height, + const Divider(thickness: 2,color:AppColor.white60 ,), + + Consumer( + builder: (context, snapshot,child) { + return SwipeHistoryList(snapshot.swipeHistory ?? [], snapshot.isLoading).expanded; + } + ), + + + ], + ).paddingAll(20), + ); + } +} + + + + +class SwipeHistoryList extends StatelessWidget { + List list; + bool isLoading; + + SwipeHistoryList(this.list, this.isLoading, {Key ?key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return (list.isEmpty && !isLoading) + ? NoDataFound(message: context.translation.noDataFound).center + : ListView.separated( + padding: EdgeInsets.only(top: 12.toScreenHeight), + itemBuilder: (cxt, index) { + if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading); + return SwipeHistoryCard(list[index]); + }, + separatorBuilder: (cxt, index) => 12.height, + itemCount: isLoading ? 6 : list.length); + } +} +class SwipeHistoryCard extends StatelessWidget { + final SwipeHistory swipeHistory; + final bool showShadow; + const SwipeHistoryCard(this.swipeHistory, {Key? key, this.showShadow = true}) : super(key: key); + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(swipeHistory.swipeTime!.toServiceRequestDetailsFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50)), + ], + ), + 8.height, + '${context.translation.swipeTypeName}: ${swipeHistory.swipeTypeName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + '${context.translation.userName}: ${swipeHistory.userName}'.bodyText(context), + '${context.translation.siteName}: ${swipeHistory.siteName}'.bodyText(context), + '${context.translation.pointName}: ${swipeHistory.pointName}'.bodyText(context), + 8.height, + ], + ).toShadowContainer(context, showShadow: showShadow); + } +} + diff --git a/lib/new_views/swipe_module/swipe_success_view.dart b/lib/new_views/swipe_module/swipe_success_view.dart new file mode 100644 index 00000000..8c55ebb3 --- /dev/null +++ b/lib/new_views/swipe_module/swipe_success_view.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; + +class SwipeSuccessView extends StatelessWidget { + static const routeName = '/swipe_success_view'; + const SwipeSuccessView({Key ?key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment:CrossAxisAlignment.center, + children: [ + 'swipe_success'.toSvgAsset(), + 17.height, + context.translation.successful.heading4(context).custom(color: AppColor.white936), + 8.height, + context.translation.youHaveSuccessfullyMarkedYourAttendance.bodyText2(context).custom(color: AppColor.neutral120), + ], + ).expanded, + AppFilledButton( + label: 'Close', + maxWidth: true, + onPressed:(){ + Navigator.pop(context); + }, + ), + ], + ).paddingOnly(start: 20, end: 20, bottom: 16), + ); + } +} + + +// ClipOval( +// child: Container( +// color: Colors.grey.withOpacity(0.2), +// padding: const EdgeInsets.all(10), +// child: ClipOval( +// child: Container( +// color: AppColor.white.withOpacity(0.2), +// padding: const EdgeInsets.all(10), +// child: ClipOval( +// child: Container( +// color: AppColor.white, +// child: 'success_swipe'.toSvgAsset().paddingAll(50), +// ), +// ).paddingAll(20), +// ), +// ), +// ), +// ) diff --git a/lib/new_views/swipe_module/utils/location_utils.dart b/lib/new_views/swipe_module/utils/location_utils.dart new file mode 100644 index 00000000..8e02e3da --- /dev/null +++ b/lib/new_views/swipe_module/utils/location_utils.dart @@ -0,0 +1,67 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class LocationUtilities { + static void havePermission(Function(bool) callback) { + Geolocator.checkPermission().then((value) async { + if (value == LocationPermission.denied || value == LocationPermission.deniedForever) { + value = await Geolocator.requestPermission(); + callback(![LocationPermission.denied, LocationPermission.deniedForever].contains(value)); + } else { + callback(true); + } + }); + } + + static void isEnabled(Function(bool) callback) { + Geolocator.isLocationServiceEnabled().then((value) => callback(value)); + } + + static bool _listeningSettingChange = true; + + static void listenGPS({bool change = true, Function(bool) ?onChange}) async { + _listeningSettingChange = change; + if (change == false) return; + + Future.doWhile(() async { + await Future.delayed(const Duration(milliseconds: 1000)); + var enable = await Geolocator.isLocationServiceEnabled(); + onChange!(enable); + return _listeningSettingChange; + }); + } + + static void locationFun(Function(bool) completion, BuildContext context) { + Permission.location.isGranted.then((isGranted) { + if (!isGranted) { + Permission.location.request().then((granted) { + completion(granted == PermissionStatus.granted); + }); + } + completion(isGranted); + }); + } + + static void getCurrentLocation(Function(Position position, bool isMocked) callback, Function errorCallBack, BuildContext context) { + void done(Position position) { + //AppStorage.sp.saveLocation(position); + bool isMocked = position.isMocked; + callback(position, isMocked); + } + + locationFun((granted) { + if (granted) { + Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: const Duration(seconds: 5)).then((value) { + done(value); + }).catchError((err) { + errorCallBack(); + }); + } else { + // AppPermissions + } + }, context); + } +} diff --git a/lib/new_views/swipe_module/utils/swipe_general_utils.dart b/lib/new_views/swipe_module/utils/swipe_general_utils.dart new file mode 100644 index 00000000..49964366 --- /dev/null +++ b/lib/new_views/swipe_module/utils/swipe_general_utils.dart @@ -0,0 +1,530 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:google_api_availability/google_api_availability.dart'; +import 'package:huawei_location/huawei_location.dart'; +import 'package:intl/intl.dart'; +import 'package:nfc_manager/nfc_manager.dart'; +import 'package:nfc_manager/platform_tags.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/main.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; +import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart'; +import 'package:test_sa/new_views/swipe_module/dialoge/nfc_reader_sheet.dart'; +import 'package:test_sa/new_views/swipe_module/enums/swipe_type.dart'; +import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart'; +import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart'; +import 'package:test_sa/new_views/swipe_module/utils/location_utils.dart'; +import 'package:test_sa/views/widgets/qr/scan_qr.dart'; +import 'package:wifi_iot/wifi_iot.dart'; + +class SwipeGeneralUtils { + SwipeGeneralUtils._(); + + static SwipeGeneralUtils instance = SwipeGeneralUtils._(); + static bool _isLoadingVisible = false; + + static bool get isLoading => _isLoadingVisible; + + void markFakeAttendance(dynamic sourceName, String lat, String long, @required BuildContext context) async { + showLoading(context); + try { + hideLoading(navigatorKey.currentState!.overlay!.context); + confirmDialog(navigatorKey.currentState!.overlay!.context, "Fake Location)"); + } catch (ex) { + log('$ex'); + hideLoading(context); + //handleException(ex, context, null); + } + } + + void showLoading(BuildContext context) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _isLoadingVisible = true; + showDialog( + context: context, + barrierColor: Colors.black.withOpacity(0.5), + useRootNavigator: false, + builder: (BuildContext context) => const AppLazyLoading(), + ).then((value) { + _isLoadingVisible = false; + }); + }); + } + + void hideLoading(BuildContext context) { + if (_isLoadingVisible) { + _isLoadingVisible = false; + Navigator.of(context).pop(); + } + _isLoadingVisible = false; + } + + static Future getStringFromPrefs(String key) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.getString(key) ?? ""; + } + + void confirmDialog(cxt, String message, {VoidCallback? onTap}) { + showDialog( + context: cxt, + builder: (BuildContext cxt) => ConfirmDialog(message: message, onTap: onTap), + ); + } + + void showErrorDialog({String ?message, required BuildContext context}) { + showDialog( + context: context, + builder: (context) => ConfirmDialog(message: message, title: 'Error', onTap: () => Navigator.pop(context)), + ); + } + + void showMDialog(context, {Widget ?child, Color? backgroundColor, bool isDismissable = true, bool isBusniessCard = false}) async { + return showDialog( + context: context, + barrierDismissible: isDismissable, + builder: (context) { + return Dialog( + shape: isBusniessCard + ? const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(15.0), + ), + ) + : null, + backgroundColor: backgroundColor, + child: child, + ); + }, + ); + } + + Widget attendanceTypeCard(String title, String icon, bool isEnabled, VoidCallback onPress, BuildContext context) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: isEnabled ? Colors.white : AppColor.white70, + borderRadius: BorderRadius.circular(18), + border: Border.all(color: AppColor.white70, width: 2), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + icon.toSvgAsset(color: isEnabled ? null : Colors.grey.withOpacity(0.5)), + title.heading5(context).custom(color: isEnabled ? AppColor.neutral50 : Colors.grey.withOpacity(0.5)), + ], + ), + ).onPress( + () { + if (!isEnabled) return; + onPress(); + }, + ); + } + + //huawei permission part.... + void getHuaweiCurrentLocation({SwipeTypeEnum ?attendanceType, required BuildContext context}) async { + try { + showLoading(context); + FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService(); + LocationRequest locationRequest = LocationRequest(); + locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; + locationRequest.interval = 500; + List locationRequestList = [locationRequest]; + LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList); + + StreamSubscription _streamSubscription; + int requestCode = (await (locationService.requestLocationUpdates(locationRequest)))!; + _streamSubscription = locationService.onLocationData!.listen( + (Location location) async { + hideLoading(context); + await locationService.removeLocationUpdates(requestCode); + handleSwipeOperation(swipeType: attendanceType!, context: context, lat: location.latitude??0, long: location.longitude??0); + requestCode = 0; + //TODO cancel this stream when listening done.. + // _streamSubscription.cancel(); + }, + ); + } catch (error) { + log("HUAWEI LOCATION ERROR!!!!!"); + log('$error'); + hideLoading(context); + // handleException(error, context, null); + } + } + + Future requestPermissions() async { + var result = await [ + Permission.location, + ].request(); + return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted); + } + + void checkHuaweiLocationPermission({required SwipeTypeEnum attendanceType,required BuildContext context}) async { + // Permission_Handler permissionHandler = PermissionHandler(); + LocationUtilities.isEnabled((bool isEnabled) async { + if (isEnabled) { + LocationUtilities.havePermission((bool permission) async { + if (permission) { + getHuaweiCurrentLocation(attendanceType: attendanceType, context: context); + } else { + bool has = await requestPermissions(); + if (has) { + getHuaweiCurrentLocation(attendanceType: attendanceType, context: context); + } else { + showDialog( + context: context, + builder: (BuildContext cxt) => ConfirmDialog( + message: "You need to give location permission to mark attendance", + onTap: () { + Navigator.pop(context); + }, + ), + ); + } + } + }); + } else { + showDialog( + context: context, + builder: (BuildContext cxt) => ConfirmDialog( + message: "You need to enable location services to mark attendance", + onTap: () async { + Navigator.pop(context); + await Geolocator.openLocationSettings(); + }, + ), + ); + } + }); + + // if (await permissionHandler.hasLocationPermission()) { + // getHuaweiCurrentLocation(attendanceType); + // } else { + // bool has = await requestPermissions(); + // if (has) { + // getHuaweiCurrentLocation(attendanceType); + // } else { + // showDialog( + // context: context, + // builder: (BuildContext cxt) => ConfirmDialog( + // message: "You need to give location permission to mark attendance", + // onTap: () { + // Navigator.pop(context); + // }, + // ), + // ); + // } + // } + } + + void handleSwipeOperation({required SwipeTypeEnum swipeType,required double lat,required double long,required BuildContext context}) { + switch (swipeType) { + case SwipeTypeEnum.NFC: + handleNfcAttendance(latitude: lat, longitude: long, context: context); + return; + case SwipeTypeEnum.QR: + performQrCodeAttendance(latitude: lat, longitude: long, context: context); + return; + case SwipeTypeEnum.Wifi: + performWifiAttendance(latitude: lat, long: long, context: context); + return; + } + } + + String formatTimeOnly(DateTime dateTime) { + return DateFormat.Hms().format(dateTime); + } + + Future performQrCodeAttendance({double ?latitude, double? longitude,required BuildContext context}) async { + UserProvider userProvider = Provider.of(context, listen: false); + + String qrCodeValue = await Navigator.of(context).push( + MaterialPageRoute(builder: (_) => ScanQr()), + ) as String; + + if (qrCodeValue != null) { + showLoading(context); + try { + final swipeModel = Swipe( + swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(), + value: qrCodeValue, + latitude: latitude, + longitude: longitude, + ); + + await userProvider.makeSwipe(model: swipeModel).then((swipeResponse) { + if (swipeResponse.isSuccess==true) { + hideLoading(context); + Navigator.pushNamed(context, SwipeSuccessView.routeName); + } else { + hideLoading(context); + showDialog( + barrierDismissible: true, + context: context, + builder: (cxt) => ConfirmDialog( + message: swipeResponse.message ?? "", + onTap: () { + Navigator.pop(context); + }, + onCloseTap: () {}, + ), + ); + } + }); + } catch (ex) { + log('$ex'); + hideLoading(context); + //this need to confirm where it comes.. + // handleException(ex, context, null); + } + } + } + + Future handleNfcAttendance({double ?latitude = 0, double? longitude = 0,required BuildContext context}) async { + // UserProvider _userProvider = Provider.of(context,listen:false); + + if (Platform.isIOS) { + readNFc(onRead: (String nfcId) async { + await _processNfcAttendance(nfcId, latitude, longitude, context); + }); + } else { + showNfcReader(context, onNcfScan: (String nfcId) async { + await _processNfcAttendance(nfcId ?? '', latitude, longitude, context); + }); + } + } + + Future _processNfcAttendance( + String nfcId, + double ?latitude, + double ?longitude, + BuildContext context, + ) async { + showLoading(context); + try { + final swipeModel = Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId, latitude: latitude, longitude: longitude); + UserProvider userProvider = Provider.of(context, listen: false); + + final swipeResponse = await userProvider.makeSwipe(model: swipeModel); + + if (swipeResponse.isSuccess==true) { + hideLoading(context); + Navigator.pushNamed(context, SwipeSuccessView.routeName); + } else { + hideLoading(context); + showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context); + } + } catch (errSwipeGeneralUtilsor) { + hideLoading(context); + } + } + + void handleSwipe({required SwipeTypeEnum swipeType, required bool isEnable, required BuildContext context}) async { + if (Platform.isAndroid && !(await isGoogleServicesAvailable())) { + checkHuaweiLocationPermission(attendanceType: swipeType, context: context); + } else { + LocationUtilities.isEnabled((bool isEnabled) { + if (isEnabled) { + LocationUtilities.havePermission((bool permission) { + if (permission) { + showLoading(context); + LocationUtilities.getCurrentLocation( + (Position position, bool isMocked) { + if (isMocked) { + hideLoading(context); + markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? "", context); + } else { + hideLoading(context); + handleSwipeOperation(swipeType: swipeType, lat: position.latitude, long: position.longitude, context: context); + } + }, + () { + hideLoading(context); + confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); + }, + context, + ); + } else { + showInfoDialog( + message: "You need to give location permission to mark attendance", + onTap: () async { + await Geolocator.openAppSettings(); + }); + } + }); + } else { + showInfoDialog( + message: "You need to enable location services to mark attendance", + onTap: () async { + await Geolocator.openLocationSettings(); + }); + } + }); + } + } + + void showInfoDialog({required String message, VoidCallback? onTap}) { + showDialog( + context: navigatorKey.currentState!.overlay!.context, + builder: (BuildContext cxt) => ConfirmDialog( + message: message, + onTap: () async { + Navigator.pop(navigatorKey.currentState!.overlay!.context); + onTap!(); + }, + ), + ); + } + + List availableAttendanceMethodList({required BuildContext context, required UserProvider userProvider, required bool isNfcSupported}) { + List availableMethods = []; + if (userProvider.user!.enableNFC!) { + availableMethods.add(attendanceTypeCard(SwipeTypeEnum.NFC.name, 'nfc_icon', isNfcSupported, () { + Navigator.pop(context); + handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: userProvider.user!.enableNFC!, context: navigatorKey.currentState!.overlay!.context); + }, context)); + } + if (userProvider.user!.enableQR!) { + availableMethods.add(attendanceTypeCard(SwipeTypeEnum.QR.name, 'qr', userProvider.user!.enableQR!, () { + Navigator.pop(context); + handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: userProvider.user!.enableQR!, context: navigatorKey.currentState!.overlay!.context); + }, context)); + } + if (kDebugMode) { + userProvider.user!.enableWifi!= true; + } + + if (userProvider.user!.enableWifi!) { + availableMethods.add(attendanceTypeCard(SwipeTypeEnum.Wifi.name, 'wifi_icon', userProvider.user!.enableWifi!, () { + Navigator.pop(context); + handleSwipe(swipeType: SwipeTypeEnum.Wifi, isEnable: userProvider.user!.enableWifi!, context: navigatorKey.currentState!.overlay!.context); + }, context)); + } + return availableMethods; + } + + void showSwipeTypeBottomSheetSheet({required bool isNfcSupported}) { + BuildContext context = navigatorKey.currentState!.overlay!.context; + UserProvider _userProvider = Provider.of(context, listen: false); + + 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: [ + context.translation.markAttendance.heading4(context).custom(color: AppColor.white936), + 8.height, + context.translation.selectMethodToMarkAttendance.bodyText2(context).custom(color: AppColor.neutral120), + 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: availableAttendanceMethodList(context: context, userProvider: _userProvider, isNfcSupported: isNfcSupported)), + ], + ).paddingAll(16), + ); + } + + void readNFc({Function(String) ?onRead}) { + NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async { + MifareUltralight f; + if (Platform.isAndroid) { + f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } else { + f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } + String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + NfcManager.instance.stopSession(); + onRead!(identifier); + }).catchError((err) { + print(err); + }); + } + + //HUAWEI DECISION MAKING + Future isGoogleServicesAvailable() async { + GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability(); + String status = availability.toString().split('.').last; + if (status == "success") { + return true; + } + return false; + } + + Future performWifiAttendance({required double latitude, required double long, required BuildContext context}) async { + String ssId = String.fromCharCodes(base64Decode("SE1HLU1PSEVNTQ==")); + String password = String.fromCharCodes(base64Decode("TTBoZW1tQDEyMTI=")); + showLoading(context); + bool isConnected = await WiFiForIoTPlugin.connect(ssId, password: password, joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false); + + if (Platform.isIOS) { + if (await WiFiForIoTPlugin.getSSID() == ssId) { + isConnected = true; + } else { + isConnected = false; + } + } + UserProvider userProvider = Provider.of(context, listen: false); + + if (isConnected) { + await WiFiForIoTPlugin.forceWifiUsage(true); + await Future.delayed(const Duration(seconds: 6)); + try { + final swipeModel = Swipe(swipeTypeValue: SwipeTypeEnum.Wifi.getIntFromSwipeTypeEnum(), value: '', latitude: latitude, longitude: long); + + final swipeResponse = await userProvider.makeSwipe(model: swipeModel); + await closeWifiRequest(); + if (swipeResponse.isSuccess==true) { + hideLoading(context); + Navigator.pushNamed(context, SwipeSuccessView.routeName); + } else { + hideLoading(context); + await Future.delayed(const Duration(milliseconds: 250)); + showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context); + } + } catch (errSwipeGeneralUtilsor) { + hideLoading(context); + await closeWifiRequest(); + } + } else { + // if (userProvider.) { + hideLoading(context); + confirmDialog(context, "Come Near HMG Wifi"); + // } else { + // await closeWifiRequest(); + // } + await closeWifiRequest(); + } + } + + Future closeWifiRequest() async { + if (Platform.isAndroid) { + await WiFiForIoTPlugin.forceWifiUsage(false); + } + return await WiFiForIoTPlugin.disconnect(); + } +} diff --git a/localization_error.txt b/localization_error.txt index b7a7b76f..44f680c9 100644 --- a/localization_error.txt +++ b/localization_error.txt @@ -4,6 +4,7 @@ "signInToYour", "overdue", "newR", - "noDataFound" + "noDataFound", + "successful" ] }