From 2c9f2dce08e2a13306d6fd32894a4f85348e82b0 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 5 Nov 2023 15:48:44 +0300 Subject: [PATCH] notifications api added. --- lib/controllers/api_routes/urls.dart | 2 +- .../firebase_notification_manger.dart | 26 ++++---- .../providers/api/notifications_provider.dart | 32 +++++----- lib/models/app_notification.dart | 26 -------- lib/models/system_notification_model.dart | 51 ++++++++++++++++ lib/new_views/common_widgets/app_drawer.dart | 25 ++++++-- lib/new_views/pages/splash_page.dart | 9 +-- lib/views/pages/splash_screen.dart | 9 +-- .../notifications/notifications_list.dart | 7 ++- .../notifications/notifications_page.dart | 59 ++++--------------- .../notifications/notification_item.dart | 10 ++-- 11 files changed, 134 insertions(+), 122 deletions(-) delete mode 100644 lib/models/app_notification.dart create mode 100644 lib/models/system_notification_model.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index d50e5066..14a19e32 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -58,7 +58,7 @@ class URLs { static get getSingleServiceRequest => "$_baseUrl/return/call/information"; // get static get getSuppliersAutoComplete => "$_baseUrl/Supplier/GetSuppliersAutoComplete"; - static get getNotifications => "$_baseUrl/return/user/notification"; // get + static get getSystemNotifications => "$_baseUrl/SystemNotification/GetSystemNotifications"; // get static get getRecentNotifications => "$_baseUrl/return/user/recent/notification"; // get static get createRequest => "$_baseUrl/CallRequest/AddCallRequest"; // get static get createReport => "$_baseUrl/handle/create/report/issue"; // get diff --git a/lib/controllers/notification/firebase_notification_manger.dart b/lib/controllers/notification/firebase_notification_manger.dart index 7e92b918..c9d60917 100644 --- a/lib/controllers/notification/firebase_notification_manger.dart +++ b/lib/controllers/notification/firebase_notification_manger.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; -import 'package:test_sa/models/app_notification.dart'; +import 'package:test_sa/models/system_notification_model.dart'; import 'notification_manger.dart'; @@ -53,18 +53,20 @@ class FirebaseNotificationManger { // Stream listener FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); - FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { - AppNotification notification = AppNotification.fromJson(message.data); - if (notification.path == null || notification.path.isEmpty) return; - Navigator.pushNamed(context, notification.path, arguments: notification.requestId); - }); + // todo @sikander, check notifications payload, because notification model is different to need to check from backend - FirebaseMessaging.onMessage.listen((RemoteMessage message) { - AppNotification notification = AppNotification.fromJson(message.data); - NotificationManger.showNotification( - title: message.notification.title, subtext: message.notification.body, hashcode: int.tryParse(notification.requestId ?? "") ?? 1, payload: json.encode(message.data)); - return; - }); + // FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { + // SystemNotificationModel notification = SystemNotificationModel.fromJson(message.data); + // if (notification.path == null || notification.path.isEmpty) return; + // Navigator.pushNamed(context, notification.path, arguments: notification.requestId); + // }); + // + // FirebaseMessaging.onMessage.listen((RemoteMessage message) { + // SystemNotificationModel notification = SystemNotificationModel.fromJson(message.data); + // NotificationManger.showNotification( + // title: message.notification.title, subtext: message.notification.body, hashcode: int.tryParse(notification.requestId ?? "") ?? 1, payload: json.encode(message.data)); + // return; + // }); } } diff --git a/lib/controllers/providers/api/notifications_provider.dart b/lib/controllers/providers/api/notifications_provider.dart index b7683ab5..f7970e3a 100644 --- a/lib/controllers/providers/api/notifications_provider.dart +++ b/lib/controllers/providers/api/notifications_provider.dart @@ -2,8 +2,9 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; 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/app_notification.dart'; +import 'package:test_sa/models/system_notification_model.dart'; import 'package:test_sa/models/user.dart'; class NotificationsProvider extends ChangeNotifier { @@ -12,7 +13,7 @@ class NotificationsProvider extends ChangeNotifier { //reset provider data void reset() { - notifications = null; + notifications = []; nextPage = true; stateCode = null; } @@ -26,7 +27,7 @@ class NotificationsProvider extends ChangeNotifier { bool nextPage = true; // list of user requests - List notifications; + List notifications = []; // when requests in-process _loading = true // done _loading = true @@ -38,7 +39,7 @@ class NotificationsProvider extends ChangeNotifier { /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getNotifications({ + Future getSystemNotifications({ @required String host, @required User user, @required int hospitalId, @@ -47,19 +48,17 @@ class NotificationsProvider extends ChangeNotifier { isLoading = true; notifyListeners(); Response response; - // userId = 397.toString(); // testing id to view data try { - response = await get( - Uri.parse(URLs.getNotifications + - "?uid=${user.id}" - "&token=${user.token}" - "&page=${(notifications?.length ?? 0) ~/ pageItemNumber}"), - headers: {"Content-Type": "application/json; charset=utf-8"}); + final Map body = {"pageSize": pageItemNumber, "pageNumber": notifications.length ~/ pageItemNumber + 1}; + response = await ApiManager.instance.post(URLs.getSystemNotifications, body: body); + stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List _serviceRequestsPage = requestsListJson.map((request) => AppNotification.fromJson(request)).toList(); + // List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); + + List requestsListJson = json.decode(response.body)["data"]; + List _serviceRequestsPage = requestsListJson.map((request) => SystemNotificationModel.fromJson(request)).toList(); if (notifications == null) notifications = []; notifications.addAll(_serviceRequestsPage); if (_serviceRequestsPage.length == pageItemNumber) { @@ -72,6 +71,7 @@ class NotificationsProvider extends ChangeNotifier { notifyListeners(); return response.statusCode; } catch (error) { + print(error); isLoading = false; stateCode = -1; notifyListeners(); @@ -84,7 +84,7 @@ class NotificationsProvider extends ChangeNotifier { /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future> getRecentNotifications({ + Future> getRecentNotifications({ @required String host, @required User user, }) async { @@ -92,13 +92,13 @@ class NotificationsProvider extends ChangeNotifier { //userId = 397.toString(); // testing id to view data try { - response = await get(Uri.parse(host + URLs.getNotifications + "?uid=${user.id}&token=${user.token}"), headers: {"Content-Type": "application/json; charset=utf-8"}); + response = await get(Uri.parse(host + URLs.getSystemNotifications + "?uid=${user.id}&token=${user.token}"), headers: {"Content-Type": "application/json; charset=utf-8"}); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List _recentNotifications = requestsListJson.map((request) => AppNotification.fromJson(request)).toList(); + List _recentNotifications = requestsListJson.map((request) => SystemNotificationModel.fromJson(request)).toList(); return _recentNotifications; } return null; diff --git a/lib/models/app_notification.dart b/lib/models/app_notification.dart deleted file mode 100644 index 339e3121..00000000 --- a/lib/models/app_notification.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart'; - -class AppNotification { - String requestId; - String title; - String description; - String date; - String path; - - AppNotification({ - this.requestId, - this.title, - this.description, - this.date, - this.path, - }); - - factory AppNotification.fromJson(Map parsedJson) { - return AppNotification( - requestId: parsedJson["nid"], - title: parsedJson["call_client"] ?? parsedJson["title"], - description: parsedJson["task_description"], - date: parsedJson["creation_date"], - path: FutureRequestServiceDetails.id); - } -} diff --git a/lib/models/system_notification_model.dart b/lib/models/system_notification_model.dart new file mode 100644 index 00000000..dbfa942e --- /dev/null +++ b/lib/models/system_notification_model.dart @@ -0,0 +1,51 @@ +import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart'; + +class SystemNotificationModel { + String userId; + String userName; + String title; + String text; + int referenceId; + int sourceId; + String sourceName; + bool readed; + String readingDate; + int id; + String createdOn; + String modifiedOn; + + SystemNotificationModel( + {this.userId, this.userName, this.title, this.text, this.referenceId, this.sourceId, this.sourceName, this.readed, this.readingDate, this.id, this.createdOn, this.modifiedOn}); + + SystemNotificationModel.fromJson(Map json) { + userId = json['userId']; + userName = json['userName']; + title = json['title']; + text = json['text']; + referenceId = json['referenceId']; + sourceId = json['sourceId']; + sourceName = json['sourceName']; + readed = json['readed']; + readingDate = json['readingDate']; + id = json['id']; + createdOn = json['createdOn']; + modifiedOn = json['modifiedOn']; + } + + Map toJson() { + final Map data = new Map(); + data['userId'] = this.userId; + data['userName'] = this.userName; + data['title'] = this.title; + data['text'] = this.text; + data['referenceId'] = this.referenceId; + data['sourceId'] = this.sourceId; + data['sourceName'] = this.sourceName; + data['readed'] = this.readed; + data['readingDate'] = this.readingDate; + data['id'] = this.id; + data['createdOn'] = this.createdOn; + data['modifiedOn'] = this.modifiedOn; + return data; + } +} diff --git a/lib/new_views/common_widgets/app_drawer.dart b/lib/new_views/common_widgets/app_drawer.dart index a4d1713d..5f0891e3 100644 --- a/lib/new_views/common_widgets/app_drawer.dart +++ b/lib/new_views/common_widgets/app_drawer.dart @@ -6,6 +6,9 @@ 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/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; import '../../controllers/providers/api/user_provider.dart'; import '../../controllers/providers/settings/setting_provider.dart'; @@ -60,7 +63,7 @@ class AppDrawer extends StatelessWidget { ListView( padding: EdgeInsets.only(top: 24), children: [ - drawerItem("drawer_notification", "Notification"), + drawerItem("drawer_notification", "Notification").onPress(() => Navigator.of(context).pushNamed(NotificationsPage.id)), 18.height, drawerItem("help_center", "Help Center"), 18.height, @@ -97,7 +100,7 @@ class AppDrawer extends StatelessWidget { ), ], ), - drawerItem("logout", "Logout").onPress(() { + drawerItem("logout", "Logout", color: AppColor.red50).onPress(() { /// TODO [zaid] : show dialog before logout // bool result = await showDialog( // context: context, @@ -115,9 +118,21 @@ class AppDrawer extends StatelessWidget { }), 18.height, 1.divider, - 24.height, + 18.height, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Powered By Cloud Solutions", + style: Theme.of(context).textTheme.headline6.copyWith(fontWeight: FontWeight.w500, color: AColors.grey3A, fontSize: 12), + textScaleFactor: AppStyle.getScaleFactor(context), + ), + 6.width, + Image.asset("assets/images/cloud_logo.png", width: 32, height: 32) + ], + ) ], - ).paddingOnly(top: 66, start: 16, end: 24, bottom: 62), + ).paddingOnly(top: 66, start: 16, end: 24, bottom: 18), ); } @@ -133,7 +148,7 @@ class AppDrawer extends StatelessWidget { 16.width, Text( title, - style: AppTextStyles.heading6.copyWith(color: const Color(0xFF3B3D4A)), + style: AppTextStyles.heading6.copyWith(color: color ?? const Color(0xFF3B3D4A)), ), ], ); diff --git a/lib/new_views/pages/splash_page.dart b/lib/new_views/pages/splash_page.dart index b6ba6774..433bd7f6 100644 --- a/lib/new_views/pages/splash_page.dart +++ b/lib/new_views/pages/splash_page.dart @@ -8,7 +8,7 @@ import 'package:test_sa/controllers/notification/notification_manger.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/app_notification.dart'; +import 'package:test_sa/models/system_notification_model.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; import 'package:test_sa/new_views/pages/login_page.dart'; @@ -31,9 +31,10 @@ class _SplashPageState extends State { void initState() { Firebase.initializeApp(); NotificationManger.initialisation((notificationDetails) { - AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload)); - if (notification.path == null || notification.path.isEmpty) return; - Navigator.pushNamed(context, notification.path, arguments: notification.requestId); + // todo @sikander, check notifications payload, because notification model is different to need to check from backend + // SystemNotificationModel notification = SystemNotificationModel.fromJson(json.decode(notificationDetails.payload)); + // if (notification.path == null || notification.path.isEmpty) return; + // Navigator.pushNamed(context, notification.path, arguments: notification.requestId); }, (id, title, body, payload) async {}); super.initState(); } diff --git a/lib/views/pages/splash_screen.dart b/lib/views/pages/splash_screen.dart index 903d613c..9eaf7ab6 100644 --- a/lib/views/pages/splash_screen.dart +++ b/lib/views/pages/splash_screen.dart @@ -7,7 +7,7 @@ import 'package:provider/provider.dart'; import 'package:test_sa/controllers/notification/notification_manger.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; -import 'package:test_sa/models/app_notification.dart'; +import 'package:test_sa/models/system_notification_model.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; @@ -39,9 +39,10 @@ class _SplashScreenState extends State { Firebase.initializeApp(); NotificationManger.initialisation((notificationDetails) { - AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload)); - if (notification.path == null || notification.path.isEmpty) return; - Navigator.pushNamed(context, notification.path, arguments: notification.requestId); + // todo @sikander, check notifications payload, because notification model is different to need to check from backend + // SystemNotificationModel notification = SystemNotificationModel.fromJson(json.decode(notificationDetails.payload)); + // if (notification.path == null || notification.path.isEmpty) return; + // Navigator.pushNamed(context, notification.path, arguments: notification.requestId); }, (id, title, body, payload) async {}); super.initState(); } diff --git a/lib/views/pages/user/notifications/notifications_list.dart b/lib/views/pages/user/notifications/notifications_list.dart index fa156074..c01425f4 100644 --- a/lib/views/pages/user/notifications/notifications_list.dart +++ b/lib/views/pages/user/notifications/notifications_list.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/extensions/context_extension.dart'; -import 'package:test_sa/models/app_notification.dart'; +import 'package:test_sa/models/system_notification_model.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; @@ -9,7 +9,7 @@ import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; import 'package:test_sa/views/widgets/notifications/notification_item.dart'; class NotificationsList extends StatelessWidget { - final List notifications; + final List notifications; final bool nextPage; final Future Function() onLazyLoad; @@ -34,7 +34,8 @@ class NotificationsList extends StatelessWidget { return NotificationItem( notification: notifications[itemIndex], onPressed: (notification) { - Navigator.of(context).pushNamed(FutureRequestServiceDetails.id, arguments: notification.requestId); + // todo @sikander, check notifications payload, because notification model is different to need to check from backend + //Navigator.of(context).pushNamed(FutureRequestServiceDetails.id, arguments: notification.requestId); }, ); }), diff --git a/lib/views/pages/user/notifications/notifications_page.dart b/lib/views/pages/user/notifications/notifications_page.dart index 17487982..49d8253d 100644 --- a/lib/views/pages/user/notifications/notifications_page.dart +++ b/lib/views/pages/user/notifications/notifications_page.dart @@ -6,6 +6,7 @@ import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_list.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; @@ -28,8 +29,8 @@ class _NotificationsPageState extends State with TickerProvid _notificationsProvider = Provider.of(context); _userProvider = Provider.of(context); _settingProvider = Provider.of(context); - return Scaffold( + appBar: DefaultAppBar(title: context.translation.notifications), body: SafeArea( child: LoadingManager( isLoading: _notificationsProvider.isLoading, @@ -37,56 +38,22 @@ class _NotificationsPageState extends State with TickerProvid stateCode: _notificationsProvider.stateCode, onRefresh: () async { _notificationsProvider.reset(); - await _notificationsProvider.getNotifications( + await _notificationsProvider.getSystemNotifications( user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, ); }, - child: Stack( - children: [ - Column( - children: [ - Container( - color: AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), - child: Column( - children: [ - Row( - children: [ - ABackButton(), - Expanded( - child: Center( - child: Text( - context.translation.notifications, - style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), - ), - ), - ), - SizedBox( - width: 48, - ) - ], - ), - ], - ), - ), - Expanded( - child: NotificationsList( - nextPage: _notificationsProvider.nextPage, - onLazyLoad: () async { - await _notificationsProvider.getNotifications( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.clientId, - ); - }, - notifications: _notificationsProvider.notifications, - ), - ), - ], - ), - ], + child: NotificationsList( + nextPage: _notificationsProvider.nextPage, + onLazyLoad: () async { + await _notificationsProvider.getSystemNotifications( + user: _userProvider.user, + host: _settingProvider.host, + hospitalId: _userProvider.user.clientId, + ); + }, + notifications: _notificationsProvider.notifications, ), ), ), diff --git a/lib/views/widgets/notifications/notification_item.dart b/lib/views/widgets/notifications/notification_item.dart index 6bce172c..be4412e3 100644 --- a/lib/views/widgets/notifications/notification_item.dart +++ b/lib/views/widgets/notifications/notification_item.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:test_sa/models/app_notification.dart'; +import 'package:test_sa/models/system_notification_model.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; class NotificationItem extends StatelessWidget { - final AppNotification notification; - final Function(AppNotification) onPressed; + final SystemNotificationModel notification; + final Function(SystemNotificationModel) onPressed; const NotificationItem({Key key, this.notification, this.onPressed}) : super(key: key); @@ -36,7 +36,7 @@ class NotificationItem extends StatelessWidget { ), ), Text( - notification.date ?? "complaint not available", + notification.createdOn ?? "complaint not available", style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white, fontSize: 12, fontWeight: FontWeight.bold), ), ], @@ -45,7 +45,7 @@ class NotificationItem extends StatelessWidget { color: AColors.white, ), Text( - notification.description ?? "complaint not available", + notification.text ?? "complaint not available", style: Theme.of(context).textTheme.subtitle1.copyWith( color: AColors.white, fontSize: 14,