From 9030b9bc817aa5f9ec74b6c3b0206208485848b3 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 29 May 2023 12:30:26 +0300 Subject: [PATCH] Notification details implemented --- lib/api/my_requests_api_client.dart | 4 +- lib/classes/notifications.dart | 45 +++++- .../get_notifications_response_model.dart | 96 +++++++++++++ lib/ui/login/login_screen.dart | 5 +- .../notification_details_page.dart | 74 ++++++++++ lib/ui/screens/my_requests/my_requests.dart | 132 +++++++++--------- lib/ui/screens/my_requests/new_request.dart | 22 +-- 7 files changed, 299 insertions(+), 79 deletions(-) create mode 100644 lib/models/get_notifications_response_model.dart create mode 100644 lib/ui/notifications/notification_details_page.dart diff --git a/lib/api/my_requests_api_client.dart b/lib/api/my_requests_api_client.dart index c9507b9..96eafa5 100644 --- a/lib/api/my_requests_api_client.dart +++ b/lib/api/my_requests_api_client.dart @@ -60,7 +60,7 @@ class MyRequestsApiClient { }, url, postParams); } - Future getSubmitNewRequest(List> list) async + Future getSubmitNewRequest(List> list) async { String url = "${ApiConsts.erpRest}SUBMIT_CCP_TRANSACTION"; Map postParams = { @@ -73,7 +73,7 @@ class MyRequestsApiClient { postParams["EITTransactionTBL"] = list; return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); - return responseData.submitCcpTransactionList; + return responseData; }, url, postParams); } diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 9528616..e29b29c 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -3,12 +3,16 @@ import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; // import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; import 'package:huawei_push/huawei_push.dart' as huawei_push; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/models/get_notifications_response_model.dart'; +import 'package:mohem_flutter_app/ui/notifications/notification_details_page.dart'; import 'package:permission_handler/permission_handler.dart'; final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); @@ -24,6 +28,8 @@ class AppNotifications { String _huaweiToken = ''; + late BuildContext context; + Future requestPermissions() async { if (Platform.isIOS) { await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); @@ -40,11 +46,13 @@ class AppNotifications { } } - void init(String? firebaseToken) async { + void init(String? firebaseToken, BuildContext context) async { // if (Platform.isAndroid) { // hmsApiAvailability = HmsApiAvailability(); // } + this.context = context; + await requestPermissions(); AppState().setDeviceToken = firebaseToken; await Permission.notification.isDenied.then((bool value) { @@ -113,12 +121,47 @@ class AppNotifications { void _handleMessage(RemoteMessage message) { Utils.saveStringFromPrefs("isAppOpendByChat", "false"); + GetNotificationsResponseModel notification = GetNotificationsResponseModel(); + + notification.createdOn = DateUtil.getMonthDayYearDateFormatted(DateTime.now()); + notification.messageTypeData = message.data['picture']; + notification.message = message.data['message']; + notification.notificationType = message.data["NotificationType"].toString(); + if (message.data["NotificationType"] == "2") { + notification.videoURL = message.data["VideoUrl"]; + } + + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => NotificationsDetailsPage( + notification: notification, + ), + ), + ); } void _handleOpenApp(RemoteMessage message) { if (message.data.isNotEmpty && message.data["type"] == 'chat') { Utils.saveStringFromPrefs("isAppOpendByChat", "true"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); + } else { + GetNotificationsResponseModel notification = GetNotificationsResponseModel(); + + notification.createdOn = DateUtil.getMonthDayYearDateFormatted(DateTime.now()); + notification.messageTypeData = message.data['picture']; + notification.message = message.data['message']; + notification.notificationType = message.data["NotificationType"].toString(); + if (message.data["NotificationType"] == "2") { + notification.videoURL = message.data["VideoUrl"]; + } + + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => NotificationsDetailsPage( + notification: notification, + ), + ), + ); } } } diff --git a/lib/models/get_notifications_response_model.dart b/lib/models/get_notifications_response_model.dart new file mode 100644 index 0000000..adf08ee --- /dev/null +++ b/lib/models/get_notifications_response_model.dart @@ -0,0 +1,96 @@ +class GetNotificationsResponseModel { + int? id; + int? recordId; + int? patientID; + bool? projectOutSA; + String? deviceType; + String? deviceToken; + String? message; + String? messageType; + String? messageTypeData; + dynamic videoURL; + bool? isQueue; + String? isQueueOn; + String? createdOn; + String? createdBy; + String? notificationType; + bool? isSent; + String? isSentOn; + bool? isRead; + String? isReadOn; + int? channelID; + int? projectID; + + GetNotificationsResponseModel( + {this.id, + this.recordId, + this.patientID, + this.projectOutSA, + this.deviceType, + this.deviceToken, + this.message, + this.messageType, + this.messageTypeData, + this.videoURL, + this.isQueue, + this.isQueueOn, + this.createdOn, + this.createdBy, + this.notificationType, + this.isSent, + this.isSentOn, + this.isRead, + this.isReadOn, + this.channelID, + this.projectID}); + + GetNotificationsResponseModel.fromJson(Map json) { + id = json['Id']; + recordId = json['RecordId']; + patientID = json['PatientID']; + projectOutSA = json['ProjectOutSA']; + deviceType = json['DeviceType']; + deviceToken = json['DeviceToken']; + message = json['Message']; + messageType = json['MessageType']; + messageTypeData = json['MessageTypeData']; + videoURL = json['VideoURL']; + isQueue = json['IsQueue']; + isQueueOn = json['IsQueueOn']; + createdOn = json['CreatedOn']; + createdBy = json['CreatedBy']; + notificationType = json['NotificationType']; + isSent = json['IsSent']; + isSentOn = json['IsSentOn']; + isRead = json['IsRead']; + isReadOn = json['IsReadOn']; + channelID = json['ChannelID']; + projectID = json['ProjectID']; + } + + Map toJson() { + Map data = new Map(); + data['Id'] = this.id; + data['RecordId'] = this.recordId; + data['PatientID'] = this.patientID; + data['ProjectOutSA'] = this.projectOutSA; + data['DeviceType'] = this.deviceType; + data['DeviceToken'] = this.deviceToken; + data['Message'] = this.message; + data['MessageType'] = this.messageType; + data['MessageTypeData'] = this.messageTypeData; + data['VideoURL'] = this.videoURL; + data['IsQueue'] = this.isQueue; + data['IsQueueOn'] = this.isQueueOn; + data['CreatedOn'] = this.createdOn; + data['CreatedBy'] = this.createdBy; + data['NotificationType'] = this.notificationType; + data['IsSent'] = this.isSent; + data['IsSentOn'] = this.isSentOn; + data['IsRead'] = this.isRead; + data['IsReadOn'] = this.isReadOn; + data['ChannelID'] = this.channelID; + data['ProjectID'] = this.projectID; + return data; + } +} diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 0eb7f4f..3293e43 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -110,7 +110,8 @@ class _LoginScreenState extends State { await Firebase.initializeApp(); _firebaseMessaging = FirebaseMessaging.instance; firebaseToken = await _firebaseMessaging.getToken(); - AppNotifications().init(firebaseToken); + print(firebaseToken); + AppNotifications().init(firebaseToken, context); checkLoginInfo(); await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); } @@ -123,7 +124,7 @@ class _LoginScreenState extends State { String? firebaseAPNSToken = await _firebaseMessaging.getAPNSToken(); print("Firebase Token: $firebaseToken"); print("Firebase APNS Token: $firebaseAPNSToken"); - AppNotifications().init(firebaseToken); + AppNotifications().init(firebaseToken, context); checkLoginInfo(); await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); } diff --git a/lib/ui/notifications/notification_details_page.dart b/lib/ui/notifications/notification_details_page.dart new file mode 100644 index 0000000..67573dc --- /dev/null +++ b/lib/ui/notifications/notification_details_page.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:lottie/lottie.dart'; +import 'package:mohem_flutter_app/models/get_notifications_response_model.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; + +class NotificationsDetailsPage extends StatefulWidget { + final GetNotificationsResponseModel notification; + + NotificationsDetailsPage({required this.notification}); + + @override + State createState() => _NotificationsDetailsPageState(); +} + +class _NotificationsDetailsPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget( + context, + title: "Notification Details", + ), + body: ListView( + physics: BouncingScrollPhysics(), + padding: EdgeInsets.all(21), + children: [ + Text( + widget.notification.createdOn!, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Color(0xff2E303A), + letterSpacing: -0.64, + ), + ), + if (widget.notification.messageTypeData != null) + if (widget.notification.messageTypeData!.isNotEmpty && widget.notification.notificationType != "2") + Padding( + padding: const EdgeInsets.only(top: 18), + child: Image.network(widget.notification.messageTypeData!, loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) { + if (loadingProgress == null) return child; + return Center( + child: SizedBox( + width: 40.0, + height: 40.0, + child: showLoadingAnimation(), + ), + ); + }, fit: BoxFit.fill), + ), + SizedBox(height: 18), + Text( + widget.notification.message!.trim(), + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xff575757), + letterSpacing: -0.48, + ), + ), + ], + ), + ); + } + + Widget showLoadingAnimation() { + return Lottie.asset( + 'assets/lottie/loading.json', + repeat: true, + reverse: false, + ); + } +} diff --git a/lib/ui/screens/my_requests/my_requests.dart b/lib/ui/screens/my_requests/my_requests.dart index dd6147f..4d16219 100644 --- a/lib/ui/screens/my_requests/my_requests.dart +++ b/lib/ui/screens/my_requests/my_requests.dart @@ -76,70 +76,72 @@ class _MyRequestsState extends State { }), ), 12.height, - getCCPTransactionsList.isNotEmpty ? Expanded( - child: ListView.separated( - physics: const BouncingScrollPhysics(), - shrinkWrap: true, - itemBuilder: (BuildContext context, int index) { - return Container( - width: double.infinity, - padding: const EdgeInsets.only(left: 12, right: 12, top: 10, bottom: 12), - margin: const EdgeInsets.only(left: 12, right: 12, top: 10, bottom: 0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ("Request ID: " + getCCPTransactionsList[index].rEQUESTID.toString()).toText12(color: MyColors.grey57Color), - DateUtil.formatDateToDate(DateUtil.convertStringToDate(getCCPTransactionsList[index].rEQUESTDATE!), false).toText12(color: MyColors.grey70Color), - ], - ), - Container( - padding: const EdgeInsets.only(top: 10.0), - child: ("Phase: " + getCCPTransactionsList[index].cCPPHASE!).toText12(color: MyColors.grey57Color, isBold: true), - ), - Container( - padding: const EdgeInsets.only(top: 10.0), - child: "Program Name: ".toText12(color: MyColors.grey57Color, isBold: true), - ), - getCCPTransactionsList[index].cONCURRENTPROGRAMNAME!.toText12(color: MyColors.gradiantEndColor), - Container( - padding: const EdgeInsets.only(top: 10.0), - child: InkWell( - onTap: () { - getCCPOutput(getCCPTransactionsList[index].rEQUESTID.toString()); - }, - child: Row( - children: [ - "Output: ".toText12(color: MyColors.grey57Color), - 8.width, - "Open PDF".toText12(color: MyColors.grey57Color), - 6.width, - const Icon(Icons.launch, size: 16.0), - ], - ), + getCCPTransactionsList.isNotEmpty + ? Expanded( + child: ListView.separated( + physics: const BouncingScrollPhysics(), + shrinkWrap: true, + itemBuilder: (BuildContext context, int index) { + return Container( + width: double.infinity, + padding: const EdgeInsets.only(left: 12, right: 12, top: 10, bottom: 12), + margin: const EdgeInsets.only(left: 12, right: 12, top: 10, bottom: 0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: const Color(0xff000000).withOpacity(.05), + blurRadius: 26, + offset: const Offset(0, -3), + ), + ], ), - ), - ], - ), - ); - }, - separatorBuilder: (BuildContext context, int index) => 12.height, - itemCount: getCCPTransactionsList.length), - ) : Container(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ("Request ID: " + getCCPTransactionsList[index].rEQUESTID.toString()).toText12(color: MyColors.grey57Color), + DateUtil.formatDateToDate(DateUtil.convertStringToDate(getCCPTransactionsList[index].rEQUESTDATE!), false).toText12(color: MyColors.grey70Color), + ], + ), + Container( + padding: const EdgeInsets.only(top: 10.0), + child: ("Phase: " + getCCPTransactionsList[index].cCPPHASE!).toText12(color: MyColors.grey57Color, isBold: true), + ), + Container( + padding: const EdgeInsets.only(top: 10.0), + child: "Program Name: ".toText12(color: MyColors.grey57Color, isBold: true), + ), + getCCPTransactionsList[index].cONCURRENTPROGRAMNAME!.toText12(color: MyColors.gradiantEndColor), + Container( + padding: const EdgeInsets.only(top: 10.0), + child: InkWell( + onTap: () { + getCCPOutput(getCCPTransactionsList[index].rEQUESTID.toString()); + }, + child: Row( + children: [ + "Output: ".toText12(color: MyColors.grey57Color), + 8.width, + "Open PDF".toText12(color: MyColors.grey57Color), + 6.width, + const Icon(Icons.launch, size: 16.0), + ], + ), + ), + ), + ], + ), + ); + }, + separatorBuilder: (BuildContext context, int index) => 12.height, + itemCount: getCCPTransactionsList.length), + ) + : Container(), ], ).expanded, 1.divider, @@ -153,7 +155,9 @@ class _MyRequestsState extends State { void openNewRequest() async { await Navigator.pushNamed(context, AppRoutes.newRequest).then((value) { - // getOpenTickets(); + if (value != null && value == "refresh") { + getCCPTransactions(selectedConcurrentProgramList?.cONCURRENTPROGRAMNAME); + } }); } diff --git a/lib/ui/screens/my_requests/new_request.dart b/lib/ui/screens/my_requests/new_request.dart index 670b18d..04d7cb4 100644 --- a/lib/ui/screens/my_requests/new_request.dart +++ b/lib/ui/screens/my_requests/new_request.dart @@ -5,12 +5,12 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/my_requests_api_client.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/dyanmic_forms/validate_eit_transaction_model.dart'; +import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/get_eit_dff_structure_list_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_transactions_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_transations_list_model.dart'; @@ -118,14 +118,14 @@ class _NewRequestState extends State { return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: vatcherVal.toString()).toJson(); }).toList(); Utils.showLoading(context); - submitCcpTransactionList = await MyRequestsApiClient().getSubmitNewRequest(values); - getCCPTransactionsList = await MyRequestsApiClient().getCcpTransactions(values); + GenericResponseModel responseModel = await MyRequestsApiClient().getSubmitNewRequest(values); Utils.hideLoading(context); - Navigator.pushNamed( - context, - AppRoutes.myRequests, - ); - setState(() {}); + + if (responseModel.messageStatus == 1) { + Navigator.pop(context, "refresh"); + } else { + Utils.showToast(responseModel.errorEndUserMessage ?? ""); + } } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); @@ -214,13 +214,15 @@ class _NewRequestState extends State { pIDCOLUMNNAME: DateFormat('yyyy/MM/dd HH:MM:SS', "en_US").format(date1), pRETURNMSG: "null", pRETURNSTATUS: getCCPDFFStructureModelList![index].dEFAULTVALUE, - pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy/MM/dd HH:MM:SS', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); + pVALUECOLUMNNAME: + getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy/MM/dd HH:MM:SS', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); } else { eservicesdv = ESERVICESDV( pIDCOLUMNNAME: DateFormat('yyyy-MM-dd', "en_US").format(date1), pRETURNMSG: "null", pRETURNSTATUS: getCCPDFFStructureModelList![index].dEFAULTVALUE, - pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy-MM-dd hh:mm:ss', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); + pVALUECOLUMNNAME: + getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy-MM-dd hh:mm:ss', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date)); } getCCPDFFStructureModelList![index].eSERVICESDV = eservicesdv; setState(() {});