diff --git a/assets/images/notf.png b/assets/images/notf.png new file mode 100644 index 00000000..39eb3fb3 Binary files /dev/null and b/assets/images/notf.png differ diff --git a/lib/config/config.dart b/lib/config/config.dart index 1577186a..ca1ed829 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -341,6 +341,8 @@ const GET_CMC_ORDER_DETAIL_BY_ID ="Services/Patients.svc/REST/PatientER_CMC_GetT const GET_CHECK_UP_ITEMS ="Services/Patients.svc/REST/GetCheckUpItems"; const PUSH_NOTIFICATION_GET_ALL_NOTIFICATIONS = 'Services/MobileNotifications.svc/REST/PushNotification_GetAllNotifications'; +const PUSH_NOTIFICATION_SET_MESSAGES_FROM_POOL_AS_READ = + 'Services/MobileNotifications.svc/REST/PushNotification_SetMessagesFromPoolAsRead'; const TIMER_MIN = 10; const GOOGLE_API_KEY = "AIzaSyCmevVlr2Bh-c8W1VUzo8gt8JRY7n5PANw"; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 0ef677e0..3b70c566 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -677,5 +677,6 @@ const Map> localizedValues = { "AppointmentLabel": {"en": "Appointment", "ar": "موعد"}, "BloodType": {"en": "Blood Type", "ar": "فصيلة الدم"}, "notifications": {"en": "Notifications", "ar": "إشعارات"}, + "notificationDetails": {"en": "Notification Details", "ar": "تفاصيل الاشعار"}, }; diff --git a/lib/core/model/notifications/mark_message_as_read_request_model.dart b/lib/core/model/notifications/mark_message_as_read_request_model.dart new file mode 100644 index 00000000..99dab006 --- /dev/null +++ b/lib/core/model/notifications/mark_message_as_read_request_model.dart @@ -0,0 +1,15 @@ +class MarkMessageAsReadRequestModel { + int notificationPoolID; + + MarkMessageAsReadRequestModel({this.notificationPoolID}); + + MarkMessageAsReadRequestModel.fromJson(Map json) { + notificationPoolID = json['NotificationPoolID']; + } + + Map toJson() { + final Map data = new Map(); + data['NotificationPoolID'] = this.notificationPoolID; + return data; + } +} diff --git a/lib/core/service/notifications_service.dart b/lib/core/service/notifications_service.dart index f8c8a211..87081a0f 100644 --- a/lib/core/service/notifications_service.dart +++ b/lib/core/service/notifications_service.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/model/notifications/get_notifications_request_model.dart'; import 'package:diplomaticquarterapp/core/model/notifications/get_notifications_response_model.dart'; +import 'package:diplomaticquarterapp/core/model/notifications/mark_message_as_read_request_model.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; class NotificationService extends BaseService { @@ -10,6 +11,7 @@ class NotificationService extends BaseService { hasError = false; await baseAppClient.post(PUSH_NOTIFICATION_GET_ALL_NOTIFICATIONS, onSuccess: (dynamic response, int statusCode) { + if(getNotificationsRequestModel.currentPage ==0) notificationsList.clear(); response['List_GetAllNotificationsFromPool'].forEach((appoint) { notificationsList.add(GetNotificationsResponseModel.fromJson(appoint)); @@ -19,4 +21,19 @@ class NotificationService extends BaseService { super.error = error; }, body: getNotificationsRequestModel.toJson()); } + Future markAsRead(MarkMessageAsReadRequestModel markMessageAsReadRequestModel ) async { + hasError = false; + await baseAppClient.post(PUSH_NOTIFICATION_SET_MESSAGES_FROM_POOL_AS_READ, + onSuccess: (dynamic response, int statusCode) { + updateNotification(markMessageAsReadRequestModel.notificationPoolID); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: markMessageAsReadRequestModel.toJson()); + } + + updateNotification(id) { + int index = notificationsList.indexWhere((element) => element.id == id); + notificationsList[index].isRead = true; + } } diff --git a/lib/core/viewModels/notifications_view_model.dart b/lib/core/viewModels/notifications_view_model.dart index 30cd63d9..d1bbeda4 100644 --- a/lib/core/viewModels/notifications_view_model.dart +++ b/lib/core/viewModels/notifications_view_model.dart @@ -1,25 +1,39 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/notifications/get_notifications_request_model.dart'; import 'package:diplomaticquarterapp/core/model/notifications/get_notifications_response_model.dart'; +import 'package:diplomaticquarterapp/core/model/notifications/mark_message_as_read_request_model.dart'; import 'package:diplomaticquarterapp/core/service/notifications_service.dart'; import '../../locator.dart'; import 'base_view_model.dart'; class NotificationViewModel extends BaseViewModel { - NotificationService _notificationService = - locator(); + NotificationService _notificationService = locator(); - List get notifications => _notificationService.notificationsList; + List get notifications => + _notificationService.notificationsList; - Future getNotifications() async { + Future getNotifications( + GetNotificationsRequestModel getNotificationsRequestModel) async { setState(ViewState.Busy); - GetNotificationsRequestModel getNotificationsRequestModel = new GetNotificationsRequestModel(currentPage: 0,pagingSize: 14,notificationStatusID: 2); - await _notificationService.getAllNotifications(getNotificationsRequestModel); + await _notificationService + .getAllNotifications(getNotificationsRequestModel); if (_notificationService.hasError) { error = _notificationService.error; setState(ViewState.Error); } else setState(ViewState.Idle); } + + Future markAsRead(id) async { + // setState(ViewState.Busy); + MarkMessageAsReadRequestModel markMessageAsReadRequestModel = + new MarkMessageAsReadRequestModel(notificationPoolID: id); + await _notificationService.markAsRead(markMessageAsReadRequestModel); + // if (_notificationService.hasError) { + // error = _notificationService.error; + // setState(ViewState.Error); + // } else + // setState(ViewState.Idle); + } } \ No newline at end of file diff --git a/lib/pages/DrawerPages/notifications/notification_details_page.dart b/lib/pages/DrawerPages/notifications/notification_details_page.dart new file mode 100644 index 00000000..3858c940 --- /dev/null +++ b/lib/pages/DrawerPages/notifications/notification_details_page.dart @@ -0,0 +1,103 @@ +import 'package:diplomaticquarterapp/core/model/notifications/get_notifications_response_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/notifications_view_model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/progress_indicator/app_circular_progress_Indeicator.dart'; +import 'package:flutter/material.dart'; + +class NotificationsDetailsPage extends StatelessWidget { + final GetNotificationsResponseModel notification; + + NotificationsDetailsPage({this.notification}); + + getDateForm(String date) { + DateTime d = DateUtil.convertStringToDate(date); + String monthName = DateUtil.getMonth(d.month).toString(); + TimeOfDay timeOfDay = TimeOfDay(hour: d.hour, minute: d.minute); + String minute = timeOfDay.minute < 10 + ? timeOfDay.minute.toString().padLeft(2, '0') + : timeOfDay.minute.toString(); + + String hour = '${timeOfDay.hourOfPeriod}:$minute'; + if (timeOfDay.period == DayPeriod.am) { + hour = hour + "AM"; + } else { + { + hour = hour + "PM"; + } + } + return monthName + ',${d.day},${d.year}, $hour'; + } + + @override + Widget build(BuildContext context) { + return BaseView( + builder: (_, model, widget) => AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).notificationDetails, + body: SingleChildScrollView( + child: Center( + child: FractionallySizedBox( + widthFactor: 0.9, + child: Column( + children: [ + SizedBox( + height: 25, + ), + Container( + // margin: EdgeInsets.only(left: 30), + width: double.infinity, + color: Colors.grey[400], + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Texts( + getDateForm(notification.createdOn), + fontSize: 16, + ), + ), + ), + SizedBox( + height: 15, + ), + if (notification.messageTypeData.length != 0) + FractionallySizedBox( + widthFactor: 0.9, + child: Image.network(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: AppCircularProgressIndicator(), + ), + ); + }, + fit: BoxFit + .fill) //Image.network(notification.messageTypeData), + ), + SizedBox( + height: 15, + ), + Row( + children: [ + Expanded( + child: Center( + child: Texts(notification.message), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/DrawerPages/notifications/notifications_page.dart b/lib/pages/DrawerPages/notifications/notifications_page.dart new file mode 100644 index 00000000..4790eb17 --- /dev/null +++ b/lib/pages/DrawerPages/notifications/notifications_page.dart @@ -0,0 +1,142 @@ +import 'package:diplomaticquarterapp/core/model/notifications/get_notifications_request_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/notifications_view_model.dart'; +import 'package:diplomaticquarterapp/pages/DrawerPages/notifications/notification_details_page.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +// ignore: must_be_immutable +class NotificationsPage extends StatelessWidget { + getDateForm(String date) { + DateTime d = DateUtil.convertStringToDate(date); + String monthName = DateUtil.getMonth(d.month).toString(); + TimeOfDay timeOfDay = TimeOfDay(hour: d.hour, minute: d.minute); + String minute = timeOfDay.minute < 10 + ? timeOfDay.minute.toString().padLeft(2, '0') + : timeOfDay.minute.toString(); + + String hour = '${timeOfDay.hourOfPeriod}:$minute'; + if (timeOfDay.period == DayPeriod.am) { + hour = hour + "AM"; + } else { + { + hour = hour + "PM"; + } + } + + //DayPeriod.am + return monthName + ',${d.day},${d.year}, $hour'; + } + + int currentIndex = 0; + + @override + Widget build(BuildContext context) { + var prescriptionReport; + return BaseView( + onModelReady: (model) { + GetNotificationsRequestModel getNotificationsRequestModel = + new GetNotificationsRequestModel( + currentPage: currentIndex, + pagingSize: 14, + notificationStatusID: 2); + + model.getNotifications(getNotificationsRequestModel); + }, + builder: (_, model, widget) => AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).notifications, + baseViewModel: model, + body: ListView( + children: model.notifications + .map( + (notification) => InkWell( + onTap: () async { + if(!notification.isRead) + await model.markAsRead(notification.id); + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => + NotificationsDetailsPage( + notification: notification, + ))); + }, + child: Container( + width: double.infinity, + margin: EdgeInsets.only( + top: 5, left: 10, right: 10, bottom: 5), + padding: EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(10.0), + ), + border: Border.all( + color: notification.isRead + ? Colors.grey[200] + : Theme.of(context).primaryColor, + width: 0.5), + ), + child: Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts(getDateForm(notification.createdOn)), + SizedBox( + height: 5, + ), + Row( + children: [ + Expanded( + child: Texts(notification.message)), + if (notification.messageType == "image") + Icon(FontAwesomeIcons.images) + ], + ), + SizedBox( + height: 5, + ), + ], + ), + ), + ), + SizedBox( + width: 15, + ), + ], + ), + ), + ), + ) + .toList() + ..add( + InkWell( + onTap: () { + currentIndex++; + GetNotificationsRequestModel + getNotificationsRequestModel = + new GetNotificationsRequestModel( + currentPage: currentIndex, + pagingSize: 14, + notificationStatusID: 2); + + model.getNotifications(getNotificationsRequestModel); + }, + child: Center( + child: Image.asset('assets/images/notf.png'), + ), + ), + )), + ), + ); + } +} diff --git a/lib/pages/DrawerPages/notifications_page.dart b/lib/pages/DrawerPages/notifications_page.dart deleted file mode 100644 index 4e6e7e42..00000000 --- a/lib/pages/DrawerPages/notifications_page.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'package:diplomaticquarterapp/core/viewModels/notifications_view_model.dart'; -import 'package:diplomaticquarterapp/pages/base/base_view.dart'; -import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; -import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; -import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; -import 'package:flutter/material.dart'; - -class NotificationsPage extends StatelessWidget { - getDateForm(String date) { - DateTime d = DateUtil.convertStringToDate(date); - String monthName = DateUtil.getMonth(d.month).toString(); - TimeOfDay timeOfDay = TimeOfDay(hour: d.hour, minute: d.minute); - String minute = timeOfDay.minute < 10 - ? timeOfDay.minute.toString().padLeft(2, '0') - : timeOfDay.minute.toString(); - - String hour = '${timeOfDay.hourOfPeriod}:$minute'; - if (timeOfDay.period == DayPeriod.am) { - hour = hour + "AM"; - } else { - { - hour = hour + "PM"; - } - } - - //DayPeriod.am - return monthName + ',${d.day},${d.year}, $hour'; - } - - @override - Widget build(BuildContext context) { - var prescriptionReport; - return BaseView( - onModelReady: (model) => model.getNotifications(), - builder: (_, model, widget) => AppScaffold( - isShowAppBar: true, - appBarTitle: TranslationBase.of(context).notifications, - baseViewModel: model, - body: ListView.builder( - itemBuilder: (context, index) => Container( - width: double.infinity, - margin: EdgeInsets.only(top: 5, left: 10, right: 10, bottom: 5), - padding: EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(10.0), - ), - border: Border.all( - color: model.notifications[index].isRead - ? Colors.grey[200] - : Theme.of(context).primaryColor, - width: 0.5), - ), - child: Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts( - getDateForm(model.notifications[index].createdOn)), - SizedBox( - height: 5, - ), - Texts(model.notifications[index].message), - SizedBox( - height: 5, - ), - Texts(model.notifications[index].notificationType), - ], - ), - ), - ), - SizedBox( - width: 15, - ), - ], - ), - ), - itemCount: model.notifications.length, - ), - ), - ); - } -} diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 64b3a969..33621b1a 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -734,6 +734,7 @@ class TranslationBase { String get loginToUseService => localizedValues['loginToUseService'][locale.languageCode]; String get notifications => localizedValues['notifications'][locale.languageCode]; + String get notificationDetails => localizedValues['notificationDetails'][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index f345f641..ab517337 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -4,7 +4,7 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart'; import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart'; -import 'package:diplomaticquarterapp/pages/DrawerPages/notifications_page.dart'; +import 'package:diplomaticquarterapp/pages/DrawerPages/notifications/notifications_page.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';