From 9ab4ed69641153f26458195980900f428d8185a3 Mon Sep 17 00:00:00 2001
From: WaseemAbbasi22 <50428976+WaseemAbbasi22@users.noreply.github.com>
Date: Wed, 24 Jun 2026 17:27:25 +0300
Subject: [PATCH] notifications apis integrated
---
assets/images/Icon_mark_read.svg | 5 +
assets/images/notification_setting.svg | 4 +
lib/controllers/api_routes/api_manager.dart | 40 ++
lib/controllers/api_routes/urls.dart | 26 +-
.../providers/api/notifications_provider.dart | 96 ++++-
lib/l10n/app_ar.arb | 14 +-
lib/l10n/app_en.arb | 26 +-
lib/l10n/app_localizations.dart | 72 ++++
lib/l10n/app_localizations_ar.dart | 37 ++
lib/l10n/app_localizations_en.dart | 37 ++
lib/main.dart | 14 +
lib/models/module_with_submodules_model.dart | 66 ++++
lib/models/notification_filter_model.dart | 67 ++++
lib/models/system_notification_model.dart | 55 ++-
.../models/notification_channel_model.dart | 28 ++
.../models/notification_preference_model.dart | 167 ++++++++
.../notification_setting_provider.dart | 236 +++++++++++
.../view/notification_setting_page.dart | 138 +++++++
.../widgets/notification_preference_card.dart | 186 +++++++++
lib/new_views/app_style/app_color.dart | 8 +
lib/new_views/common_widgets/app_drawer.dart | 4 +
.../common_widgets/app_text_form_field.dart | 2 +-
.../modules_with_submodules_provider.dart | 37 ++
.../notification_channel_lookup_provider.dart | 36 ++
...notification_priority_lookup_provider.dart | 36 ++
...otification_recipient_lookup_provider.dart | 36 ++
.../notification_filter_page.dart | 340 ++++++++++++++++
.../notifications/notifications_list.dart | 46 ++-
.../notifications/notifications_page.dart | 368 ++++++++++++++++--
.../widgets/notification_card_redesigned.dart | 131 +++++++
.../widgets/notification_tab_button.dart | 55 +++
31 files changed, 2337 insertions(+), 76 deletions(-)
create mode 100644 assets/images/Icon_mark_read.svg
create mode 100644 assets/images/notification_setting.svg
create mode 100644 lib/models/module_with_submodules_model.dart
create mode 100644 lib/models/notification_filter_model.dart
create mode 100644 lib/modules/notification_setting/models/notification_channel_model.dart
create mode 100644 lib/modules/notification_setting/models/notification_preference_model.dart
create mode 100644 lib/modules/notification_setting/provider/notification_setting_provider.dart
create mode 100644 lib/modules/notification_setting/view/notification_setting_page.dart
create mode 100644 lib/modules/notification_setting/view/widgets/notification_preference_card.dart
create mode 100644 lib/providers/lookups/modules_with_submodules_provider.dart
create mode 100644 lib/providers/lookups/notification_channel_lookup_provider.dart
create mode 100644 lib/providers/lookups/notification_priority_lookup_provider.dart
create mode 100644 lib/providers/lookups/notification_recipient_lookup_provider.dart
create mode 100644 lib/views/pages/user/notifications/notification_filter_page.dart
create mode 100644 lib/views/pages/user/notifications/widgets/notification_card_redesigned.dart
create mode 100644 lib/views/pages/user/notifications/widgets/notification_tab_button.dart
diff --git a/assets/images/Icon_mark_read.svg b/assets/images/Icon_mark_read.svg
new file mode 100644
index 00000000..fd7ed9bd
--- /dev/null
+++ b/assets/images/Icon_mark_read.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/notification_setting.svg b/assets/images/notification_setting.svg
new file mode 100644
index 00000000..d007a3db
--- /dev/null
+++ b/assets/images/notification_setting.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/controllers/api_routes/api_manager.dart b/lib/controllers/api_routes/api_manager.dart
index 722e894e..ea8fcf06 100644
--- a/lib/controllers/api_routes/api_manager.dart
+++ b/lib/controllers/api_routes/api_manager.dart
@@ -336,6 +336,46 @@ class ApiManager {
return response;
}
+ /// POST request with List/Array body (for endpoints that expect JSON arrays)
+ Future postList(String url, {Map? headers, required List body, bool showToast = true}) async {
+ headers ??= {};
+
+ headers.addAll(_headers);
+
+ Uri url0 = Uri.parse(url);
+ if (!kReleaseMode) {
+ print("URL:$url0");
+ print("Headers:$headers");
+ print("Body:$body");
+ }
+
+ // OPTIMIZATION: Use persistent HTTP client for connection pooling
+ var request = http.Request('POST', url0);
+ request.body = json.encode(body);
+ request.headers.addAll(headers);
+
+ http.StreamedResponse streamedResponse = await _httpClient.send(request);
+ http.Response response = await http.Response.fromStream(streamedResponse);
+
+ // OPTIMIZATION: Parse JSON once and reuse (was parsing twice before)
+ try {
+ if (response.statusCode == 401) {
+ showLoginDialog();
+ } else {
+ // Parse response body only once
+ final responseBody = jsonDecode(response.body);
+ if (responseBody is Map) {
+ final message = responseBody["message"]; // Reuse parsed body
+ if (message != null && message.toString().isNotEmpty && showToast) {
+ Fluttertoast.showToast(msg: message, toastLength: Toast.LENGTH_LONG);
+ }
+ }
+ }
+ } catch (ex) {}
+
+ return response;
+ }
+
Future multiPart(String url, {Map? headers, required Map body, required List> files}) async {
Map headers0 = const {
'Content-Type': 'multipart/form-data',
diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart
index 36531408..77f8ad95 100644
--- a/lib/controllers/api_routes/urls.dart
+++ b/lib/controllers/api_routes/urls.dart
@@ -4,12 +4,12 @@ class URLs {
static const String appReleaseBuildNumber = "42";
// static const host1 = "https://atomsm.hmg.com"; // production url
- // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
- static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
+ static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
+ // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
- static final String _baseUrl = "$_host/mobile"; // host local UAT
+ // static final String _baseUrl = "$_host/mobile"; // host local UAT
// static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
- // static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
+ static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
// static final String _baseUrl = "$_host/v4/mobile"; // v4 for Demo module
// static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation
// static final String _baseUrl = "$_host/v6/mobile"; // for asset delivery module
@@ -236,7 +236,19 @@ class URLs {
static get addSupplierEngineer => "$_baseUrl/Supplier/AddSupplierEngineer";
- static get getSystemNotifications => "$_baseUrl/SystemNotification/GetSystemNotifications"; // get
+ // static get getSystemNotifications => "$_baseUrl/SystemNotification/GetSystemNotifications"; // get (OLD - COMMENTED OUT)
+ static get getNotificationInbox => "$_baseUrl/NotificationNew/Inbox"; // get notifications with filters
+ static get markAllNotificationsAsRead => "$_baseUrl/NotificationNew/MarkAllRead"; // mark all as read
+ static get markOneNotificationAsRead => "$_baseUrl/NotificationNew/MarkAsReadOneNotification"; // mark one notification as read
+
+ // Notification Filter Lookups
+ static get getNotificationPriorityLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=5022"; // notification priority filter
+ static get getNotificationChannelLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=5024"; // notification channel filter
+ static get getNotificationRecipientLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=5021"; // notification recipient filter
+
+ // Modules and SubModules
+ static get getModulesWithSubModules => "$_baseUrl/Module/GetModulesWithSubModules"; // get modules with submodules for filters
+
static get getRecentNotifications => "$_baseUrl/return/user/recent/notification"; // get
static get createRequest => "$_baseUrl/CallRequest/AddCallRequest"; // get
static get CheckIfAssetHasAnotherServiceRequest => "$_baseUrl/ServiceRequest/CheckForPendingRequestForAsset"; // get
@@ -565,5 +577,9 @@ class URLs {
// Print/Report URLs
static get generateReport => "$_baseUrl/ReportPDF/GenerateReport";
+ // Notification Preference Center
+ static String get getNotificationPreferences => "$_baseUrl/NotificationPreferenceCenter/GetTemplateApplyOnCurrentUser";
+ static String get saveNotificationPreferences => "$_baseUrl/NotificationPreferenceCenter/SaveNotificationPreferenceCenter";
+
//4104 attachment type lookup
}
diff --git a/lib/controllers/providers/api/notifications_provider.dart b/lib/controllers/providers/api/notifications_provider.dart
index 53d97eaa..49422655 100644
--- a/lib/controllers/providers/api/notifications_provider.dart
+++ b/lib/controllers/providers/api/notifications_provider.dart
@@ -4,6 +4,7 @@ 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/notification_filter_model.dart';
import 'package:test_sa/models/system_notification_model.dart';
import 'package:test_sa/models/user.dart';
@@ -11,6 +12,9 @@ class NotificationsProvider extends ChangeNotifier {
// number of items call in each request
final pageItemNumber = 12;
+ // Store active filters
+ NotificationFilterModel? activeFilters;
+
//reset provider data
void reset() {
notifications = [];
@@ -38,25 +42,49 @@ 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 getSystemNotifications({required User user, bool resetProvider = false}) async {
+ Future getSystemNotifications({
+ required User user,
+ bool resetProvider = false,
+ NotificationFilterModel? filters,
+ }) async {
if (isLoading == true) return -2;
if (resetProvider) {
reset();
}
+
+ // Store filters for pagination
+ if (filters != null) {
+ activeFilters = filters;
+ }
+
isLoading = true;
notifyListeners();
late Response response;
try {
- final Map body = {"pageSize": pageItemNumber, "pageNumber": notifications.length ~/ pageItemNumber + 1, "userId": user.userID};
- response = await ApiManager.instance.post(URLs.getSystemNotifications, body: body);
+ // Base request body with pagination
+ final Map body = {
+ "pageSize": pageItemNumber,
+ "pageNumber": notifications.length ~/ pageItemNumber + 1,
+ };
+
+ // Add filter parameters only if they have values
+ if (activeFilters != null) {
+ body.addAll(activeFilters!.toApiBody());
+ }
+ // Don't add null values if no filters are active - just send pagination params only
+
+ response = await ApiManager.instance.post(URLs.getNotificationInbox, body: body);
+
+ // OLD API - Commented out but kept for reference
+ // final Map body = {"pageSize": pageItemNumber, "pageNumber": notifications.length ~/ pageItemNumber + 1, "userId": user.userID};
+ // 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(response.body)["data"];
List serviceRequestsPage = requestsListJson.map((request) => SystemNotificationModel.fromJson(request)).toList();
- notifications ??= [];
notifications.addAll(serviceRequestsPage);
// Update nextPage based on response length
nextPage = serviceRequestsPage.length == pageItemNumber;
@@ -73,6 +101,62 @@ class NotificationsProvider extends ChangeNotifier {
}
}
+ /// Mark all notifications as read
+ /// Returns a map with success status and message from API
+ Future