diff --git a/assets/images/attachment_icon.svg b/assets/images/attachment_icon.svg
new file mode 100644
index 00000000..d0da9eaf
--- /dev/null
+++ b/assets/images/attachment_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/chat_attachment.svg b/assets/images/chat_attachment.svg
new file mode 100644
index 00000000..80d2003b
--- /dev/null
+++ b/assets/images/chat_attachment.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/chat_delivered.svg b/assets/images/chat_delivered.svg
new file mode 100644
index 00000000..4ac9df87
--- /dev/null
+++ b/assets/images/chat_delivered.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/chat_mic.svg b/assets/images/chat_mic.svg
new file mode 100644
index 00000000..60b5d00f
--- /dev/null
+++ b/assets/images/chat_mic.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/chat_msg_send.svg b/assets/images/chat_msg_send.svg
new file mode 100644
index 00000000..e0ad1ebc
--- /dev/null
+++ b/assets/images/chat_msg_send.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/chat_seen.svg b/assets/images/chat_seen.svg
new file mode 100644
index 00000000..f6aa3475
--- /dev/null
+++ b/assets/images/chat_seen.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/chat_sent.svg b/assets/images/chat_sent.svg
new file mode 100644
index 00000000..0af44564
--- /dev/null
+++ b/assets/images/chat_sent.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/star_empty.svg b/assets/images/star_empty.svg
new file mode 100644
index 00000000..03cb916c
--- /dev/null
+++ b/assets/images/star_empty.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/star_filled.svg b/assets/images/star_filled.svg
new file mode 100644
index 00000000..16abaa52
--- /dev/null
+++ b/assets/images/star_filled.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/controllers/api_routes/api_manager.dart b/lib/controllers/api_routes/api_manager.dart
index 20c55464..9594acd0 100644
--- a/lib/controllers/api_routes/api_manager.dart
+++ b/lib/controllers/api_routes/api_manager.dart
@@ -42,7 +42,9 @@ class ApiManager {
if (jsonDecode(response.body) is Map) {
final message = jsonDecode(response.body)["message"];
if (message != null && message.toString().isNotEmpty) {
- Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
+ if (enableToastMessage) {
+ 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 e283defd..2e7e5f56 100644
--- a/lib/controllers/api_routes/urls.dart
+++ b/lib/controllers/api_routes/urls.dart
@@ -4,18 +4,24 @@ class URLs {
static const String appReleaseBuildNumber = "28";
// 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 const host1 = "http://10.201.111.125:9495"; // temporary Server UAT url
-
// static String _baseUrl = "$_host/mobile";
+
static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/v4/mobile"; // for asset inventory on UAT
// static final String _baseUrl = "$_host/mobile"; // host local UAT
// static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
// static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation
+ static const String chatHubUrl = "https://apiderichat.hmg.com/chathub";
+
+ static const String chatHubUrlApi = "$chatHubUrl/api"; // new V2 apis
+ static const String chatHubUrlChat = "$chatHubUrl/hubs/chat"; // new V2 apis
+ static const String chatApiKey = "f53a98286f82798d588f67a7f0db19f7aebc839e"; // new V2 apis
+
static String _host = host1;
set host(String value) => _host = value;
@@ -171,8 +177,6 @@ class URLs {
static get taskJobImpactStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1264";
- static get getLoanPeriod => "$_baseUrl/Lookups/GetLookup?lookupEnum=3051";
-
//service request.....
static get getServiceRequests => "$_baseUrl/CallRequest/GetCallRequests"; // get
static get getServiceRequestById => "$_baseUrl/CallRequest/GetCallRequestById"; // get
@@ -311,6 +315,7 @@ class URLs {
static get getPentry => "$_baseUrl/return/pentry/details"; // get
static get updatePentry => "$_baseUrl/Visit/UpdateVisit"; // get
static get getPentryTaskStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=403"; // get
+ // get
static get getPentryVisitStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=402"; // get
static get getPentryStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=401"; // get
// contacts
@@ -346,7 +351,22 @@ class URLs {
static get getClassification => '$_baseUrl/AssetInventory/Classification';
- //Loan Module...
- //getDepartmentBasedOnSite
- static get getMedDepartmentBasedOnSite => '$_baseUrl/TRAFDataSource/GetDepartmentBasedOnSite';
+ //internal Audit
+ static get getInternalAuditEquipmentById => "$_baseUrl/InternalAuditEquipments/GetInternalAuditEquipmentById";
+ static get getInternalAuditSystemById => "$_baseUrl/InternalAuditSystems/GetInternalAuditSystemByIdV2";
+ static get getInternalAuditChecklist => "$_baseUrl/Lookups/GetLookup?lookupEnum=43";
+ static get getInternalAuditWoType => "$_baseUrl/Lookups/GetLookup?lookupEnum=2500";
+ static get getInternalAuditFindingType => "$_baseUrl/Lookups/GetLookup?lookupEnum=2502";
+ static get addOrUpdateEquipmentInternalAudit => "$_baseUrl/InternalAuditEquipments/AddOrUpdateAuditEquipment";
+ static get addOrUpdateInternalAuditSystem => "$_baseUrl/InternalAuditSystems/AddOrUpdateInternalAuditSystem";
+ static get getWoAutoComplete => "$_baseUrl/InternalAuditSystems/AutoCompleteAllWorkOrder";
+ static get updateAuditEquipmentsEngineer => "$_baseUrl/InternalAuditEquipments/UpdateAuditEquipmentsEngineer";
+ static get updateAuditSystemEngineer => "$_baseUrl/InternalAuditSystems/UpdateAuditSystemEngineer";
+ static get loadAllWorkOrderDetailsByID => "$_baseUrl/InternalAuditSystems/LoadAllWorkOrderDetailsByID";
+
+ //chat
+ static get chatSdkToken => '$chatHubUrlApi/auth/sdk-token';
+ //survey
+ static get getQuestionnaire => '$_baseUrl/SurveyQuestionnaire/GetQuestionnaire';
+ static get submitSurvey => '$_baseUrl/SurveyQuestionnaire/SubmitSurvey';
}
diff --git a/lib/controllers/notification/firebase_notification_manger.dart b/lib/controllers/notification/firebase_notification_manger.dart
index 16abd263..7a8a67f9 100644
--- a/lib/controllers/notification/firebase_notification_manger.dart
+++ b/lib/controllers/notification/firebase_notification_manger.dart
@@ -9,6 +9,7 @@ import 'package:test_sa/controllers/notification/notification_manger.dart';
import 'package:test_sa/models/device/device_transfer.dart';
import 'package:test_sa/models/new_models/gas_refill_model.dart';
import 'package:test_sa/modules/cm_module/views/service_request_detail_main_view.dart';
+import 'package:test_sa/modules/cx_module/survey/survey_page.dart';
import 'package:test_sa/modules/pm_module/ppm_wo/ppm_details_page.dart';
import 'package:test_sa/modules/pm_module/recurrent_wo/recurrent_work_order_view.dart';
import 'package:test_sa/views/pages/device_transfer/device_transfer_details.dart';
@@ -120,6 +121,9 @@ class FirebaseNotificationManger {
break;
case "12":
serviceClass = RecurrentWorkOrderView(taskId: int.parse(messageData["requestNumber"].toString()));
+ case "17":
+ serviceClass = SurveyPage(surveyId: int.parse(messageData["requestNumber"].toString()));
+
//Didn't handle task request yet...
// case 6:
// serviceClass = TaskRequestDetailsView(
diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart
index 470f803d..99f77a02 100644
--- a/lib/controllers/providers/api/all_requests_provider.dart
+++ b/lib/controllers/providers/api/all_requests_provider.dart
@@ -133,15 +133,24 @@ class AllRequestsProvider extends ChangeNotifier {
List getStatues(BuildContext context) {
List list = [1, 2, 3, 4];
+ //TODO need to refactor this code ....
if (context.userProvider.isAssessor) {
list = [9];
return list;
}
+ if (context.userProvider.isQualityUser) {
+
+ list = [10,11];
+ return list;
+ }
if (!context.userProvider.isNurse) {
list.add(5);
}
+ if (context.userProvider.isEngineer) {
+ list.add(10);
+ }
list.add(6); // task module
if (context.settingProvider.isUserFlowMedical && !context.userProvider.isNurse) {
diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart
index 40d6327a..8b522790 100644
--- a/lib/controllers/providers/api/gas_refill_provider.dart
+++ b/lib/controllers/providers/api/gas_refill_provider.dart
@@ -47,12 +47,16 @@ class GasRefillProvider extends ChangeNotifier {
// failed _loading = false
bool isLoading = false;
+ GasRefillModel? gasRefillModel;
+
Future getGasRefillObjectById(num id) async {
try {
+ gasRefillModel = null;
Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gasRefillId=$id");
-
if (response.statusCode >= 200 && response.statusCode < 300) {
- return GasRefillModel.fromJson(json.decode(response.body)["data"]);
+ gasRefillModel = GasRefillModel.fromJson(json.decode(response.body)["data"]);
+ notifyListeners();
+ return gasRefillModel;
} else {
return null;
}
diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart
index 481d06d5..471be087 100644
--- a/lib/controllers/providers/api/user_provider.dart
+++ b/lib/controllers/providers/api/user_provider.dart
@@ -45,6 +45,7 @@ class UserProvider extends ChangeNotifier {
bool get isNurse => user!.type == UsersTypes.normal_user;
bool get isAssessor => user!.type == UsersTypes.assessor || user!.type == UsersTypes.assessorTl;
+ bool get isQualityUser => user!.type == UsersTypes.qualityUser;
VerifyOtpModel _verifyOtpModel = VerifyOtpModel();
SwipeTransaction _swipeTransactionModel = SwipeTransaction();
diff --git a/lib/dashboard_latest/widgets/request_category_list.dart b/lib/dashboard_latest/widgets/request_category_list.dart
index 07d5d92d..9ca9daff 100644
--- a/lib/dashboard_latest/widgets/request_category_list.dart
+++ b/lib/dashboard_latest/widgets/request_category_list.dart
@@ -3,6 +3,7 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/inventory_session_item_view.dart';
+import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_item_view.dart';
import 'package:test_sa/modules/tm_module/tasks_wo/task_request_item_view.dart';
import 'package:test_sa/modules/traf_module/traf_request_item_view.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
@@ -56,6 +57,11 @@ class RequestCategoryList extends StatelessWidget {
return InventorySessionItemView(requestData: request);
case 9:
return TrafRequestItemView(requestData: request);
+ //TODO need to verify this ...
+ case 10:
+ return EquipmentInternalAuditItemView(requestData: request);
+ case 11:
+ return EquipmentInternalAuditItemView(requestData: request);
default:
return Container(
height: 100,
diff --git a/lib/extensions/context_extension.dart b/lib/extensions/context_extension.dart
index 85299f73..f85af74c 100644
--- a/lib/extensions/context_extension.dart
+++ b/lib/extensions/context_extension.dart
@@ -19,6 +19,7 @@ extension BuildContextExtension on BuildContext {
SettingProvider get settingProvider => Provider.of(this, listen: false);
UserProvider get userProvider => Provider.of(this, listen: false);
+
bool isTablet() {
final mediaQueryData = MediaQuery.of(this);
final double screenWidth = mediaQueryData.size.width;
@@ -27,9 +28,12 @@ extension BuildContextExtension on BuildContext {
bool isTablet = (devicePixelRatio < 2 && (screenWidth >= 700 || screenHeight >= 700)) || (devicePixelRatio >= 2 && (screenWidth >= 1000 || screenHeight >= 1000));
return isTablet;
}
- void showConfirmDialog(String message, {String? title, VoidCallback? onTap}) => showDialog(
+
+
+
+ void showConfirmDialog(String message, {String? title, VoidCallback? onTap, String? okTitle}) => showDialog(
context: this,
- builder: (BuildContext cxt) => ConfirmDialog(message: message, onTap: onTap, title: title),
+ builder: (BuildContext cxt) => ConfirmDialog(message: message, onTap: onTap, title: title,okTitle: okTitle),
);
Future showBottomSheet(Widget childWidget, {bool? isDismissible, String? title}) => showModalBottomSheet(
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index eabd9fce..855560d1 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -6,6 +6,21 @@ extension StringExtensions on String {
void get showToast => Fluttertoast.showToast(msg: this);
+ String get chatMsgTime {
+ DateTime dateTime = DateTime.parse(this).toLocal();
+ return DateFormat('hh:mm a').format(dateTime);
+ }
+
+ String get chatMsgDate {
+ DateTime dateTime = DateTime.parse(this).toLocal();
+ return DateFormat('EEE dd MMM').format(dateTime);
+ }
+
+ String get chatMsgDateWithYear {
+ DateTime dateTime = DateTime.parse(this).toLocal();
+ return DateFormat('EEE dd MMM, yyyy').format(dateTime);
+ }
+
String get toServiceRequestCardFormat {
DateTime dateTime = DateTime.parse(this);
return "${DateFormat('dd MMM, yyyy').format(dateTime)}\n${DateFormat('hh:mm a').format(dateTime)}";
diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart
index 8caa8ccf..3fd48cd8 100644
--- a/lib/extensions/widget_extensions.dart
+++ b/lib/extensions/widget_extensions.dart
@@ -79,13 +79,15 @@ extension WidgetExtensions on Widget {
: this;
}
- Widget toShimmer({bool isShow = true, double radius = 20, required BuildContext context}) => isShow
+ Widget toShimmer({bool isShow = true, double radius = 20, double? width, double? height, required BuildContext context}) => isShow
? Shimmer.fromColors(
baseColor: context.isDark ? AppColor.backgroundDark : const Color(0xffe8eff0),
highlightColor: AppColor.background(context),
child: ClipRRect(
borderRadius: BorderRadius.circular(radius),
child: Container(
+ width: width,
+ height: height,
color: AppColor.background(context),
child: this,
),
diff --git a/lib/helper/utils.dart b/lib/helper/utils.dart
index b56c7474..f4db3acd 100644
--- a/lib/helper/utils.dart
+++ b/lib/helper/utils.dart
@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_api_availability/google_api_availability.dart';
+
// import 'package:mohem_flutter_app/app_state/app_state.dart';
// import 'package:mohem_flutter_app/classes/colors.dart';
// import 'package:mohem_flutter_app/config/routes.dart';
@@ -23,6 +24,7 @@ import 'package:nfc_manager/platform_tags.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
+import 'package:test_sa/views/widgets/dialogs/loading_dialog.dart';
// ignore_for_file: avoid_annotating_with_dynamic
@@ -49,19 +51,21 @@ class Utils {
return null;
}
}
-static String getOrdinal(int number) {
- if (number >= 11 && number <= 13) return "${number}th";
- switch (number % 10) {
- case 1:
- return "${number}st";
- case 2:
- return "${number}nd";
- case 3:
- return "${number}rd";
- default:
- return "${number}th";
+
+ static String getOrdinal(int number) {
+ if (number >= 11 && number <= 13) return "${number}th";
+ switch (number % 10) {
+ case 1:
+ return "${number}st";
+ case 2:
+ return "${number}nd";
+ case 3:
+ return "${number}rd";
+ default:
+ return "${number}th";
+ }
}
-}
+
static int stringToHex(String colorCode) {
try {
return int.parse(colorCode.replaceAll("#", "0xff"));
@@ -73,7 +77,8 @@ static String getOrdinal(int number) {
static Future delay(int millis) async {
return await Future.delayed(Duration(milliseconds: millis));
}
- static bool isBeforeOrEqualCurrentTime(TimeOfDay t1, TimeOfDay t2) {
+
+ static bool isBeforeOrEqualCurrentTime(TimeOfDay t1, TimeOfDay t2) {
return t1.hour < t2.hour || (t1.hour == t2.hour && t1.minute <= t2.minute);
}
@@ -102,6 +107,21 @@ static String getOrdinal(int number) {
_isLoadingVisible = false;
}
+ static void showUploadingDialog(BuildContext context) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ _isLoadingVisible = true;
+
+ showDialog(
+ context: context,
+ barrierColor: Colors.black.withOpacity(0.5),
+ useRootNavigator: false,
+ builder: (BuildContext context) => const UploadingDialog(),
+ ).then((value) {
+ _isLoadingVisible = false;
+ });
+ });
+ }
+
static Future getStringFromPrefs(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(key) ?? "";
@@ -176,6 +196,7 @@ static String getOrdinal(int number) {
),
);
}
+
//
// static Widget getNoDataWidget(BuildContext context) {
// return Column(
@@ -421,15 +442,15 @@ static String getOrdinal(int number) {
}
return false;
}
- //
- // static bool isDate(String input, String format) {
- // try {
- // DateTime d = DateFormat(format).parseStrict(input);
- // //print(d);
- // return true;
- // } catch (e) {
- // //print(e);
- // return false;
- // }
- // }
+//
+// static bool isDate(String input, String format) {
+// try {
+// DateTime d = DateFormat(format).parseStrict(input);
+// //print(d);
+// return true;
+// } catch (e) {
+// //print(e);
+// return false;
+// }
+// }
}
diff --git a/lib/main.dart b/lib/main.dart
index 8b34b73a..29c6f8af 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -30,6 +30,13 @@ import 'package:test_sa/controllers/providers/api/status_drop_down/report/servic
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart';
import 'package:test_sa/modules/cm_module/views/nurse/create_new_request_view.dart';
+import 'package:test_sa/modules/cx_module/chat/chat_provider.dart';
+import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/create_equipment_internal_audit_form.dart';
+import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/create_system_internal_audit_form.dart';
+import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/update_system_internal_audit_page.dart';
+import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_finding_type_provider.dart';
+import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
+import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_wo_type_provider.dart';
import 'package:test_sa/modules/loan_module/pages/create_loan_request_view.dart';
import 'package:test_sa/modules/loan_module/provider/loan_period_provider.dart';
import 'package:test_sa/modules/loan_module/provider/loan_provider.dart';
@@ -103,6 +110,9 @@ import 'controllers/providers/api/gas_refill_comments.dart';
import 'controllers/providers/api/user_provider.dart';
import 'controllers/providers/settings/setting_provider.dart';
import 'dashboard_latest/dashboard_provider.dart';
+import 'modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart';
+import 'modules/internal_audit_module/provider/internal_audit_checklist_provider.dart';
+import 'modules/cx_module/survey/survey_provider.dart';
import 'new_views/pages/gas_refill_request_form.dart';
import 'providers/lookups/classification_lookup_provider.dart';
import 'providers/lookups/department_lookup_provider.dart';
@@ -242,8 +252,11 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ServiceReportRepairLocationProvider()),
ChangeNotifierProvider(create: (_) => ServiceRequestFaultDescriptionProvider()),
- ///todo deleted
- //ChangeNotifierProvider(create: (_) => ServiceReportVisitOperatorProvider()),
+ //chat
+ ChangeNotifierProvider(create: (_) => ChatProvider()),
+ //chat
+ ChangeNotifierProvider(create: (_) => SurveyProvider()),
+
///todo deleted
//ChangeNotifierProvider(create: (_) => ServiceReportMaintenanceSituationProvider()),
//ChangeNotifierProvider(create: (_) => ServiceReportUsersProvider()),
@@ -290,6 +303,10 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => PpmServiceProvider()),
ChangeNotifierProvider(create: (_) => CommentsProvider()),
ChangeNotifierProvider(create: (_) => GasRefillCommentsProvider()),
+ ChangeNotifierProvider(create: (_) => InternalAuditCheckListProvider()),
+ ChangeNotifierProvider(create: (_) => InternalAuditWoTypeProvider()),
+ ChangeNotifierProvider(create: (_) => InternalAuditProvider()),
+ ChangeNotifierProvider(create: (_) => InternalAuditFindingTypeProvider()),
///todo deleted
//ChangeNotifierProvider(create: (_) => RequestStatusProvider()),
@@ -361,6 +378,10 @@ class MyApp extends StatelessWidget {
ProfilePage.id: (_) => const ProfilePage(),
ReportBugPage.id: (_) => const ReportBugPage(),
HelpCenterPage.id: (_) => const HelpCenterPage(),
+ CreateEquipmentInternalAuditForm.id: (_) => const CreateEquipmentInternalAuditForm(),
+ CreateSystemInternalAuditForm.id: (_) => const CreateSystemInternalAuditForm(),
+ UpdateEquipmentInternalAuditPage.id: (_) => UpdateEquipmentInternalAuditPage(),
+ UpdateSystemInternalAuditPage.id: (_) => UpdateSystemInternalAuditPage(),
CreateLoanRequestView.id: (_) => const CreateLoanRequestView(),
// SwipeSuccessView.routeName: (_) => const SwipeSuccessView(),
// SwipeHistoryView.routeName: (_) => const SwipeHistoryView(),
diff --git a/lib/models/enums/user_types.dart b/lib/models/enums/user_types.dart
index 63f1d9d7..cd6b5f13 100644
--- a/lib/models/enums/user_types.dart
+++ b/lib/models/enums/user_types.dart
@@ -3,5 +3,6 @@ enum UsersTypes {
normal_user, // 1
nurse, // 1
assessor,
- assessorTl
+ assessorTl,
+ qualityUser
}
diff --git a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart
index dda5432b..21541769 100644
--- a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart
+++ b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart
@@ -31,11 +31,11 @@ class ActivityMaintenanceHelperModel {
WorkOrderAssignedEmployee? assignedEmployee;
SuppEngineerWorkOrders? supEngineer;
ActivityMaintenanceAssistantEmployees? modelAssistantEmployees;
+ List? assistantEmployList=[];
List? assistantEmployees;
List? activityMaintenanceTimers = [];
TimerModel? activityMaintenanceTimerModel = TimerModel();
TimerModel? activityTimePicker;
- List? assistantEmployList=[];
List? timerModelList = [];
ActivityMaintenanceHelperModel(
diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart
index febd3d80..25519bd6 100644
--- a/lib/models/new_models/work_order_detail_model.dart
+++ b/lib/models/new_models/work_order_detail_model.dart
@@ -348,33 +348,46 @@ class AssetGroup {
}
class WorkOrderAssignedEmployee {
- WorkOrderAssignedEmployee({
- required this.userId,
- required this.userName,
- required this.email,
- required this.languageId,
- });
-
- String userId;
+ String? userId;
String? userName;
String? email;
+ String? employeeId;
int? languageId;
+ String? extensionNo;
+ String? phoneNumber;
+ String? positionName;
+ String? position;
+ bool? isActive;
- factory WorkOrderAssignedEmployee.fromJson(Map json) {
- return WorkOrderAssignedEmployee(
- userId: json["userId"],
- userName: json["userName"],
- email: json["email"],
- languageId: json["languageId"],
- );
+ WorkOrderAssignedEmployee({this.userId, this.userName, this.email, this.employeeId, this.languageId, this.extensionNo, this.phoneNumber, this.positionName, this.position, this.isActive});
+
+ WorkOrderAssignedEmployee.fromJson(Map json) {
+ userId = json['userId'];
+ userName = json['userName'];
+ email = json['email'];
+ employeeId = json['employeeId'];
+ languageId = json['languageId'];
+ extensionNo = json['extensionNo'];
+ phoneNumber = json['phoneNumber'];
+ positionName = json['positionName'];
+ position = json['position'];
+ isActive = json['isActive'];
}
- Map toJson() => {
- "userId": userId,
- "userName": userName,
- "email": email,
- "languageId": languageId,
- };
+ Map toJson() {
+ final Map data = new Map();
+ data['userId'] = this.userId;
+ data['userName'] = this.userName;
+ data['email'] = this.email;
+ data['employeeId'] = this.employeeId;
+ data['languageId'] = this.languageId;
+ data['extensionNo'] = this.extensionNo;
+ data['phoneNumber'] = this.phoneNumber;
+ data['positionName'] = this.positionName;
+ data['position'] = this.position;
+ data['isActive'] = this.isActive;
+ return data;
+ }
}
class AssetLoan {
diff --git a/lib/models/system_notification_model.dart b/lib/models/system_notification_model.dart
index f307b289..e2cf4b39 100644
--- a/lib/models/system_notification_model.dart
+++ b/lib/models/system_notification_model.dart
@@ -13,7 +13,7 @@ class SystemNotificationModel {
String? modifiedOn;
String? priorityName;
String? statusName;
- int ? transactionType;
+ int? transactionType;
SystemNotificationModel(
{this.userId,
@@ -29,7 +29,7 @@ class SystemNotificationModel {
this.createdOn,
this.modifiedOn,
this.priorityName,
- this.transactionType,
+ this.transactionType,
this.statusName});
SystemNotificationModel.fromJson(Map? json) {
diff --git a/lib/models/user.dart b/lib/models/user.dart
index 0bb4ab23..2fd42598 100644
--- a/lib/models/user.dart
+++ b/lib/models/user.dart
@@ -1,3 +1,4 @@
+import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
@@ -107,12 +108,13 @@ class User {
return UsersTypes.assessor;
case "R-19": // Head Nurse Role
return UsersTypes.assessorTl;
+ case "R-3": // Quality User
+ return UsersTypes.qualityUser;
default:
return null;
}
}
-
Map toUpdateProfileJson() {
Map jsonObject = {};
// if (departmentId != null) jsonObject["department"] = departmentId;
diff --git a/lib/modules/cm_module/views/components/service_request_detail_view.dart b/lib/modules/cm_module/views/components/service_request_detail_view.dart
index 992c0060..440715e9 100644
--- a/lib/modules/cm_module/views/components/service_request_detail_view.dart
+++ b/lib/modules/cm_module/views/components/service_request_detail_view.dart
@@ -72,52 +72,44 @@ class _ServiceRequestDetailViewState extends State {
? const CircularProgressIndicator(color: AppColor.primary10).center
: requestProvider.currentWorkOrder == null
? const NoDataFound()
- : Stack(
- children: [
- Column(
+ : Column(
+ children: [
+ SingleChildScrollView(
+ padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
- SingleChildScrollView(
- padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider),
- initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider),
- 12.height,
- assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider),
- 12.height,
- if (context.userProvider.user!.type == UsersTypes.engineer &&
- !requestProvider.isReadOnlyRequest &&
- requestProvider.currentWorkOrder!.data!.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) ...[
- costCard(context, requestProvider),
- 12.height,
- ],
- contactInfoCard(context, requestProvider.currentWorkOrder!.data!),
- 20.height,
- ],
- ),
- ).expanded,
- SafeArea(
- top: false,
- right: false,
- left: false,
- child: FooterActionButton.requestDetailsFooterWidget(
- workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!,
- status: requestProvider.currentWorkOrder?.data?.status,
- isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null,
- activities: requestProvider.currentWorkOrder!.data?.activities ?? [],
- userProvider: _userProvider,
- context: context),
- ).toShadowContainer(context, padding: 0, showShadow: false, borderRadius: 0),
+ workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider),
+ initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider),
+ 12.height,
+ assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider),
+ 12.height,
+ if (context.userProvider.user!.type == UsersTypes.engineer &&
+ !requestProvider.isReadOnlyRequest &&
+ requestProvider.currentWorkOrder!.data!.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) ...[
+ costCard(context, requestProvider),
+ 12.height,
+ ],
+ contactInfoCard(context, requestProvider.currentWorkOrder!.data!),
+ 20.height,
],
),
- //no need to show timer as discussed with backend
- // if (requestProvider.timer != null && requestProvider.timer!.isActive) ...[
- // const TimerWidget(),
- // ]
- ],
- );
+ ).expanded,
+ SafeArea(
+ top: false,
+ right: false,
+ left: false,
+ child: FooterActionButton.requestDetailsFooterWidget(
+ workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!,
+ status: requestProvider.currentWorkOrder?.data?.status,
+ isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null,
+ activities: requestProvider.currentWorkOrder!.data?.activities ?? [],
+ userProvider: _userProvider,
+ context: context),
+ ).toShadowContainer(context, padding: 0, showShadow: false, borderRadius: 0),
+ ],
+ );
});
}
diff --git a/lib/modules/cm_module/views/forms/asset_retired/asset_retired.dart b/lib/modules/cm_module/views/forms/asset_retired/asset_retired.dart
index 34416d06..e36e430a 100644
--- a/lib/modules/cm_module/views/forms/asset_retired/asset_retired.dart
+++ b/lib/modules/cm_module/views/forms/asset_retired/asset_retired.dart
@@ -55,8 +55,6 @@ class _AssetRetiredState extends State with TickerProviderStateMix
@override
Widget build(BuildContext context) {
-
-
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.assetToBeRetired),
@@ -125,9 +123,9 @@ class _AssetRetiredState extends State with TickerProviderStateMix
onPressed: () async {
requestDetailProvider.assetRetiredHelperModel?.activityAssetToBeRetiredAttachments = [];
for (var item in _attachments) {
- String fileName = ServiceRequestUtils.isLocalUrl(item.name??'') ? ("${item.name??''.split("/").last}|${base64Encode(File(item.name??'').readAsBytesSync())}") :item.name??'';
- requestDetailProvider.assetRetiredHelperModel?.activityAssetToBeRetiredAttachments
- ?.add(ActivityAssetToBeRetiredAttachments(id: item.id, name: fileName));
+ String fileName =
+ ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
+ requestDetailProvider.assetRetiredHelperModel?.activityAssetToBeRetiredAttachments?.add(ActivityAssetToBeRetiredAttachments(id: item.id, name: fileName));
}
int status = await requestDetailProvider.createActivityAssetToBeRetired();
if (status == 200) {
diff --git a/lib/modules/cm_module/views/service_request_detail_main_view.dart b/lib/modules/cm_module/views/service_request_detail_main_view.dart
index bd89910c..7f9ad154 100644
--- a/lib/modules/cm_module/views/service_request_detail_main_view.dart
+++ b/lib/modules/cm_module/views/service_request_detail_main_view.dart
@@ -1,3 +1,4 @@
+import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
@@ -10,6 +11,9 @@ import 'package:test_sa/models/enums/work_order_next_step.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/bottom_sheets/service_request_bottomsheet.dart';
+import 'package:test_sa/modules/cx_module/chat/chat_page.dart';
+import 'package:test_sa/modules/cx_module/chat/chat_provider.dart';
+import 'package:test_sa/modules/cx_module/survey/survey_page.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
@@ -30,10 +34,13 @@ class ServiceRequestDetailMain extends StatefulWidget {
class _ServiceRequestDetailMainState extends State {
late ServiceRequestDetailProvider _requestProvider;
+ static const int moduleId = 1;
+
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
+ Provider.of(context, listen: false).reset();
getInitialData();
});
}
@@ -81,6 +88,37 @@ class _ServiceRequestDetailMainState extends State {
Navigator.pop(context);
},
actions: [
+ if (context.userProvider.isEngineer || context.userProvider.isNurse)
+ Selector(
+ selector: (_, myModel) => myModel.isLoading, // Selects only the userName
+ builder: (_, isLoading, __) {
+ if (isLoading) {
+ return const SizedBox();
+ } else {
+ ServiceRequestDetailProvider provider = Provider.of(context, listen: false);
+ int? statusValue = provider.currentWorkOrder?.data?.status?.value;
+ if (statusValue == 2 || statusValue == 3 || statusValue == 5 || statusValue == 6) {
+ getChatToken(moduleId, provider.currentWorkOrder?.data?.workOrderNo ?? "");
+ return Consumer(builder: (pContext, requestProvider, _) {
+ return IconButton(
+ icon: const Icon(Icons.chat_bubble),
+ onPressed: () {
+ Navigator.push(
+ context,
+ CupertinoPageRoute(
+ builder: (context) => ChatPage(
+ moduleId: moduleId,
+ requestId: widget.requestId,
+ title: _requestProvider.currentWorkOrder?.data?.workOrderNo ?? "",
+ readOnly: _requestProvider.isReadOnlyRequest,
+ )));
+ },
+ ).toShimmer(context: context, isShow: requestProvider.chatLoginTokenLoading, radius: 30, height: 30, width: 30);
+ });
+ }
+ return const SizedBox();
+ }
+ }),
isNurse
? IconButton(
icon: 'qr'.toSvgAsset(
@@ -140,4 +178,17 @@ class _ServiceRequestDetailMainState extends State {
)),
);
}
+
+ void getChatToken(int moduleId, String title) {
+ ChatProvider cProvider = Provider.of(context, listen: false);
+ if (cProvider.chatLoginResponse != null && cProvider.referenceID == widget.requestId) return;
+ String assigneeEmployeeNumber = Provider.of(context, listen: false).currentWorkOrder?.data?.assignedEmployee?.employeeId ?? "";
+ String myEmployeeId = context.userProvider.user!.username!;
+
+ String receiver = context.userProvider.isNurse
+ ? assigneeEmployeeNumber
+ : (context.userProvider.isEngineer ? Provider.of(context, listen: false).currentWorkOrder!.data!.workOrderContactPerson.first.employeeId! : "");
+
+ cProvider.getUserAutoLoginTokenSilent(moduleId, widget.requestId, title, myEmployeeId, receiver);
+ }
}
diff --git a/lib/modules/cx_module/chat/api_client.dart b/lib/modules/cx_module/chat/api_client.dart
new file mode 100644
index 00000000..63e57b93
--- /dev/null
+++ b/lib/modules/cx_module/chat/api_client.dart
@@ -0,0 +1,295 @@
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:flutter/foundation.dart';
+import 'package:http/http.dart';
+import 'package:http/io_client.dart';
+// ignore_for_file: avoid_annotating_with_dynamic
+
+typedef FactoryConstructor = U Function(dynamic);
+
+class APIError {
+ dynamic errorCode;
+ int? errorType;
+ String? errorMessage;
+ int? errorStatusCode;
+
+ APIError(this.errorCode, this.errorMessage, this.errorType, this.errorStatusCode);
+
+ Map toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage, 'errorType': errorType, 'ErrorStatusCode': errorStatusCode};
+
+ @override
+ String toString() {
+ return jsonEncode(this);
+ }
+}
+
+APIException _throwAPIException(Response response) {
+ switch (response.statusCode) {
+ case 200:
+ APIError? apiError;
+ if (response.body != null && response.body.isNotEmpty) {
+ var jsonError = jsonDecode(response.body);
+ print(jsonError);
+ apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'], jsonError['ErrorStatusCode']);
+ }
+ return APIException(APIException.BAD_REQUEST, error: apiError);
+ case 400:
+ APIError? apiError;
+ if (response.body != null && response.body.isNotEmpty) {
+ var jsonError = jsonDecode(response.body);
+ apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'], jsonError['ErrorStatusCode']);
+ }
+ return APIException(APIException.BAD_REQUEST, error: apiError);
+ case 401:
+ return APIException(APIException.UNAUTHORIZED);
+ case 403:
+ return APIException(APIException.FORBIDDEN);
+ case 404:
+ return APIException(APIException.NOT_FOUND);
+ case 500:
+ return APIException(APIException.INTERNAL_SERVER_ERROR);
+ case 444:
+ var downloadUrl = response.headers["location"];
+ return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl);
+ default:
+ return APIException(APIException.OTHER);
+ }
+}
+
+class ApiClient {
+ static final ApiClient _instance = ApiClient._internal();
+
+ ApiClient._internal();
+
+ factory ApiClient() => _instance;
+
+ Future postJsonForObject(FactoryConstructor factoryConstructor, String url, T jsonObject,
+ {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async {
+ var _headers = {'Accept': 'application/json'};
+ if (headers != null && headers.isNotEmpty) {
+ _headers.addAll(headers);
+ }
+ if (!kReleaseMode) {
+ print("Url:$url");
+ var bodyJson = json.encode(jsonObject);
+ print("body:$bodyJson");
+ }
+ var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes, isFormData: isFormData);
+ try {
+ if (!kReleaseMode) {
+ // logger.i("Url: " + url);
+ // logger.i("res: " + response.body);
+ }
+
+ var jsonData = jsonDecode(response.body);
+ if (jsonData["IsAuthenticated"] != null) {
+ // AppState().setIsAuthenticated = jsonData["IsAuthenticated"];
+ }
+
+ // if(url.contains("GetOfferDiscountsConfigData")) {
+ // jsonData["ErrorMessage"] = "Service Not Available";
+ // jsonData["ErrorEndUserMessage"] = "Service Not Available";
+ // }
+
+ if (jsonData["ErrorMessage"] == null) {
+ return factoryConstructor(jsonData);
+ } else if (jsonData["MessageStatus"] == 2 && jsonData["IsOTPMaxLimitExceed"] == true) {
+ // await Utils.performLogout(AppRoutes.navigatorKey.currentContext, null);
+ throw const APIException(APIException.UNAUTHORIZED, error: null);
+ } else {
+ APIError? apiError;
+ apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage'], jsonData['ErrorType'] ?? 0, jsonData['ErrorStatusCode']);
+ throw APIException(APIException.BAD_REQUEST, error: apiError);
+ }
+ } catch (ex) {
+ if (ex is APIException) {
+ rethrow;
+ } else {
+ throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex);
+ }
+ }
+ }
+
+ Future postJsonForResponse(String url, T jsonObject,
+ {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async {
+ String? requestBody;
+ late Map stringObj;
+ if (jsonObject != null) {
+ requestBody = jsonEncode(jsonObject);
+ if (headers == null) {
+ headers = {'Content-Type': 'application/json'};
+ } else {
+ headers['Content-Type'] = 'application/json';
+ }
+ }
+
+ if (isFormData) {
+ headers = {'Content-Type': 'application/x-www-form-urlencoded'};
+ stringObj = ((jsonObject ?? {}) as Map).map((key, value) => MapEntry(key, value?.toString() ?? ""));
+ }
+
+ return await _postForResponse(url, isFormData ? stringObj : requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
+ }
+
+ Future _postForResponse(String url, requestBody, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async {
+ try {
+ var _headers = {};
+ if (token != null) {
+ _headers['Authorization'] = 'Bearer $token';
+ }
+
+ if (headers != null && headers.isNotEmpty) {
+ _headers.addAll(headers);
+ }
+
+ if (queryParameters != null) {
+ var queryString = new Uri(queryParameters: queryParameters).query;
+ url = url + '?' + queryString;
+ }
+ var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 120));
+
+ if (response.statusCode >= 200 && response.statusCode < 300) {
+ return response;
+ } else {
+ throw _throwAPIException(response);
+ }
+ } on SocketException catch (e) {
+ if (retryTimes > 0) {
+ print('will retry after 3 seconds...');
+ await Future.delayed(Duration(seconds: 3));
+ return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
+ } else {
+ throw APIException(APIException.OTHER, arguments: e);
+ }
+ } on HttpException catch (e) {
+ if (retryTimes > 0) {
+ print('will retry after 3 seconds...');
+ await Future.delayed(Duration(seconds: 3));
+ return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
+ } else {
+ throw APIException(APIException.OTHER, arguments: e);
+ }
+ } on TimeoutException catch (e) {
+ throw APIException(APIException.TIMEOUT, arguments: e);
+ } on ClientException catch (e) {
+ if (retryTimes > 0) {
+ print('will retry after 3 seconds...');
+ await Future.delayed(Duration(seconds: 3));
+ return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
+ } else {
+ throw APIException(APIException.OTHER, arguments: e);
+ }
+ }
+ }
+
+ Future getJsonForResponse(String url, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async {
+ if (headers == null) {
+ headers = {'Content-Type': 'application/json'};
+ } else {
+ headers['Content-Type'] = 'application/json';
+ }
+
+ if (!kReleaseMode) {
+ print("Url:$url");
+ // var bodyJson = json.encode(jsonObject);
+ // print("body:$bodyJson");
+ }
+
+ return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
+ }
+
+ Future _getForResponse(String url, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async {
+ try {
+ var _headers = {};
+ if (token != null) {
+ _headers['Authorization'] = 'Bearer $token';
+ }
+
+ if (headers != null && headers.isNotEmpty) {
+ _headers.addAll(headers);
+ }
+
+ if (queryParameters != null) {
+ var queryString = new Uri(queryParameters: queryParameters).query;
+ url = url + '?' + queryString;
+ }
+ var response = await _get(Uri.parse(url), headers: _headers).timeout(Duration(seconds: 60));
+
+ if (response.statusCode >= 200 && response.statusCode < 300) {
+ return response;
+ } else {
+ throw _throwAPIException(response);
+ }
+ } on SocketException catch (e) {
+ if (retryTimes > 0) {
+ print('will retry after 3 seconds...');
+ await Future.delayed(Duration(seconds: 3));
+ return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
+ } else {
+ throw APIException(APIException.OTHER, arguments: e);
+ }
+ } on HttpException catch (e) {
+ if (retryTimes > 0) {
+ print('will retry after 3 seconds...');
+ await Future.delayed(Duration(seconds: 3));
+ return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
+ } else {
+ throw APIException(APIException.OTHER, arguments: e);
+ }
+ } on TimeoutException catch (e) {
+ throw APIException(APIException.TIMEOUT, arguments: e);
+ } on ClientException catch (e) {
+ if (retryTimes > 0) {
+ print('will retry after 3 seconds...');
+ await Future.delayed(Duration(seconds: 3));
+ return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
+ } else {
+ throw APIException(APIException.OTHER, arguments: e);
+ }
+ }
+ }
+
+ Future _get(url, {Map? headers}) => _withClient((client) => client.get(url, headers: headers));
+
+ bool _certificateCheck(X509Certificate cert, String host, int port) => true;
+
+ Future _withClient(Future Function(Client) fn) async {
+ var httpClient = HttpClient()..badCertificateCallback = _certificateCheck;
+ var client = IOClient(httpClient);
+ try {
+ return await fn(client);
+ } finally {
+ client.close();
+ }
+ }
+
+ Future _post(url, {Map? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding));
+}
+
+class APIException implements Exception {
+ static const String BAD_REQUEST = 'api_common_bad_request';
+ static const String UNAUTHORIZED = 'api_common_unauthorized';
+ static const String FORBIDDEN = 'api_common_forbidden';
+ static const String NOT_FOUND = 'api_common_not_found';
+ static const String INTERNAL_SERVER_ERROR = 'api_common_internal_server_error';
+ static const String UPGRADE_REQUIRED = 'api_common_upgrade_required';
+ static const String BAD_RESPONSE_FORMAT = 'api_common_bad_response_format';
+ static const String OTHER = 'api_common_http_error';
+ static const String TIMEOUT = 'api_common_http_timeout';
+ static const String UNKNOWN = 'unexpected_error';
+
+ final String message;
+ final APIError? error;
+ final arguments;
+
+ const APIException(this.message, {this.arguments, this.error});
+
+ Map toJson() => {'message': message, 'error': error, 'arguments': '$arguments'};
+
+ @override
+ String toString() {
+ return jsonEncode(this);
+ }
+}
diff --git a/lib/modules/cx_module/chat/chat_api_client.dart b/lib/modules/cx_module/chat/chat_api_client.dart
new file mode 100644
index 00000000..b859e305
--- /dev/null
+++ b/lib/modules/cx_module/chat/chat_api_client.dart
@@ -0,0 +1,480 @@
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:http/http.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:test_sa/controllers/api_routes/api_manager.dart';
+import 'package:test_sa/controllers/api_routes/urls.dart';
+import 'package:test_sa/controllers/notification/firebase_notification_manger.dart';
+import 'package:test_sa/extensions/string_extensions.dart';
+import 'package:http/http.dart' as http;
+import 'package:test_sa/modules/cx_module/chat/model/chat_attachment_model.dart';
+import 'api_client.dart';
+import 'model/chat_login_response_model.dart';
+import 'model/chat_participant_model.dart';
+import 'model/get_search_user_chat_model.dart';
+import 'model/get_single_user_chat_list_model.dart';
+import 'model/get_user_login_token_model.dart' as userLoginTokenModel;
+import 'model/user_chat_history_model.dart';
+
+// import 'package:mohem_flutter_app/api/api_client.dart';
+// import 'package:mohem_flutter_app/app_state/app_state.dart';
+// import 'package:mohem_flutter_app/classes/consts.dart';
+// import 'package:mohem_flutter_app/classes/utils.dart';
+// import 'package:mohem_flutter_app/exceptions/api_exception.dart';
+// import 'package:mohem_flutter_app/main.dart';
+// import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart';
+// import 'package:mohem_flutter_app/models/chat/create_group_request.dart' as createGroup;
+// import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart';
+// import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
+// import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' as groups;
+// import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart';
+// import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as user;
+// import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav;
+
+class ChatApiClient {
+ static final ChatApiClient _instance = ChatApiClient._internal();
+
+ ChatApiClient._internal();
+
+ factory ChatApiClient() => _instance;
+
+ ChatLoginResponse? chatLoginResponse;
+
+ Future getChatLoginToken(int moduleId, int requestId, String title, String employeeNumber, String assigneeEmployeeNumber) async {
+ String platform;
+ if (Platform.isIOS) {
+ platform = "IOS";
+ } else {
+ if (await FirebaseNotificationManger.isGoogleServicesAvailable()) {
+ platform = "GOOGLE";
+ } else {
+ platform = "HUAWEI";
+ }
+ }
+ Response response = await ApiClient().postJsonForResponse(URLs.chatSdkToken, {
+ "apiKey": URLs.chatApiKey,
+ "employeeNumber": employeeNumber,
+ "assigneeEmployeeNumber": assigneeEmployeeNumber,
+ "userDetails": {"userName": ApiManager.instance.user?.username, "email": ApiManager.instance.user?.email},
+ "contextEnabled": true,
+ "moduleCode": moduleId.toString(),
+ "referenceId": requestId.toString(),
+ // "referenceType": "ticket",
+ "title": title,
+ "deviceToken": FirebaseNotificationManger.token,
+ "isHuaweiDevice": platform == "HUAWEI",
+ "platform": platform,
+ "voIPToken": null
+ });
+
+ if (!kReleaseMode) {
+ // logger.i("login-res: " + response.body);
+ }
+ if (response.statusCode == 200) {
+ chatLoginResponse = ChatLoginResponse.fromJson(jsonDecode(response.body));
+ }
+ return chatLoginResponse;
+ }
+
+ Future loadParticipants(int moduleId, int referenceId, String? assigneeEmployeeNumber) async {
+ Response response =
+ await ApiClient().getJsonForResponse("${URLs.chatHubUrlApi}/chat/context/$moduleId/$referenceId?assigneeEmployeeNumber=$assigneeEmployeeNumber", token: chatLoginResponse!.token);
+
+ if (!kReleaseMode) {
+ // logger.i("login-res: " + response.body);
+ }
+ if (response.statusCode == 200) {
+ return ChatParticipantModel.fromJson(jsonDecode(response.body));
+ } else {
+ return null;
+ }
+ }
+
+ Future> viewAllDocuments(int moduleId, int referenceId) async {
+ Response response = await ApiClient().getJsonForResponse("${URLs.chatHubUrlApi}/attachments/conversation?referenceId=$referenceId&moduleCode=$moduleId", token: chatLoginResponse!.token);
+
+ if (response.statusCode == 200) {
+ List data = jsonDecode(response.body)["response"];
+ return data.map((elemet) => ChatAttachment.fromJson(elemet)).toList();
+ } else {
+ return [];
+ }
+ }
+
+ Future> loadChatHistory(int moduleId, int referenceId, String myId, String otherId) async {
+ Response response = await ApiClient().postJsonForResponse(
+ "${URLs.chatHubUrlApi}/UserChatHistory/GetUserChatHistory/$myId/$otherId/0", {"moduleCode": moduleId.toString(), "referenceId": referenceId.toString()},
+ token: chatLoginResponse!.token);
+ try {
+ if (response.statusCode == 200) {
+ List data = jsonDecode(response.body);
+ return data.map((elemet) => SingleUserChatModel.fromJson(elemet)).toList();
+
+ // return UserChatHistoryModel.fromJson(jsonDecode(response.body));
+ } else {
+ return [];
+ }
+ } catch (ex) {
+ return [];
+ }
+ }
+
+/* Future sendTextMessage(String message, int conversationId) async {
+ try {
+ Response response =
+ await ApiClient().postJsonForResponse("${URLs.chatHubUrlApi}/chat/conversations/$conversationId/messages", {"content": message, "messageType": "Text"}, token: chatLoginResponse!.token);
+
+ if (response.statusCode == 200) {
+ return ChatResponse.fromJson(jsonDecode(response.body));
+ } else {
+ return null;
+ }
+ } catch (ex) {
+ print(ex);
+ return null;
+ }
+ }*/
+
+// Future getChatMemberFromSearch(String searchParam, int cUserId, int pageNo) async {
+// ChatUserModel chatUserModel;
+// Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync", {"employeeNumber": cUserId, "userName": searchParam, "pageNumber": pageNo},
+// token: AppState().chatDetails!.response!.token);
+// if (!kReleaseMode) {
+// logger.i("res: " + response.body);
+// }
+// chatUserModel = chatUserModelFromJson(response.body);
+// return chatUserModel;
+// }
+
+// //Get User Recent Chats
+// Future getRecentChats() async {
+// try {
+// Response response =
+//
+//
+// // await ApiManager.instance.get(URLs.getAllRequestsAndCount,h);
+//
+//
+// await ApiClient().getJsonForResponse(
+// "${ApiConsts.chatRecentUrl}getchathistorybyuserid",
+// token: AppState().chatDetails!.response!.token,
+// );
+// if (!kReleaseMode) {
+// logger.i("res: " + response.body);
+// }
+// return ChatUserModel.fromJson(
+// json.decode(response.body),
+// );
+// } catch (e) {
+// throw e;
+// }
+// }
+
+// // Get Favorite Users
+// Future getFavUsers() async {
+// Response favRes = await ApiClient().getJsonForResponse(
+// "${ApiConsts.chatFavUser}getFavUserById/${AppState().chatDetails!.response!.id}",
+// token: AppState().chatDetails!.response!.token,
+// );
+// if (!kReleaseMode) {
+// logger.i("res: " + favRes.body);
+// }
+// return ChatUserModel.fromJson(json.decode(favRes.body));
+// }
+
+// //Get User Chat History
+// Future getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async {
+// try {
+// Response response = await ApiClient().getJsonForResponse(
+// "${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal",
+// token: AppState().chatDetails!.response!.token,
+// );
+// if (!kReleaseMode) {
+// logger.i("res: " + response.body);
+// }
+// return response;
+// } catch (e) {
+// getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal);
+// throw e;
+// }
+// }
+
+// //Favorite Users
+// Future favUser({required int userID, required int targetUserID}) async {
+// Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatFavUser}addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token);
+// if (!kReleaseMode) {
+// logger.i("res: " + response.body);
+// }
+// fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
+// return favoriteChatUser;
+// }
+
+// //UnFavorite Users
+// Future unFavUser({required int userID, required int targetUserID}) async {
+// try {
+// Response response = await ApiClient().postJsonForResponse(
+// "${ApiConsts.chatFavUser}deleteFavUser",
+// {"targetUserId": targetUserID, "userId": userID},
+// token: AppState().chatDetails!.response!.token,
+// );
+// if (!kReleaseMode) {
+// logger.i("res: " + response.body);
+// }
+// fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
+// return favoriteChatUser;
+// } catch (e) {
+// e as APIException;
+// throw e;
+// }
+// }
+
+// Upload Chat Media
+ Future