Merge remote-tracking branch 'origin/design_3.0_sdk_upgrade' into design_3.0_sdk_upgrade

design_3.0_latest
Sikander Saleem 1 year ago
commit dbea53734b

@ -0,0 +1,6 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.6252 7.91663C10.6252 7.57145 10.3454 7.29163 10.0002 7.29163C9.65503 7.29163 9.3752 7.57145 9.3752 7.91663V11.25C9.3752 11.4157 9.44105 11.5747 9.55826 11.6919L11.2249 13.3586C11.469 13.6026 11.8647 13.6026 12.1088 13.3586C12.3529 13.1145 12.3529 12.7188 12.1088 12.4747L10.6252 10.9911V7.91663Z" fill="#54C166"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6252 2.29163H11.6669C12.012 2.29163 12.2919 2.0118 12.2919 1.66663C12.2919 1.32145 12.012 1.04163 11.6669 1.04163H8.33354C7.98836 1.04163 7.70854 1.32145 7.70854 1.66663C7.70854 2.0118 7.98836 2.29163 8.33354 2.29163H9.3752V2.73197C5.17992 3.05111 1.8752 6.55627 1.8752 10.8333C1.8752 12.6389 2.46418 14.3069 3.4605 15.6558L2.05826 17.058C1.81418 17.3021 1.81418 17.6978 2.05826 17.9419C2.30234 18.186 2.69807 18.186 2.94215 17.9419L4.28029 16.6038C5.74858 18.0593 7.7694 18.9583 10.0002 18.9583C12.231 18.9583 14.2518 18.0593 15.7201 16.6038L17.0583 17.9419C17.3023 18.186 17.6981 18.186 17.9421 17.9419C18.1862 17.6978 18.1862 17.3021 17.9421 17.058L16.5399 15.6558C17.5362 14.3069 18.1252 12.6389 18.1252 10.8333C18.1252 6.55627 14.8205 3.05111 10.6252 2.73197V2.29163ZM3.1252 10.8333C3.1252 7.03633 6.20325 3.95829 10.0002 3.95829C13.7972 3.95829 16.8752 7.03633 16.8752 10.8333C16.8752 14.6303 13.7972 17.7083 10.0002 17.7083C6.20325 17.7083 3.1252 14.6303 3.1252 10.8333Z" fill="#54C166"/>
<path d="M2.75265 1.8914C3.19022 1.82103 3.59198 1.98844 3.95003 2.16747L4.44628 2.41559C4.75501 2.56996 4.88015 2.94538 4.72579 3.25412C4.57142 3.56285 4.196 3.68799 3.88726 3.53362L3.39101 3.2855C3.04468 3.11233 2.96194 3.1238 2.95111 3.12554C2.94076 3.12721 2.85798 3.14203 2.58346 3.41655C2.30894 3.69107 2.29412 3.77385 2.29246 3.7842C2.29071 3.79503 2.27924 3.87777 2.45241 4.2241L2.70054 4.72035C2.8549 5.02909 2.72976 5.40451 2.42103 5.55888C2.11229 5.71324 1.73687 5.5881 1.5825 5.27937L1.33438 4.78312C1.15535 4.42507 0.987945 4.02331 1.05831 3.58574C1.12876 3.14768 1.41409 2.81816 1.69958 2.53267C1.98507 2.24718 2.31459 1.96184 2.75265 1.8914Z" fill="#54C166"/>
<path d="M17.0491 3.12554C17.0383 3.1238 16.9555 3.11233 16.6092 3.2855L16.1129 3.53363C15.8042 3.68799 15.4288 3.56285 15.2744 3.25412C15.1201 2.94538 15.2452 2.56996 15.5539 2.41559L16.0502 2.16747C16.4082 1.98844 16.81 1.82103 17.2476 1.8914C17.6856 1.96184 18.0151 2.24718 18.3006 2.53267C18.5861 2.81816 18.8715 3.14768 18.9419 3.58574C19.0123 4.02331 18.8449 4.42507 18.6658 4.78312L18.4177 5.27937C18.2633 5.5881 17.8879 5.71324 17.5792 5.55888C17.2704 5.40451 17.1453 5.02909 17.2997 4.72035L17.5478 4.2241C17.721 3.87777 17.7095 3.79503 17.7078 3.7842C17.7061 3.77385 17.6913 3.69107 17.4167 3.41655C17.1422 3.14203 17.0594 3.12721 17.0491 3.12554Z" fill="#54C166"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -43,6 +43,7 @@ class URLs {
static get engineerDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerCount'; static get engineerDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerCount';
static get engineerDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails'; static get engineerDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails';
static get engineerDashboardNotAssignDetails=> '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails'; static get engineerDashboardNotAssignDetails=> '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails';
static get engineerDashboardUpcoming=> '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming';
static get engineerAcceptUrl=> '$_baseUrl/ServiceRequest/EngineerAccept'; static get engineerAcceptUrl=> '$_baseUrl/ServiceRequest/EngineerAccept';
static get engineerAssignHimSelfUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToHimself'; static get engineerAssignHimSelfUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToHimself';
static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject'; static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject';
@ -53,6 +54,7 @@ class URLs {
static get reOrderActivity=> '$_baseUrl/ServiceRequest/ReOrderActivity'; static get reOrderActivity=> '$_baseUrl/ServiceRequest/ReOrderActivity';
static get engineerConfirmArriveUrl=> '$_baseUrl/ServiceRequest/EngineerConfirmArrive'; static get engineerConfirmArriveUrl=> '$_baseUrl/ServiceRequest/EngineerConfirmArrive';
static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder'; static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder';
static get engineerSetReminderUrl=> '$_baseUrl/ServiceRequest/EngineerSetReminder';
static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById'; static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById';
static get getQrCodeUrl=> '$_baseUrl/ServiceRequest/GetQRCode'; static get getQrCodeUrl=> '$_baseUrl/ServiceRequest/GetQRCode';
static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart'; static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart';
@ -123,6 +125,7 @@ class URLs {
static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303"; static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303";
static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505"; static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505";
static get getServiceReportRetirementType => "$_baseUrl/Lookups/GetLookup?lookupEnum=415"; static get getServiceReportRetirementType => "$_baseUrl/Lookups/GetLookup?lookupEnum=415";
static get getVisitReminderTimeValue => "$_baseUrl/Lookups/GetLookup?lookupEnum=1211";
static get getServiceReportActivityStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1302"; static get getServiceReportActivityStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1302";
static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get
static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get

@ -1,4 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
@ -14,7 +15,15 @@ class DashBoardProvider extends ChangeNotifier {
bool isAllCountLoading = false; bool isAllCountLoading = false;
bool isLoading = false; bool isLoading = false;
bool _isDetailLoading = false; bool _isDetailLoading = false;
bool _isShowDashBoardCalendar = false; bool _isShowDashBoardCalendar = true;
DateTime _upcomingFilterSelectedDate = DateTime.now();
DateTime get upcomingFilterSelectedDate => _upcomingFilterSelectedDate;
set upcomingFilterSelectedDate(DateTime value) {
_upcomingFilterSelectedDate = value;
notifyListeners();
}
bool get isShowDashBoardCalendar => _isShowDashBoardCalendar; bool get isShowDashBoardCalendar => _isShowDashBoardCalendar;
@ -51,7 +60,7 @@ class DashBoardProvider extends ChangeNotifier {
List<CategoryTabs> tabs = []; List<CategoryTabs> tabs = [];
void setTabs({required UsersTypes userType, required BuildContext context}) { void setTabs({required UsersTypes userType, required BuildContext context}) {
tabs = CategoryTabs.getTabs(userType: userType, context: context); tabs = CategoryTabs.getTabs(userType: userType, context: context);
} }
@ -71,8 +80,9 @@ class DashBoardProvider extends ChangeNotifier {
_requestDetailList = null; _requestDetailList = null;
dashboardCount = null; dashboardCount = null;
} }
void refreshDashboard({required UsersTypes userType,required BuildContext context}) {
setTabs(userType:userType,context: context); void refreshDashboard({required UsersTypes userType, required BuildContext context}) {
setTabs(userType: userType, context: context);
getDashBoardCount(usersType: userType); getDashBoardCount(usersType: userType);
resetRequestDataList(); resetRequestDataList();
getRequestDetail(usersType: userType, status: tabs[currentListIndex].tag); getRequestDetail(usersType: userType, status: tabs[currentListIndex].tag);
@ -143,7 +153,11 @@ class DashBoardProvider extends ChangeNotifier {
} }
void getHighPriorityRequests({bool showLoader = true, required UsersTypes usersType}) { void getHighPriorityRequests({bool showLoader = true, required UsersTypes usersType}) {
getRequestDetail(showLoader: showLoader, usersType: usersType, isHighPriority: true); getRequestDetail(
showLoader: showLoader,
usersType: usersType,
isHighPriority: true,
);
} }
void getOverdueRequests({bool showLoader = true, required UsersTypes usersType}) { void getOverdueRequests({bool showLoader = true, required UsersTypes usersType}) {
@ -170,19 +184,21 @@ class DashBoardProvider extends ChangeNotifier {
getRequestDetail(showLoader: showLoader, usersType: usersType, status: 4); getRequestDetail(showLoader: showLoader, usersType: usersType, status: 4);
} }
Future<int> getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false}) async { Future<int> getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false, String? date}) async {
if (showLoader) { if (showLoader) {
isDetailLoading = showLoader; isDetailLoading = showLoader;
notifyListeners(); notifyListeners();
} }
Response response; Response response;
String url = ''; String url = '';
if (usersType == UsersTypes.engineer) { if (usersType == UsersTypes.engineer) {
if(status==0){ //these checks are to call different apis for dashboard for engineer...
if (status == 0) {
url = URLs.engineerDashboardUpcoming;
} else if (status == 1) {
url = URLs.engineerDashboardNotAssignDetails; url = URLs.engineerDashboardNotAssignDetails;
}else{ } else {
url = URLs.engineerDashboardDetailsUrl; url = URLs.engineerDashboardDetailsUrl;
} }
} else { } else {
@ -190,52 +206,17 @@ class DashBoardProvider extends ChangeNotifier {
} }
try { try {
Map<String, dynamic> body = {"pageNumber": pageNum, "pageSize": pageItemNumber}; Map<String, dynamic> body = {"pageNumber": pageNum, "pageSize": pageItemNumber};
if (status != null&&status!=0) body["statusValue"] = status;
if (status != null && status == 0) {
body["date"] = date ??upcomingFilterSelectedDate.toIso8601String();
} else {
body["statusValue"] = status;
}
if (isHighPriority) body["isHighPriority"] = true; if (isHighPriority) body["isHighPriority"] = true;
if (isOverdue) body["isOverdue"] = true; if (isOverdue) body["isOverdue"] = true;
response = await ApiManager.instance.post(url, body: body); response = await ApiManager.instance.post(url, body: body);
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
if (_requestDetailList == null) {
_requestDetailList = DD.DashboardDetail.fromJson(json.decode(response.body));
} else {
_requestDetailList!.data!.addAll(DD.DashboardDetail.fromJson(json.decode(response.body)).data ?? []);
}
if (_requestDetailList!.data!.length >= pageItemNumber) {
nextPage = true;
} else {
nextPage = false;
}
} else {
requestDetailList = null;
}
if (showLoader) {
isDetailLoading = false;
}
notifyListeners();
return response.statusCode;
} catch (error) {
if (showLoader) {
isDetailLoading = false;
}
stateCode = -1;
notifyListeners();
return -1;
}
}
Future<int> getEngineerDashboardNotAssignedDetail({bool showLoader = true,}) async {
if (showLoader) {
isDetailLoading = showLoader;
notifyListeners();
}
Response response;
try {
Map<String, dynamic> body = {"pageNumber": pageNum, "pageSize": pageItemNumber};
response = await ApiManager.instance.post(URLs.engineerDashboardNotAssignDetails, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
if (_requestDetailList == null) { if (_requestDetailList == null) {
_requestDetailList = DD.DashboardDetail.fromJson(json.decode(response.body)); _requestDetailList = DD.DashboardDetail.fromJson(json.decode(response.body));
@ -265,6 +246,48 @@ class DashBoardProvider extends ChangeNotifier {
} }
} }
// Future<int> getDashboardEngineerUpcoming({bool showLoader = true, required String date}) async {
// if (showLoader) {
// isDetailLoading = showLoader;
// notifyListeners();
// }
//
//
// Response response;
//
// try {
// Map<String, dynamic> body = {"pageNumber": pageNum, "pageSize": pageItemNumber};
// response = await ApiManager.instance.post(URLs.engineerDashboardNotAssignDetails, body: body);
// stateCode = response.statusCode;
// if (response.statusCode >= 200 && response.statusCode < 300) {
// if (_requestDetailList == null) {
// _requestDetailList = DD.DashboardDetail.fromJson(json.decode(response.body));
// } else {
// _requestDetailList!.data!.addAll(DD.DashboardDetail.fromJson(json.decode(response.body)).data ?? []);
// }
// if (_requestDetailList!.data!.length >= pageItemNumber) {
// nextPage = true;
// } else {
// nextPage = false;
// }
// } else {
// requestDetailList = null;
// }
// if (showLoader) {
// isDetailLoading = false;
// }
// notifyListeners();
// return response.statusCode;
// } catch (error) {
// if (showLoader) {
// isDetailLoading = false;
// }
// stateCode = -1;
// notifyListeners();
// return -1;
// }
// }
bool get isDetailLoading => _isDetailLoading; bool get isDetailLoading => _isDetailLoading;
set isDetailLoading(bool value) { set isDetailLoading(bool value) {

@ -70,7 +70,6 @@ class _DashboardViewState extends State<DashboardView> {
if (isFCM) { if (isFCM) {
FirebaseNotificationManger.initialized(context); FirebaseNotificationManger.initialized(context);
NotificationManger.initialisation((notificationDetails) { NotificationManger.initialisation((notificationDetails) {
print('i am called with notification details ${notificationDetails.toString()}');
FirebaseNotificationManger.handleMessage(context, json.decode(notificationDetails.payload!)); FirebaseNotificationManger.handleMessage(context, json.decode(notificationDetails.payload!));
}, (id, title, body, payload) async {}); }, (id, title, body, payload) async {});

@ -23,30 +23,31 @@ class RequestCategoryFragment extends StatelessWidget {
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user; bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user;
return Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ return Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
//TODO uncommit this to get the calendar card.. //TODO uncommit this to get the calendar card..
// !isNurse !isNurse && dashboardProvider.tabs.isNotEmpty && dashboardProvider.tabs[dashboardProvider.currentListIndex].tag == 0
// ? Column( ? Column(
// children: [ crossAxisAlignment: CrossAxisAlignment.start,
// Row( children: [
// mainAxisAlignment: MainAxisAlignment.spaceBetween, context.translation.allWorkOrder.heading4(context),
// children: [ // Row(
// context.translation.allWorkOrder.heading4(context), // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// GestureDetector( // children: [
// onTap: () { // context.translation.allWorkOrder.heading4(context),
// dashboardProvider.isShowDashBoardCalendar = !dashboardProvider.isShowDashBoardCalendar; // GestureDetector(
// }, // onTap: () {
// child: dashboardProvider.isShowDashBoardCalendar ? AppAsset.listIcon.toSvgAsset() : AppAsset.calendarIcon.toSvgAsset()) // dashboardProvider.isShowDashBoardCalendar = !dashboardProvider.isShowDashBoardCalendar;
// ], // },
// ), // child: dashboardProvider.isShowDashBoardCalendar ? AppAsset.listIcon.toSvgAsset() : AppAsset.calendarIcon.toSvgAsset())
// dashboardProvider.isShowDashBoardCalendar // ],
// ? Padding( // ),
// padding: EdgeInsets.only(top: 12.toScreenHeight), dashboardProvider.isShowDashBoardCalendar
// child: const WeeklyCalendarFragment(), ? Padding(
// ) padding: EdgeInsets.only(top: 12.toScreenHeight),
// : const SizedBox(), child: const WeeklyCalendarFragment(),
// ], )
// ).paddingOnly(start: 16, end: 16) : const SizedBox(),
// : ],
context.translation.allWorkOrder.heading4(context).paddingOnly(start: 16, end: 16), ).paddingOnly(start: 14, end: 12)
: context.translation.allWorkOrder.heading4(context).paddingOnly(start: 16, end: 16),
getTabs( getTabs(
requestsProvider: dashboardProvider, requestsProvider: dashboardProvider,
context: context, context: context,

@ -2,6 +2,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
@ -35,7 +36,7 @@ class RequestsFragment extends StatelessWidget {
context.isDark ? AppColor.redStatus(context) : AppColor.red30, context.isDark ? AppColor.redStatus(context) : AppColor.red30,
), ),
listItem(snapshot.dashboardCount?.data?.countOverdue ?? 0, "overdue", context.translation.overdue, context, snapshot.isAllCountLoading, 1, AppColor.yellowIcon(context)), listItem(snapshot.dashboardCount?.data?.countOverdue ?? 0, "overdue", context.translation.overdue, context, snapshot.isAllCountLoading, 1, AppColor.yellowIcon(context)),
listItem(snapshot.dashboardCount?.data?.countOpen ?? 0, "new_request", ApiManager.instance.user?.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR, listItem(snapshot.dashboardCount?.data?.countInprogress ?? 0, "new_request", ApiManager.instance.user?.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR,
context, snapshot.isAllCountLoading, 2, AppColor.primary10), context, snapshot.isAllCountLoading, 2, AppColor.primary10),
listItem(snapshot.dashboardCount?.data?.countComplete ?? 0, "complete_request", context.translation.completed, context, snapshot.isAllCountLoading, 3, AppColor.greenStatus(context)), listItem(snapshot.dashboardCount?.data?.countComplete ?? 0, "complete_request", context.translation.completed, context, snapshot.isAllCountLoading, 3, AppColor.greenStatus(context)),
], ],
@ -47,8 +48,9 @@ class RequestsFragment extends StatelessWidget {
return GestureDetector( return GestureDetector(
onTap: isLoading onTap: isLoading
? null ? null
: () { : () async {
Navigator.push(context, MaterialPageRoute(builder: (context) => RequestsListPage(index, title))); await Navigator.push(context, MaterialPageRoute(builder: (context) => RequestsListPage(index, title)));
Provider.of<DashBoardProvider>(context, listen: false).refreshDashboard(userType: Provider.of<SettingProvider>(context, listen: false).user!.type!, context: context);
}, },
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,

@ -33,6 +33,10 @@ extension EnumExtensionsWorkOrder on WorkOrderNextStepEnum {
case WorkOrderNextStepEnum.waitingForRequesterToConfirm: case WorkOrderNextStepEnum.waitingForRequesterToConfirm:
//replace with correct value... //replace with correct value...
return 31; return 31;
case WorkOrderNextStepEnum.eFixRemotely:
return 35;
case WorkOrderNextStepEnum.eNeedVisit:
return 36;
} }
} }
} }
@ -62,6 +66,10 @@ extension IntExtensionsWorkOrder on int {
return WorkOrderNextStepEnum.assetRetirementManagementApproval; return WorkOrderNextStepEnum.assetRetirementManagementApproval;
case 31: case 31:
return WorkOrderNextStepEnum.waitingForRequesterToConfirm; return WorkOrderNextStepEnum.waitingForRequesterToConfirm;
case 35:
return WorkOrderNextStepEnum.eFixRemotely;
case 36:
return WorkOrderNextStepEnum.eNeedVisit;
default: default:
return WorkOrderNextStepEnum.onlyView; return WorkOrderNextStepEnum.onlyView;
} }

@ -16,6 +16,8 @@
"exit": "إغلاق", "exit": "إغلاق",
"requestDetails": "تفاصيل الطلب", "requestDetails": "تفاصيل الطلب",
"retirementType": "نوع التقاعد", "retirementType": "نوع التقاعد",
"endDateTimeMustBeGreaterThanStartDate": "يجب أن يكون تاريخ ووقت الانتهاء أكبر من تاريخ البدء",
"signaturesAreRequired": "التوقيعات مطلوبة",
"assetRetiredPendingOpManagementApproval": "تم تقاعد الأصل. في انتظار موافقة إدارة العمليات", "assetRetiredPendingOpManagementApproval": "تم تقاعد الأصل. في انتظار موافقة إدارة العمليات",
"youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm": "لقد قمت بوضع علامة على هذه المشكلة على أنها تم إصلاحها. في انتظار تأكيد مقدم الطلب", "youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm": "لقد قمت بوضع علامة على هذه المشكلة على أنها تم إصلاحها. في انتظار تأكيد مقدم الطلب",
"assetRetirementRequestSubmittedSuccessfully": "تم تقديم طلب تقاعد الأصل بنجاح", "assetRetirementRequestSubmittedSuccessfully": "تم تقديم طلب تقاعد الأصل بنجاح",

@ -61,6 +61,8 @@
"edit": "Edit", "edit": "Edit",
"emailNotFound": "Email not found", "emailNotFound": "Email not found",
"from": "From", "from": "From",
"endDateTimeMustBeGreaterThanStartDate": "End Date time must be greater than start date",
"signaturesAreRequired": "Signatures are required",
"to": "To", "to": "To",
"linkNotFound": "Link not found", "linkNotFound": "Link not found",
"nameNotFound": "Name not found", "nameNotFound": "Name not found",

@ -54,6 +54,7 @@ import 'package:test_sa/providers/service_request_providers/requested_through_pr
import 'package:test_sa/providers/service_request_providers/type_of_request_provider.dart'; import 'package:test_sa/providers/service_request_providers/type_of_request_provider.dart';
import 'package:test_sa/providers/work_order/activity_status_provider.dart'; import 'package:test_sa/providers/work_order/activity_status_provider.dart';
import 'package:test_sa/providers/work_order/fault_description_provider.dart'; import 'package:test_sa/providers/work_order/fault_description_provider.dart';
import 'package:test_sa/providers/work_order/need_visit_reminder_time_provider.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart'; import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/providers/work_order/retirement_type_provider.dart'; import 'package:test_sa/providers/work_order/retirement_type_provider.dart';
import 'package:test_sa/providers/work_order/service_type_provider.dart'; import 'package:test_sa/providers/work_order/service_type_provider.dart';
@ -79,6 +80,7 @@ import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_pa
import 'package:test_sa/views/widgets/departments/single_department_picker.dart'; import 'package:test_sa/views/widgets/departments/single_department_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_detail_page.dart'; import 'package:test_sa/views/widgets/equipment/asset_detail_page.dart';
import 'package:test_sa/views/widgets/equipment/single_device_picker.dart'; import 'package:test_sa/views/widgets/equipment/single_device_picker.dart';
import 'controllers/notification/notification_manger.dart';
import 'controllers/providers/api/gas_refill_comments.dart'; import 'controllers/providers/api/gas_refill_comments.dart';
import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/api/user_provider.dart';
import 'controllers/providers/settings/setting_provider.dart'; import 'controllers/providers/settings/setting_provider.dart';
@ -93,9 +95,9 @@ import 'package:timezone/timezone.dart' as tz;
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
// _configureLocalTimeZone(); _configureLocalTimeZone();
// NotificationManger.initialisation((notificationDetails) { NotificationManger.initialisation((notificationDetails) {
// }, (id, title, body, payload) async {}); }, (id, title, body, payload) async {});
if (Platform.isIOS) { if (Platform.isIOS) {
await Firebase.initializeApp( await Firebase.initializeApp(
@ -232,6 +234,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => FaultDescriptionProvider()), ChangeNotifierProvider(create: (_) => FaultDescriptionProvider()),
ChangeNotifierProvider(create: (_) => RetirementTypeProvider()), ChangeNotifierProvider(create: (_) => RetirementTypeProvider()),
ChangeNotifierProvider(create: (_) => ActivityStatusProvider()), ChangeNotifierProvider(create: (_) => ActivityStatusProvider()),
ChangeNotifierProvider(create: (_) => NeedVisitReminderTimeProvider()),
///todo deleted ///todo deleted
//ChangeNotifierProvider(create: (_) => AssetTypesProvider()), //ChangeNotifierProvider(create: (_) => AssetTypesProvider()),

@ -4,6 +4,8 @@ enum WorkOrderNextStepEnum {
nTakeAction, // 5 nTakeAction, // 5
eRejectAccept, // 9 eRejectAccept, // 9
eFixRemotelyNeedVisit, // 12 eFixRemotelyNeedVisit, // 12
eFixRemotely, // 35
eNeedVisit, // 36
eArrived, // 15 eArrived, // 15
verifyAssetDetail, // 16 verifyAssetDetail, // 16
activity, // 17 activity, // 17

@ -4,6 +4,7 @@ import 'package:test_sa/models/new_models/assistant_employee.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart'; import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/models/timer_model.dart';
class ActivityMaintenanceHelperModel { class ActivityMaintenanceHelperModel {
int? id; int? id;
@ -32,6 +33,8 @@ class ActivityMaintenanceHelperModel {
SuppEngineerWorkOrders? supEngineer; SuppEngineerWorkOrders? supEngineer;
ActivityMaintenanceAssistantEmployees? modelAssistantEmployees; ActivityMaintenanceAssistantEmployees? modelAssistantEmployees;
List<AssistantEmployees>? assistantEmployees; List<AssistantEmployees>? assistantEmployees;
List<ActivityMaintenanceTimers>? activityMaintenanceTimers=[];
TimerModel? activityMaintenanceTimerModel = TimerModel();
ActivityMaintenanceHelperModel( ActivityMaintenanceHelperModel(
{this.id, {this.id,
@ -43,6 +46,7 @@ class ActivityMaintenanceHelperModel {
this.supplier, this.supplier,
this.endTime, this.endTime,
this.workingHour, this.workingHour,
this.activityMaintenanceTimerModel,
this.travelHours, this.travelHours,
this.repairLocation, this.repairLocation,
this.assignedEmployeeId, this.assignedEmployeeId,
@ -55,6 +59,7 @@ class ActivityMaintenanceHelperModel {
this.assistantEmployees, this.assistantEmployees,
this.supEngineer, this.supEngineer,
this.assignedEmployee, this.assignedEmployee,
this.activityMaintenanceTimers,
this.modelAssistantEmployees}); this.modelAssistantEmployees});
@ -76,10 +81,8 @@ class ActivityMaintenanceHelperModel {
data['supplierStartTime'] = supplierStartTime?.toIso8601String(); data['supplierStartTime'] = supplierStartTime?.toIso8601String();
data['supplierEndTime'] = supplierEndTime?.toIso8601String(); data['supplierEndTime'] = supplierEndTime?.toIso8601String();
data['supplierWorkingHour'] = supplierWorkingHour; data['supplierWorkingHour'] = supplierWorkingHour;
// //TODO remove this when backend fix this on their side.. //TODO fix this properly...
// if(activityStatus!=null){ data['activityMaintenanceTimers'] = activityMaintenanceTimers;
// data['lastSituationId'] = activityStatus?.id;
// }
if (assistantEmployees != null&&assistantEmployees!.isNotEmpty) { if (assistantEmployees != null&&assistantEmployees!.isNotEmpty) {
data['assistantEmployees'] = [modelAssistantEmployees?.toJson()]; data['assistantEmployees'] = [modelAssistantEmployees?.toJson()];
} }

@ -10,13 +10,15 @@ class DashboardDetail {
DashboardDetail({this.data, this.totalRows, this.message, this.title, this.innerMessage, this.responseCode, this.isSuccess}); DashboardDetail({this.data, this.totalRows, this.message, this.title, this.innerMessage, this.responseCode, this.isSuccess});
DashboardDetail.fromJson(Map<String, dynamic> json) { DashboardDetail.fromJson(Map<String, dynamic> json) {
totalRows = json['totalRows'];
print('total rows is $totalRows');
if (json['data'] != null) { if (json['data'] != null) {
data = <Data>[]; data = <Data>[];
json['data'].forEach((v) { json['data'].forEach((v) {
data!.add(Data.fromJson(v)); data!.add(Data.fromJson(v));
}); });
} }
totalRows = json['totalRows'];
message = json['message']; message = json['message'];
title = json['title']; title = json['title'];
innerMessage = json['innerMessage']; innerMessage = json['innerMessage'];

@ -61,6 +61,7 @@ class WorkOrderData {
required this.assignedEmployee, required this.assignedEmployee,
required this.lastActivityStatus, required this.lastActivityStatus,
required this.status, required this.status,
required this.setReminder,
required this.nextStep, required this.nextStep,
required this.assetVerificationType, required this.assetVerificationType,
required this.workOrderContactPerson, required this.workOrderContactPerson,
@ -106,6 +107,7 @@ class WorkOrderData {
WorkOrderAssignedEmployee? assignedEmployee; WorkOrderAssignedEmployee? assignedEmployee;
Lookup? lastActivityStatus; Lookup? lastActivityStatus;
Lookup? status; Lookup? status;
Lookup? setReminder;
Lookup? nextStep; Lookup? nextStep;
int? assetVerificationType; int? assetVerificationType;
List<WorkOrderContactPerson> workOrderContactPerson; List<WorkOrderContactPerson> workOrderContactPerson;
@ -150,8 +152,9 @@ class WorkOrderData {
room: json["room"], room: json["room"],
assetType: json["assetType"] == null ? null : Lookup.fromJson(json["assetType"]), assetType: json["assetType"] == null ? null : Lookup.fromJson(json["assetType"]),
assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]), assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]),
lastActivityStatus: json["lastActivityStatus"]!=null?Lookup.fromJson(json["lastActivityStatus"]):null, lastActivityStatus: json["lastActivityStatus"] != null ? Lookup.fromJson(json["lastActivityStatus"]) : null,
status: json["status"] == null ? null : Lookup.fromJson(json["status"]), status: json["status"] == null ? null : Lookup.fromJson(json["status"]),
setReminder: json["setReminder"] == null ? null : Lookup.fromJson(json["setReminder"]),
nextStep: json["nextStep"] == null ? null : Lookup.fromJson(json["nextStep"]), nextStep: json["nextStep"] == null ? null : Lookup.fromJson(json["nextStep"]),
assetVerificationType: json["assetVerificationType"], assetVerificationType: json["assetVerificationType"],
workOrderContactPerson: json["workOrderContactPerson"] == null ? [] : List<WorkOrderContactPerson>.from(json["workOrderContactPerson"]!.map((x) => WorkOrderContactPerson.fromJson(x))), workOrderContactPerson: json["workOrderContactPerson"] == null ? [] : List<WorkOrderContactPerson>.from(json["workOrderContactPerson"]!.map((x) => WorkOrderContactPerson.fromJson(x))),
@ -174,7 +177,7 @@ class WorkOrderData {
totalWorkingHours: json["totalWorkingHours"], totalWorkingHours: json["totalWorkingHours"],
workOrderHistory: json["workOrderHistory"] == null ? [] : List<WorkOrderHistory>.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))), workOrderHistory: json["workOrderHistory"] == null ? [] : List<WorkOrderHistory>.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))),
activities: json["activities"] == null ? [] : List<Activities>.from(json["activities"]!.map((x) => Activities.fromJson(x))), activities: json["activities"] == null ? [] : List<Activities>.from(json["activities"]!.map((x) => Activities.fromJson(x))),
needAVisitDateTime: DateTime.tryParse(json["requestedDate"] ?? ""), needAVisitDateTime: DateTime.tryParse(json["needAVisitDateTime"] ?? ""),
needAVisitComment: json["needAVisitComment"], needAVisitComment: json["needAVisitComment"],
activityAssetToBeRetireds: json["activityAssetToBeRetireds"] == null ? [] : List<dynamic>.from(json["activityAssetToBeRetireds"]!.map((x) => x)), activityAssetToBeRetireds: json["activityAssetToBeRetireds"] == null ? [] : List<dynamic>.from(json["activityAssetToBeRetireds"]!.map((x) => x)),
); );
@ -200,6 +203,7 @@ class WorkOrderData {
"assignedEmployee": assignedEmployee?.toJson(), "assignedEmployee": assignedEmployee?.toJson(),
"lastActivityStatus": lastActivityStatus, "lastActivityStatus": lastActivityStatus,
"status": status?.toJson(), "status": status?.toJson(),
"setReminder": setReminder?.toJson(),
"nextStep": nextStep?.toJson(), "nextStep": nextStep?.toJson(),
"assetVerificationType": assetVerificationType, "assetVerificationType": assetVerificationType,
"workOrderContactPerson": workOrderContactPerson.map((x) => x?.toJson()).toList(), "workOrderContactPerson": workOrderContactPerson.map((x) => x?.toJson()).toList(),
@ -298,6 +302,7 @@ class WorkOrderAssignedEmployee {
"languageId": languageId, "languageId": languageId,
}; };
} }
class AssetLoan { class AssetLoan {
AssetLoan({ AssetLoan({
required this.id, required this.id,
@ -336,8 +341,6 @@ class AssetLoan {
}; };
} }
class Activities { class Activities {
int? id; int? id;
int? orderNo; int? orderNo;
@ -535,8 +538,8 @@ class WorkOrderHistory {
WorkOrderHistory({ WorkOrderHistory({
required this.id, required this.id,
required this.workorderStatus, required this.workorderStatus,
this.assetVerificationType, this.assetVerificationType,
this.photoVerfication, this.photoVerfication,
required this.activityStatus, required this.activityStatus,
required this.date, required this.date,
required this.timeDifference, required this.timeDifference,
@ -554,7 +557,7 @@ class WorkOrderHistory {
Lookup? assetVerificationType; Lookup? assetVerificationType;
dynamic activityStatus; dynamic activityStatus;
DateTime? date; DateTime? date;
String timeDifference =''; String timeDifference = '';
String? photoVerfication; String? photoVerfication;
WorkOrderAssignedEmployee? user; WorkOrderAssignedEmployee? user;
Lookup? step; Lookup? step;
@ -617,6 +620,7 @@ class ActivityMaintenance {
String? supplierEndTime; String? supplierEndTime;
double? supplierWorkingHours; double? supplierWorkingHours;
List<ActivityMaintenanceAssistantEmployees>? assistantEmployees; List<ActivityMaintenanceAssistantEmployees>? assistantEmployees;
List<ActivityMaintenanceTimers>? activityMaintenanceTimers;
ActivityMaintenance( ActivityMaintenance(
{this.id, {this.id,
@ -628,6 +632,7 @@ class ActivityMaintenance {
this.travelHours, this.travelHours,
this.repairLocation, this.repairLocation,
this.assignedEmployee, this.assignedEmployee,
this.activityMaintenanceTimers,
this.technicalComment, this.technicalComment,
this.supplier, this.supplier,
this.supplierEngineer, this.supplierEngineer,
@ -647,7 +652,6 @@ class ActivityMaintenance {
repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null; repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null;
assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null;
technicalComment = json['technicalComment']; technicalComment = json['technicalComment'];
//json["supplier"] == null ? null : Lookup.fromJson(json["supplier"]), //json["supplier"] == null ? null : Lookup.fromJson(json["supplier"]),
supplier = json["supplier"] == null ? null : Lookup.fromJson(json["supplier"]); supplier = json["supplier"] == null ? null : Lookup.fromJson(json["supplier"]);
supplierEngineer = json["supplierEngineer"] == null ? null : Lookup.fromJson(json["supplierEngineer"]); supplierEngineer = json["supplierEngineer"] == null ? null : Lookup.fromJson(json["supplierEngineer"]);
@ -661,6 +665,12 @@ class ActivityMaintenance {
assistantEmployees!.add(ActivityMaintenanceAssistantEmployees.fromJson(v)); assistantEmployees!.add(ActivityMaintenanceAssistantEmployees.fromJson(v));
}); });
} }
if (json['activityMaintenanceTimers'] != null) {
activityMaintenanceTimers = <ActivityMaintenanceTimers>[];
json['activityMaintenanceTimers'].forEach((v) {
activityMaintenanceTimers!.add(ActivityMaintenanceTimers.fromJson(v));
});
}
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -766,3 +776,28 @@ class ActivityMaintenanceAssistantEmployees {
return data; return data;
} }
} }
class ActivityMaintenanceTimers {
int? id;
String? startTime;
String? endTime;
dynamic workingHours;
ActivityMaintenanceTimers({this.id, this.startTime, this.endTime, this.workingHours});
ActivityMaintenanceTimers.fromJson(Map<String, dynamic> json) {
id = json['id'];
startTime = json['startTime'];
endTime = json['endTime'];
workingHours = json['workingHours'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['startTime'] = startTime;
data['endTime'] = endTime;
data['workingHours'] = workingHours;
return data;
}
}

@ -40,7 +40,10 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
]; ];
_provider = Provider.of<AllRequestsProvider>(context, listen: false); _provider = Provider.of<AllRequestsProvider>(context, listen: false);
_provider!.reset(); _provider!.reset();
_provider!.getAllRequests(context); WidgetsBinding.instance.addPostFrameCallback((_) {
_provider!.getAllRequests(context);
});
} }
return Scaffold( return Scaffold(

@ -20,7 +20,6 @@ class PpmItemView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print(' type is ${requestData?.nameOfType}');
if (requestData != null) { if (requestData != null) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -48,7 +47,7 @@ print(' type is ${requestData?.nameOfType}');
], ],
), ),
8.height, 8.height,
(requestData?.nameOfType ?? context.translation.ppmRequest).heading5(context), (requestData?.typeTransaction ?? context.translation.ppmRequest).heading5(context),
8.height, 8.height,
'${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context), '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context),
// '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed // '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed

@ -17,6 +17,7 @@ class RequestPaginatedListview extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print('count i got is ${totalCount}');
return ListView.builder( return ListView.builder(
itemCount: list.length < totalCount ? list.length + 1 : list.length, itemCount: list.length < totalCount ? list.length + 1 : list.length,
controller: scrollController, controller: scrollController,

@ -51,7 +51,7 @@ class ServiceRequestItemView extends StatelessWidget {
], ],
), ),
8.height, 8.height,
(requestData!.typeTransaction ?? context.translation.correctiveMaintenance).heading5(context), (requestData?.typeTransaction ?? context.translation.correctiveMaintenance).heading5(context),
'${context.translation.assetName}: ${requestData!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.assetName}: ${requestData!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context),
// '${context.translation.assetNumber}: ${request.assetNo}'.bodyText(context), // '${context.translation.assetNumber}: ${request.assetNo}'.bodyText(context),
// '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context), // '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context),

@ -1,3 +1,6 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart';
@ -31,8 +34,10 @@ class _RequestsListPageState extends State<RequestsListPage> {
void initState() { void initState() {
super.initState(); super.initState();
_dashBoardProvider = Provider.of<DashBoardProvider>(context, listen: false); _dashBoardProvider = Provider.of<DashBoardProvider>(context, listen: false);
_dashBoardProvider.resetRequestDataList(); scheduleMicrotask(() async {
callRequestApis(); _dashBoardProvider.resetRequestDataList();
callRequestApis();
});
handleScroll(); handleScroll();
} }
@ -46,8 +51,14 @@ class _RequestsListPageState extends State<RequestsListPage> {
_scrollController = ScrollController(); _scrollController = ScrollController();
int pageNo = 1; int pageNo = 1;
_scrollController.addListener(() async { _scrollController.addListener(() async {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_dashBoardProvider.isDetailLoading) { log('loading value i got is ${_dashBoardProvider.isDetailLoading}');
log('total rows i got is ${_dashBoardProvider.requestDetailList!.totalRows}');
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent &&
!_dashBoardProvider.isDetailLoading &&
(_dashBoardProvider.requestDetailList!.data!.length < _dashBoardProvider.requestDetailList!.totalRows!.toInt())) {
log('I am here in scroll ');
pageNo = pageNo + 1; pageNo = pageNo + 1;
_dashBoardProvider.pageNum = pageNo;
callRequestApis(showLoader: false, pageNo: pageNo); callRequestApis(showLoader: false, pageNo: pageNo);
} }
}); });
@ -95,10 +106,11 @@ class _RequestsListPageState extends State<RequestsListPage> {
})); }));
} }
Future<void> callRequestApis({bool showLoader = true, int pageNo = 1, int pageSize = 12}) async { Future<void> callRequestApis({bool showLoader = true, int pageNo = 1, int pageSize = 10}) async {
UsersTypes usersTypes = Provider.of<UserProvider>(context, listen: false).user!.type!; UsersTypes usersTypes = Provider.of<UserProvider>(context, listen: false).user!.type!;
if (widget.index == 0) { if (widget.index == 0) {
// high priority // high priority
_dashBoardProvider.getHighPriorityRequests(usersType: usersTypes, showLoader: showLoader); _dashBoardProvider.getHighPriorityRequests(usersType: usersTypes, showLoader: showLoader);
} else if (widget.index == 1) { } else if (widget.index == 1) {
// overdue // overdue

@ -26,8 +26,6 @@ class FaultDescriptionProvider extends ChangeNotifier {
try { try {
response = await ApiManager.instance.get(URLs.getFaultDescription+"?assetId=$assetId",); response = await ApiManager.instance.get(URLs.getFaultDescription+"?assetId=$assetId",);
print('url is ${URLs.getFaultDescription+"?assetId=$assetId"}');
print('response of get fault is ${response.body}');
List<FaultDescription> list = []; List<FaultDescription> list = [];
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received

@ -0,0 +1,35 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import '../../controllers/api_routes/api_manager.dart';
import '../../controllers/api_routes/urls.dart';
import '../../models/lookup.dart';
class NeedVisitReminderTimeProvider extends LoadingListNotifier<Lookup> {
@override
Future getDate() async {
if (loading == true) return -2;
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.get(URLs.getVisitReminderTimeValue);
print('response i got is ${response.body}');
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
List categoriesListJson = json.decode(response.body)["data"];
items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
}

@ -123,6 +123,7 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
void updateNeedVisitHelperModel(NeedVisitHelperModel? value) { void updateNeedVisitHelperModel(NeedVisitHelperModel? value) {
needVisitHelperModel = value; needVisitHelperModel = value;
log ("value:${value!.visitDate.toString()}");
notifyListeners(); notifyListeners();
} }
@ -380,6 +381,7 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
notifyListeners();
} }
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
@ -469,6 +471,33 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
} }
} }
//engineer Confirm Arrive......
Future<int> engineerSetReminder({required int workOrderId, required int reminderId}) async {
Response response;
try {
//"workOrderCreatedById": "string"
Map<String, dynamic> body = {
"workOrderId": workOrderId,
"setReminderId": reminderId,
};
isLoading = true;
notifyListeners();
response = await ApiManager.instance.post(URLs.engineerSetReminderUrl, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
}
if (response.statusCode >= 200 && response.statusCode < 300) {}
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return -1;
}
}
//assignEngineerToWorkOrder...... //assignEngineerToWorkOrder......
Future<CommonResponseModel> assignEngineerWorkOrder({required String workOrderId, required String engineerId}) async { Future<CommonResponseModel> assignEngineerWorkOrder({required String workOrderId, required String engineerId}) async {
try { try {
@ -739,7 +768,6 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
body: activityMaintenanceHelperModel!.toJson(), body: activityMaintenanceHelperModel!.toJson(),
); );
stateCode = response.statusCode; stateCode = response.statusCode;
print('response of activity maintenace part is ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); // currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
// updateCurrentWorkOrder(currentWorkOrder); // updateCurrentWorkOrder(currentWorkOrder);

@ -16,6 +16,7 @@ import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:huawei_push/huawei_push.dart' as h_push; import 'package:huawei_push/huawei_push.dart' as h_push;
class ServiceRequestUtils { class ServiceRequestUtils {
static double calculateAndAssignWorkingHours({ static double calculateAndAssignWorkingHours({
required DateTime? startTime, required DateTime? startTime,
@ -33,6 +34,7 @@ class ServiceRequestUtils {
return -1; // Indicating invalid input return -1; // Indicating invalid input
} }
} }
static String calculateTimeDifference(DateTime startDate, DateTime endDate) { static String calculateTimeDifference(DateTime startDate, DateTime endDate) {
try { try {
Duration diff = startDate.difference(endDate); Duration diff = startDate.difference(endDate);
@ -52,9 +54,31 @@ class ServiceRequestUtils {
} }
} }
static void getQrCode({required BuildContext context }) async{ static String formatTimerDuration(int seconds) {
int hours = seconds ~/ 3600;
int minutes = (seconds % 3600) ~/ 60;
int remainingSeconds = seconds % 60;
String formattedDuration = '';
if (hours > 0) {
formattedDuration += '$hours hour${hours > 1 ? 's' : ''} ';
}
if (minutes > 0) {
formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} ';
}
if (remainingSeconds > 0) {
formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} ';
}
if (formattedDuration.isEmpty) {
formattedDuration = 'Less than a second';
}
return formattedDuration.trim();
}
static void getQrCode({required BuildContext context}) async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context,listen:false); ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
String? base64String = await requestDetailProvider.getQrCode(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId ?? 0); String? base64String = await requestDetailProvider.getQrCode(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId ?? 0);
Navigator.pop(context); Navigator.pop(context);
if (base64String != null) { if (base64String != null) {
@ -66,7 +90,7 @@ class ServiceRequestUtils {
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
backgroundColor: Colors.white, backgroundColor: Colors.white,
title:context.translation.scanQr.heading6(context).center, title: context.translation.scanQr.heading6(context).center,
content: Image.memory( content: Image.memory(
bytes, // Displaying the QR code from base64 bytes, // Displaying the QR code from base64
fit: BoxFit.contain, // Ensure the image fits well in the dialog fit: BoxFit.contain, // Ensure the image fits well in the dialog
@ -74,61 +98,41 @@ class ServiceRequestUtils {
return const Icon(Icons.error, color: Colors.red); return const Icon(Icons.error, color: Colors.red);
}, },
), ),
); );
}, },
); );
} else { } else {
print('Failed to get the QR code'); print('Failed to get the QR code');
} }
} }
static void scheduleNotification({required BuildContext context, required DateTime scheduleDateTime}) {
DateTime scheduleTime = scheduleDateTime;
static Widget testScheduleNotificationButton({required BuildContext context}){ NotificationManger.scheduleNotification(title: 'Scheduled Notification', body: '$scheduleTime', scheduledNotificationDateTime: scheduleTime);
return ElevatedButton(
child: const Text('Schedule notifications'),
onPressed: () {
// debugPrint('Notification Scheduled for $D');
// NotificationManger.showNotification(context: context, title: 'test notification', subtext: 'test notification', hashcode: 1);
DateTime scheduleTime= DateTime.now().add(const Duration(seconds: 10));
NotificationManger.scheduleNotification(
title: 'Scheduled Notification',
body: '$scheduleTime',
scheduledNotificationDateTime: scheduleTime);();
},
);
} }
//steps: //steps:
//add permission for andriod.. //add permission for andriod..
//add string in info.plist for ios... //add string in info.plist for ios...
//create event.. //create event..
static Widget testAddEventToCalendarButton({required BuildContext context}){ static void addEventToCalendar({required BuildContext context, required DateTime start, required DateTime end,required String title}) async {
return ElevatedButton( var currentLocation = getLocation(await FlutterTimezone.getLocalTimezone());
child: const Text('Add Event to Calendar'), setLocalLocation(currentLocation);
onPressed: () async { await Future.delayed(const Duration(seconds: 2));
var currentLocation = getLocation( await FlutterTimezone.getLocalTimezone()); TZDateTime startDate = TZDateTime.from(start, currentLocation);
setLocalLocation(currentLocation); TZDateTime endDate = TZDateTime.from(end, currentLocation);
await Future.delayed(const Duration(seconds: 2)); var eventToCreate = Event(
var eventToCreate = Event( "1",
"1", title: title,
title: "test123", description: "You have reminder for Visit",
description: "test", start: startDate,
start: TZDateTime.now(currentLocation), end: endDate,
end: TZDateTime.now(currentLocation).add(const Duration(seconds: 10)),
);
final createEventResult =
await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate);
if (createEventResult!.isSuccess) {
Fluttertoast.showToast(msg: 'added successfully');
}
},
); );
print('title i got is ${eventToCreate.title}');
await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate);
} }
// Map<String, dynamic> messageData = message.data; // Map<String, dynamic> messageData = message.data;
// if (messageData["notificationType"] != null && messageData["accept"] != null) { // if (messageData["notificationType"] != null && messageData["accept"] != null) {
// if (messageData["notificationType"] == "arrivalConfirmation") { // if (messageData["notificationType"] == "arrivalConfirmation") {
@ -141,7 +145,6 @@ class ServiceRequestUtils {
// } // }
// } // }
static Future<bool?> listenForApproval() async { static Future<bool?> listenForApproval() async {
print('listen for approval called..'); print('listen for approval called..');
bool isVerified = false; bool isVerified = false;
@ -198,6 +201,7 @@ class ServiceRequestUtils {
return false; return false;
} }
} }
class ConfirmArrivalNotificationModel { class ConfirmArrivalNotificationModel {
final String? transactionType; final String? transactionType;
final String? requestId; final String? requestId;
@ -234,4 +238,4 @@ class ConfirmArrivalNotificationModel {
'accept': accept, 'accept': accept,
}; };
} }
} }

@ -201,6 +201,29 @@ class FooterActionButton {
textColor: AppColor.neutral150, textColor: AppColor.neutral150,
fontSize: 12.toScreenWidth, fontSize: 12.toScreenWidth,
)); ));
case WorkOrderNextStepEnum.eFixRemotely:
return footerContainer(
child: AppFilledButton(
label: context.translation.fixedRemotely,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
requestDetailProvider.fixRemotelyHelperModel = FixRemotelyHelperModel();
ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context);
},
),
);
case WorkOrderNextStepEnum.eNeedVisit:
return footerContainer(
child: AppFilledButton(
label: context.translation.needAVisit,
maxWidth: true,
buttonColor: AppColor.neutral50,
onPressed: () async {
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel();
ServiceRequestBottomSheet.initialVisitBottomSheet(context: context);
},
));
} }
} else { } else {
if (workOrderNextStepStatus == WorkOrderNextStepEnum.nTakeAction) { if (workOrderNextStepStatus == WorkOrderNextStepEnum.nTakeAction) {

@ -20,6 +20,7 @@ import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart'; import 'package:test_sa/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart';
@ -248,7 +249,9 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
} }
Widget maintenanceActivityCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider, required BuildContext context, required Activities activity}) { Widget maintenanceActivityCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider, required BuildContext context, required Activities activity}) {
print('activity i got is ${activity.toJson()}'); double totalWorkingHours =
activity.activityMaintenance?.activityMaintenanceTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0;
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -296,16 +299,16 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
), ),
3.height, 3.height,
Text( Text(
'${context.translation.workingHours}: ${activity.activityMaintenance?.workingHours??'-'}', '${context.translation.workingHours}: ${totalWorkingHours > 0.0 ? ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()) : '-'}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
), ),
2.height, 2.height,
if(activity.activityMaintenance?.assignedEmployee!=null&&activity.activityMaintenance!.assistantEmployees!.isNotEmpty)...[ if (activity.activityMaintenance?.assignedEmployee != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[
Text( Text(
'${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}', '${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
), ),
]else...[ ] else ...[
Text( Text(
'${context.translation.assignedEmployee}: ${activity.activityMaintenance?.assignedEmployee?.userName}', '${context.translation.assignedEmployee}: ${activity.activityMaintenance?.assignedEmployee?.userName}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
@ -359,6 +362,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
supplierStartTime: activity.activityMaintenance?.supplierStartTime != null ? DateTime.parse(activity.activityMaintenance!.supplierStartTime!) : null, supplierStartTime: activity.activityMaintenance?.supplierStartTime != null ? DateTime.parse(activity.activityMaintenance!.supplierStartTime!) : null,
supplierEndTime: activity.activityMaintenance?.supplierEndTime != null ? DateTime.parse(activity.activityMaintenance!.supplierEndTime!) : null, supplierEndTime: activity.activityMaintenance?.supplierEndTime != null ? DateTime.parse(activity.activityMaintenance!.supplierEndTime!) : null,
supplierWorkingHour: activity.activityMaintenance?.supplierWorkingHours, supplierWorkingHour: activity.activityMaintenance?.supplierWorkingHours,
activityMaintenanceTimers: activity.activityMaintenance?.activityMaintenanceTimers ?? [],
supplier: activity.activityMaintenance?.supplier != null supplier: activity.activityMaintenance?.supplier != null
? SupplierDetails( ? SupplierDetails(
id: activity.activityMaintenance?.supplier?.id, id: activity.activityMaintenance?.supplier?.id,

@ -1,4 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -17,6 +18,7 @@ import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/reject_reason_provider.dart'; import 'package:test_sa/providers/service_request_providers/reject_reason_provider.dart';
import 'package:test_sa/providers/work_order/need_visit_reminder_time_provider.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart'; import 'package:test_sa/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart';
@ -31,12 +33,12 @@ import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../new_views/common_widgets/app_text_form_field.dart';
class ServiceRequestBottomSheet { class ServiceRequestBottomSheet {
static buildBottomSheetParent({required BuildContext context, required Widget childWidget,bool ?isDismissible}) { static buildBottomSheetParent({required BuildContext context, required Widget childWidget, bool? isDismissible}) {
return showModalBottomSheet( return showModalBottomSheet(
context: context, context: context,
useSafeArea: true, useSafeArea: true,
isScrollControlled: true, isScrollControlled: true,
isDismissible:isDismissible??true, isDismissible: isDismissible ?? true,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
builder: (context) => SingleChildScrollView( builder: (context) => SingleChildScrollView(
child: childWidget, child: childWidget,
@ -202,14 +204,14 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.green70, buttonColor: AppColor.green70,
loading: false, loading: false,
onPressed: () async { onPressed: () async {
if(requestDetailProvider.fixRemotelyHelperModel?.startDate==null&&requestDetailProvider.fixRemotelyHelperModel?.endDate==null){ if (requestDetailProvider.fixRemotelyHelperModel?.startDate == null && requestDetailProvider.fixRemotelyHelperModel?.endDate == null) {
"Please Select start and end date".showToast; "Please Select start and end date".showToast;
return; return;
} }
requestDetailProvider.fixRemotelyHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder?.data?.requestId; requestDetailProvider.fixRemotelyHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder?.data?.requestId;
requestDetailProvider.engineerFixRemotely(); requestDetailProvider.engineerFixRemotely();
Navigator.pop(context); Navigator.pop(context);
const SizedBox().flushBar(context: context, title: '', message: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm); const SizedBox().flushBar(context: context, title: '', message: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm);
}, },
), ),
), ),
@ -246,25 +248,23 @@ class ServiceRequestBottomSheet {
date: requestDetailProvider.needVisitHelperModel?.visitDate, date: requestDetailProvider.needVisitHelperModel?.visitDate,
formatDateWithTime: true, formatDateWithTime: true,
onDatePicker: (selectedDate) { onDatePicker: (selectedDate) {
if (selectedDate != null) { showTimePicker(
showTimePicker( context: context,
context: context, initialTime: TimeOfDay.now(),
initialTime: TimeOfDay.now(), ).then((selectedTime) {
).then((selectedTime) { // Handle the selected date and time here.
// Handle the selected date and time here. if (selectedTime != null) {
if (selectedTime != null) { DateTime selectedDateTime = DateTime(
DateTime selectedDateTime = DateTime( selectedDate.year,
selectedDate.year, selectedDate.month,
selectedDate.month, selectedDate.day,
selectedDate.day, selectedTime.hour,
selectedTime.hour, selectedTime.minute,
selectedTime.minute, );
); requestDetailProvider.needVisitHelperModel?.visitDate = selectedDateTime;
requestDetailProvider.needVisitHelperModel?.visitDate = selectedDateTime; requestDetailProvider.updateNeedVisitHelperModel(requestDetailProvider.needVisitHelperModel);
requestDetailProvider.updateNeedVisitHelperModel(requestDetailProvider.needVisitHelperModel); }
} });
});
}
}, },
), ),
8.height, 8.height,
@ -290,24 +290,24 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.primary10, buttonColor: AppColor.primary10,
loading: false, loading: false,
onPressed: () async { onPressed: () async {
if(requestDetailProvider.needVisitHelperModel?.visitDate==null){ if (requestDetailProvider.needVisitHelperModel?.visitDate == null) {
"Please select visit date".showToast; "Please select visit date".showToast;
return; return;
} }
if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) {
requestDetailProvider.updateNeedVisitHelperModel(NeedVisitHelperModel( requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId;
workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId,
visitDate: requestDetailProvider.needVisitHelperModel?.visitDate,
comment: requestDetailProvider.needVisitHelperModel?.comment,
));
requestDetailProvider.engineerUpdateNeedVisit(); requestDetailProvider.engineerUpdateNeedVisit();
Navigator.pop(context);
} else { } else {
requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId; requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId;
requestDetailProvider.engineerNeedVisit(); requestDetailProvider.engineerNeedVisit();
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel(); getReminderTimeList(context: context);
Navigator.pop(context);
initialVisitReminderBottomSheet(context: context);
} }
Navigator.pop(context);
// initialVisitReminderBottomSheet(context: context);
// //
}, },
), ),
@ -317,49 +317,60 @@ class ServiceRequestBottomSheet {
})); }));
} }
static Future initialVisitReminderBottomSheet({required BuildContext context}) { static Future<void> getReminderTimeList({required BuildContext context}) async {
String selectedReminderTime = '10 minutes before'; NeedVisitReminderTimeProvider timeProvider = Provider.of<NeedVisitReminderTimeProvider>(context, listen: false);
timeProvider.reset();
WidgetsBinding.instance.addPostFrameCallback((_) {
timeProvider.getDate();
});
}
static Future initialVisitReminderBottomSheet({required BuildContext context, Lookup? reminder}) {
Lookup selectedReminderTime = reminder ?? Lookup();
Widget reminderTimeWidget({required BuildContext context}) { Widget reminderTimeWidget({required BuildContext context}) {
List<String> reminderTimeList = ['5 minutes before', '10 minutes before', '15 minutes before']; return Consumer<NeedVisitReminderTimeProvider>(builder: (cxt, snapshot, _) {
if (snapshot.loading) {
return const ALoading();
}
return StatefulBuilder( return StatefulBuilder(
builder: (context, setState) { builder: (context, setState) {
return Wrap( return Wrap(
direction: Axis.vertical, direction: Axis.vertical,
runSpacing: 8, runSpacing: 8,
spacing: 8, spacing: 20,
children: [ children: [
for (var element in reminderTimeList) for (var element in snapshot.items)
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox( SizedBox(
width: 24, width: 24,
height: 24, height: 24,
child: Radio<String>( child: Radio<Lookup>(
value: element, value: element,
activeColor: Colors.red, activeColor: Colors.red,
fillColor: MaterialStateColor.resolveWith((states) { fillColor: MaterialStateColor.resolveWith((states) {
if (states.contains(MaterialState.selected)) return AppColor.primary10; if (states.contains(MaterialState.selected)) return AppColor.primary10;
return AppColor.neutral130; return AppColor.neutral130;
}), }),
groupValue: selectedReminderTime, groupValue: selectedReminderTime,
onChanged: (String? value) { onChanged: (Lookup? value) {
setState(() { setState(() {
selectedReminderTime = value!; selectedReminderTime = value!;
}); });
}, },
),
), ),
), 8.width,
8.width, Text(element.name ?? '', style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral120)),
Text(element, style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral120)), ],
], )
) ],
], );
); },
}, ).toShimmer(isShow: snapshot.loading);
); });
} }
return buildBottomSheetParent( return buildBottomSheetParent(
@ -380,7 +391,7 @@ class ServiceRequestBottomSheet {
alignment: AlignmentDirectional.centerStart, alignment: AlignmentDirectional.centerStart,
child: context.translation.youCanSetTheReminderInAlarmToRemindYouBeforeVisit.bodyText2(context), child: context.translation.youCanSetTheReminderInAlarmToRemindYouBeforeVisit.bodyText2(context),
), ),
12.height, 30.height,
reminderTimeWidget(context: context), reminderTimeWidget(context: context),
30.height, 30.height,
Row( Row(
@ -393,20 +404,6 @@ class ServiceRequestBottomSheet {
textColor: AppColor.black10, textColor: AppColor.black10,
loading: false, loading: false,
onPressed: () async { onPressed: () async {
if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) {
requestDetailProvider.updateNeedVisitHelperModel(
NeedVisitHelperModel(
workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId,
visitDate: requestDetailProvider.needVisitHelperModel?.visitDate,
comment: requestDetailProvider.needVisitHelperModel?.comment,
),
);
requestDetailProvider.engineerUpdateNeedVisit();
} else {
requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId;
requestDetailProvider.engineerNeedVisit();
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel();
}
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
@ -418,19 +415,16 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.primary10, buttonColor: AppColor.primary10,
loading: false, loading: false,
onPressed: () async { onPressed: () async {
if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { requestDetailProvider.engineerSetReminder(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!, reminderId: selectedReminderTime.id!);
requestDetailProvider.updateNeedVisitHelperModel( try {
NeedVisitHelperModel( DateTime visitDateTime = DateTime.parse(requestDetailProvider.currentWorkOrder!.data!.needAVisitDateTime.toString());
workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId, DateTime updatedDateTime = visitDateTime.subtract(Duration(minutes: selectedReminderTime.value ?? 0));
visitDate: requestDetailProvider.needVisitHelperModel?.visitDate, if (updatedDateTime.isAfter(DateTime.now())) {
comment: requestDetailProvider.needVisitHelperModel?.comment, ServiceRequestUtils.scheduleNotification(context: context, scheduleDateTime: updatedDateTime);
), ServiceRequestUtils.addEventToCalendar(context: context, start: updatedDateTime, end: visitDateTime, title: context.translation.needAVisit);
); }
requestDetailProvider.engineerUpdateNeedVisit(); } catch (e) {
} else { log('error $e');
requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId;
requestDetailProvider.engineerNeedVisit();
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel();
} }
Navigator.pop(context); Navigator.pop(context);
}, },
@ -445,6 +439,7 @@ class ServiceRequestBottomSheet {
), ),
); );
} }
static Future getQRCodeBottomSheet({required BuildContext context}) async { static Future getQRCodeBottomSheet({required BuildContext context}) async {
// Show the loading dialog while fetching QR code // Show the loading dialog while fetching QR code
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
@ -481,12 +476,12 @@ class ServiceRequestBottomSheet {
child: isLoading child: isLoading
? const ALoading() // Show loader while fetching the new QR code ? const ALoading() // Show loader while fetching the new QR code
: Image.memory( : Image.memory(
bytes, // Displaying the QR code from base64 bytes, // Displaying the QR code from base64
fit: BoxFit.contain, // Ensure the image fits well in the dialog fit: BoxFit.contain, // Ensure the image fits well in the dialog
errorBuilder: (context, error, stackTrace) { errorBuilder: (context, error, stackTrace) {
return const Icon(Icons.error, color: Colors.red); return const Icon(Icons.error, color: Colors.red);
}, },
), ),
), ),
), ),
12.height, 12.height,
@ -538,7 +533,6 @@ class ServiceRequestBottomSheet {
}, },
), ),
16.height, 16.height,
], ],
); );
}, },
@ -549,7 +543,6 @@ class ServiceRequestBottomSheet {
} }
} }
static Future rejectRequestBottomSheet({required BuildContext context}) { static Future rejectRequestBottomSheet({required BuildContext context}) {
TextEditingController _commentController = TextEditingController(); TextEditingController _commentController = TextEditingController();
return buildBottomSheetParent( return buildBottomSheetParent(
@ -854,7 +847,7 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.green70, buttonColor: AppColor.green70,
loading: false, loading: false,
onPressed: () { onPressed: () {
if(feedback.isEmpty){ if (feedback.isEmpty) {
"Please provide feedback".showToast; "Please provide feedback".showToast;
return; return;
} }
@ -984,7 +977,6 @@ class ServiceRequestBottomSheet {
setState(() { setState(() {
newSignature = signature; newSignature = signature;
nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
print('signature i got is ${newSignature}');
}); });
}, },
onSaved: (signature) { onSaved: (signature) {
@ -992,7 +984,6 @@ class ServiceRequestBottomSheet {
setState(() { setState(() {
newSignature = signature; newSignature = signature;
nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
print('signature i got is ${newSignature}');
}); });
}, },
), ),
@ -1030,13 +1021,13 @@ class ServiceRequestBottomSheet {
workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!, workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!,
signatureNurse: nurseSignature, signatureNurse: nurseSignature,
); );
await requestDetailProvider.nurseConfirm(); requestDetailProvider.nurseConfirm();
if (requestDetailProvider.currentWorkOrder!.data!.requestId != null) { if (requestDetailProvider.currentWorkOrder!.data!.requestId != null) {
requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!);
} }
Navigator.pop(context); Navigator.pop(context);
} else { } else {
//show some toast... context.translation.signaturesAreRequired.showToast;
} }
}, },
).expanded, ).expanded,
@ -1045,8 +1036,8 @@ class ServiceRequestBottomSheet {
], ],
); );
})); }));
} }
static Future nurseVerifyArrivalBottomSheet({required BuildContext context}) { static Future nurseVerifyArrivalBottomSheet({required BuildContext context}) {
return buildBottomSheetParent( return buildBottomSheetParent(
context: context, context: context,
@ -1094,7 +1085,7 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.green70, buttonColor: AppColor.green70,
onPressed: () async { onPressed: () async {
Navigator.pop(context); Navigator.pop(context);
int? status = await requestDetailProvider.nurseConfirmEngineerArrival(workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId ?? 0); int? status = await requestDetailProvider.nurseConfirmEngineerArrival(workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId ?? 0);
if (status == 200) { if (status == 200) {
requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!);
} }
@ -1105,13 +1096,13 @@ class ServiceRequestBottomSheet {
], ],
); );
})); }));
} }
static Future waitingForApprovalBottomSheet({required BuildContext context}) { static Future waitingForApprovalBottomSheet({required BuildContext context}) {
return buildBottomSheetParent( return buildBottomSheetParent(
context: context, context: context,
childWidget: Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { childWidget: Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -1132,7 +1123,5 @@ class ServiceRequestBottomSheet {
], ],
); );
})); }));
} }
} }

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
@ -9,9 +11,18 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';
class InitialVisitCard extends StatelessWidget { class InitialVisitCard extends StatefulWidget {
const InitialVisitCard({Key? key}) : super(key: key); const InitialVisitCard({Key? key}) : super(key: key);
@override
State<InitialVisitCard> createState() => _InitialVisitCardState();
}
class _InitialVisitCardState extends State<InitialVisitCard> {
@override
void initState() {
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, snapshot) { return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, snapshot) {
@ -27,13 +38,22 @@ class InitialVisitCard extends StatelessWidget {
children: [ children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text( Text(
requestDetailProvider.needVisitHelperModel!.visitDate.toString().toInitialVisitCardFormat, requestDetailProvider.needVisitHelperModel!.visitDate != null ? requestDetailProvider.needVisitHelperModel!.visitDate.toString().toInitialVisitCardFormat : '',
textAlign: TextAlign.end, textAlign: TextAlign.end,
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10), style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
), ),
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() { Row(
ServiceRequestBottomSheet.initialVisitBottomSheet(context: context); children: [
}), "reminder_icon".toSvgAsset(height: 21, width: 21).onPress(() {
ServiceRequestBottomSheet.getReminderTimeList(context: context);
ServiceRequestBottomSheet.initialVisitReminderBottomSheet(context: context, reminder: requestDetailProvider.currentWorkOrder?.data?.setReminder);
}),
24.width,
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() {
ServiceRequestBottomSheet.initialVisitBottomSheet(context: context);
}),
],
),
]), ]),
2.height, 2.height,
context.translation.visitDateAndTime.bodyText2(context).custom(color: AppColor.neutral120), context.translation.visitDateAndTime.bodyText2(context).custom(color: AppColor.neutral120),

@ -25,7 +25,7 @@ import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart';
class ServiceRequestDetailView extends StatelessWidget { class ServiceRequestDetailView extends StatelessWidget {
ServiceRequestDetailView({Key? key}) : super(key: key); const ServiceRequestDetailView({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -54,6 +54,7 @@ class ServiceRequestDetailView extends StatelessWidget {
).expanded, ).expanded,
FooterActionButton.requestDetailsFooterWidget( FooterActionButton.requestDetailsFooterWidget(
workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!, workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!,
// workOrderNextStepStatus: WorkOrderNextStepEnum.eNeedVisit,
activities: requestProvider.currentWorkOrder!.data?.activities ?? [], activities: requestProvider.currentWorkOrder!.data?.activities ?? [],
userProvider: _userProvider, userProvider: _userProvider,
context: context), context: context),
@ -213,7 +214,6 @@ class ServiceRequestDetailView extends StatelessWidget {
'${context.translation.assetStatus}: ${workOrder.equipmentStatus?.name ?? "-"}', '${context.translation.assetStatus}: ${workOrder.equipmentStatus?.name ?? "-"}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
), ),
//TODO need to confirm from backend..
Text( Text(
'${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}', '${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
@ -330,11 +330,11 @@ class ServiceRequestDetailView extends StatelessWidget {
if (requestDetailProvider.currentWorkOrder!.data!.needAVisitDateTime != null && if (requestDetailProvider.currentWorkOrder!.data!.needAVisitDateTime != null &&
userProvider.user?.type == UsersTypes.engineer && userProvider.user?.type == UsersTypes.engineer &&
requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) {
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel( // requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel(
workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId, // workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId,
visitDate: requestDetailProvider.currentWorkOrder?.data?.needAVisitDateTime, // visitDate: requestDetailProvider.currentWorkOrder?.data?.needAVisitDateTime,
comment: requestDetailProvider.currentWorkOrder?.data?.needAVisitComment, // comment: requestDetailProvider.currentWorkOrder?.data?.needAVisitComment,
); // );
return const InitialVisitCard(); return const InitialVisitCard();
} else { } else {
return const SizedBox(); return const SizedBox();

@ -1,9 +1,12 @@
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
class WeeklyCalendarFragment extends StatefulWidget { class WeeklyCalendarFragment extends StatefulWidget {
@ -14,14 +17,13 @@ class WeeklyCalendarFragment extends StatefulWidget {
} }
class _WeeklyCalendarFragmentState extends State<WeeklyCalendarFragment> { class _WeeklyCalendarFragmentState extends State<WeeklyCalendarFragment> {
DateTime? selectedDate = DateTime.now(); // Initially select today's date
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<DateTime> weekDates = getWeekDates(); List<DateTime> weekDates = getWeekDates();
return Consumer<DashBoardProvider>( return Consumer<DashBoardProvider>(
builder: (context, snapshot, _) => GridView.builder( builder: (context, dashBoardProvider, _) => GridView.builder(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
@ -29,7 +31,7 @@ class _WeeklyCalendarFragmentState extends State<WeeklyCalendarFragment> {
crossAxisCount: 7, crossAxisCount: 7,
childAspectRatio: 60 / 80, childAspectRatio: 60 / 80,
crossAxisSpacing: 4, crossAxisSpacing: 4,
mainAxisSpacing: 4, // mainAxisSpacing: 4,
), ),
itemCount: weekDates.length, itemCount: weekDates.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@ -38,19 +40,23 @@ class _WeeklyCalendarFragmentState extends State<WeeklyCalendarFragment> {
String formattedDate = DateFormat('dd MMM').format(currentDate); String formattedDate = DateFormat('dd MMM').format(currentDate);
// Check if the current date is selected // Check if the current date is selected
bool isSelected = selectedDate != null && selectedDate!.day == currentDate.day && selectedDate!.month == currentDate.month && selectedDate!.year == currentDate.year; bool isSelected = dashBoardProvider.upcomingFilterSelectedDate.day == currentDate.day && dashBoardProvider.upcomingFilterSelectedDate.month == currentDate.month && dashBoardProvider.upcomingFilterSelectedDate.year == currentDate.year;
return listItem( return listItem(
formattedDate: formattedDate, formattedDate: formattedDate,
formattedDay: formattedDay, formattedDay: formattedDay,
context: context, context: context,
isLoading: snapshot.isAllCountLoading, isLoading: dashBoardProvider.isAllCountLoading,
currentDate: currentDate, currentDate: currentDate,
isSelected: isSelected, isSelected: isSelected,
onSelect: () { onSelect: () {
setState(() { dashBoardProvider.upcomingFilterSelectedDate = currentDate;
selectedDate = currentDate; // Update selected date on tap // setState(() {
}); // selectedDate = currentDate; // Update selected date on tap
// });
log('selected date:${dashBoardProvider.upcomingFilterSelectedDate.toIso8601String()}');
dashBoardProvider.resetRequestDataList();
dashBoardProvider.getRequestDetail(usersType: UsersTypes.engineer, date: dashBoardProvider.upcomingFilterSelectedDate.toIso8601String(), status: 0);
}, },
); );
}, },
@ -82,51 +88,45 @@ class _WeeklyCalendarFragmentState extends State<WeeklyCalendarFragment> {
return GestureDetector( return GestureDetector(
onTap: isLoading ? null : onSelect, onTap: isLoading ? null : onSelect,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [ children: [
8.height, Container(
Column( padding: EdgeInsets.symmetric(vertical: 18.toScreenHeight),
children: [ width: double.infinity,
Container( decoration: ShapeDecoration(
padding: EdgeInsets.symmetric(horizontal: 7.toScreenWidth, vertical: 14.toScreenHeight), color: AppColor.background(context),
width: double.infinity, shape: RoundedRectangleBorder(
decoration: ShapeDecoration( borderRadius: BorderRadius.circular(10),
color: AppColor.background(context), side: isSelected
shape: RoundedRectangleBorder( ? const BorderSide(color: AppColor.primary10, width: 1.5) // Blue border if selected
borderRadius: BorderRadius.circular(14), : BorderSide.none,
side: isSelected ),
? const BorderSide(color: AppColor.primary10, width: 2) // Blue border if selected shadows: [
: BorderSide.none, BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 5,
offset: const Offset(0, 0),
spreadRadius: 0,
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
formattedDay,
style: AppTextStyles.tinyFont2.copyWith(
color: isSelected ? AppColor.black20 : AppColor.neutral170, // Blue text if selected
), ),
shadows: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 5,
offset: const Offset(0, 0),
spreadRadius: 0,
),
],
), ),
child: Column( Text(
crossAxisAlignment: CrossAxisAlignment.center, formattedDate,
children: [ style: AppTextStyles.tinyFont2.copyWith(
Text( color: isSelected ? AppColor.black20 : AppColor.neutral170, // Blue text if selected
formattedDay, ),
style: AppTextStyles.tinyFont2.copyWith(
color: isSelected ? AppColor.black20 : AppColor.neutral170, // Blue text if selected
),
),
Text(
formattedDate,
style: AppTextStyles.tinyFont2.copyWith(
color: isSelected ? AppColor.black20 : AppColor.neutral170, // Blue text if selected
),
),
],
), ),
), ],
], ),
), ),
], ],
), ),

@ -12,6 +12,7 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart'; import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart';
import '../../../../../models/lookup.dart'; import '../../../../../models/lookup.dart';
import '../../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
@ -37,8 +38,7 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
_requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false); _requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_travellingHoursController.text = _travellingHoursController.text= _requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : '';
_requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : '';
}); });
// _isLoading = true; // _isLoading = true;
} }
@ -55,6 +55,7 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, requestDetailProvider, child) { return Consumer<ServiceRequestDetailProvider>(builder: (context, requestDetailProvider, child) {
double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0;
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
@ -92,95 +93,136 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
}, },
), ),
8.height, 8.height,
Row( AppTimer(
mainAxisSize: MainAxisSize.min, label: context.translation.timer,
children: [ timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel,
ADatePicker( enabled: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.endAt == null,
label: context.translation.startTime, timerProgress: (isRunning) {
hideShadow: true, print("timerProgress:$isRunning");
backgroundColor: AppColor.neutral100, },
date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, onChange: (timer) async {
formatDateWithTime: true, requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer;
onDatePicker: (selectedDate) { return true;
showTimePicker( },
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime;
requestDetailProvider.activityMaintenanceHelperModel?.endTime = null;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
_workingHoursController.clear();
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
},
);
}
});
},
).expanded,
8.width,
ADatePicker(
label: context.translation.endTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.endTime,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null &&
selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) {
"End Date time must be greater then start date".showToast;
return;
}
requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
},
);
}
});
},
).expanded,
],
),
8.height,
AppTextFormField(
labelText: context.translation.workingHours,
backgroundColor: AppColor.neutral80,
controller: _workingHoursController,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
enable: false,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
), ),
// Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// ADatePicker(
// label: context.translation.startTime,
// hideShadow: true,
// backgroundColor: AppColor.neutral100,
// date: requestDetailProvider.activityMaintenanceHelperModel?.startTime,
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(
// selectedDate.year,
// selectedDate.month,
// selectedDate.day,
// selectedTime.hour,
// selectedTime.minute,
// );
// requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime;
// requestDetailProvider.activityMaintenanceHelperModel?.endTime = null;
// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// _workingHoursController.clear();
// ServiceRequestUtils.calculateAndAssignWorkingHours(
// startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
// endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
// workingHoursController: _workingHoursController,
// updateModel: (hours) {
// requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
// },
// );
// }
// });
// },
// ).expanded,
// 8.width,
// ADatePicker(
// label: context.translation.endTime,
// hideShadow: true,
// backgroundColor: AppColor.neutral100,
// date: requestDetailProvider.activityMaintenanceHelperModel?.endTime,
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null &&
// selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) {
// "End Date time must be greater then start date".showToast;
// return;
// }
// requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime;
// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// ServiceRequestUtils.calculateAndAssignWorkingHours(
// startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime,
// endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime,
// workingHoursController: _workingHoursController,
// updateModel: (hours) {
// requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours;
// },
// );
// }
// });
// },
// ).expanded,
// ],
// ),
8.height, 8.height,
if (totalWorkingHours > 0.0) ...[
Container(
height: 56.toScreenHeight,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Total Working Time",
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
),
Text(
" ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}",
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
8.height,
],
// if (totalWorkingHours > 0.0) ...[
// AppTextFormField(
// labelText: context.translation.workingHours,
// backgroundColor: AppColor.neutral80,
// controller: _workingHoursController,
// suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '',
// textAlign: TextAlign.center,
// labelStyle: AppTextStyles.textFieldLabelStyle,
// enable: false,
// showShadow: false,
// style: Theme.of(context).textTheme.titleMedium,
// ),
// 8.height,
// ],
AppTextFormField( AppTextFormField(
labelText: context.translation.travelingHours, labelText: context.translation.travelingHours,
controller: _travellingHoursController, controller: _travellingHoursController,

@ -99,10 +99,25 @@ class _MaintenanceRequestFormState extends State<MaintenanceRequestForm> with Si
//TODO add this as dropdown not added in design yet Bhaa need to confirm with hussain then. //TODO add this as dropdown not added in design yet Bhaa need to confirm with hussain then.
requestDetailProvider.activityMaintenanceHelperModel?.lastSituationId = 282; requestDetailProvider.activityMaintenanceHelperModel?.lastSituationId = 282;
print('model is ${requestDetailProvider.activityMaintenanceHelperModel?.toJson()}');
if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) {
print('value of timer is ${requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel.toString()}');
ActivityMaintenanceTimers model = ActivityMaintenanceTimers(
id: 0,
startTime: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.startAt!.toIso8601String(), // Handle potential null
endTime: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.endAt?.toIso8601String(), // Handle potential null
workingHours: ((requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.durationInSecond ?? 0) / 60 / 60),
);
print('model i got is ${model.toJson()}');
requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers =requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers??[];
requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add(
ActivityMaintenanceTimers(
id: 0,
startTime: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.startAt!.toIso8601String(), // Handle potential null
endTime: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.endAt?.toIso8601String(), // Handle potential null
workingHours: ((requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.durationInSecond ?? 0) / 60 / 60),
),
);
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
int status = -1; int status = -1;
if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) {
@ -130,23 +145,33 @@ class _MaintenanceRequestFormState extends State<MaintenanceRequestForm> with Si
} }
bool validate({required ActivityMaintenanceHelperModel model}) { bool validate({required ActivityMaintenanceHelperModel model}) {
print('employee id is ${model.assignedEmployeeId}');
if (model.activityStatus == null) { if (model.activityStatus == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}"); Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}");
return false; return false;
} else if (model.startTime == null) { }
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.startTime}"); if (model.activityMaintenanceTimerModel?.startAt == null) {
Fluttertoast.showToast(msg: "Working Hours Required");
return false; return false;
} else if (model.endTime == null) { }
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.endTime}"); if (model.activityMaintenanceTimerModel?.endAt == null) {
Fluttertoast.showToast(msg: "Please Stop The Timer");
return false; return false;
} }
// if (model.startTime == null) {
// Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.startTime}");
// return false;
// }
// if (model.endTime == null) {
// Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.endTime}");
// return false;
// }
// else if (model.travelHours == null) { // else if (model.travelHours == null) {
// Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.travelingHours}"); // Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.travelingHours}");
// return false; // return false;
// } // }
else if (model.repairLocation == null) { if (model.repairLocation == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.repairLocation}"); Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.repairLocation}");
return false; return false;
} }

@ -7,6 +7,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/enums/work_order_next_step.dart'; 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/new_views/app_style/app_color.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/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
@ -38,11 +39,16 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
Future<void> getInitialData() async{ Future<void> getInitialData() async{
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user; bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user;
_requestProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false); _requestProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
await _requestProvider.getWorkOrderById(id: widget.requestId); await _requestProvider.getWorkOrderById(id: widget.requestId);
if (isNurse && (_requestProvider.currentWorkOrder?.data?.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.waitingForRequesterToConfirm)) { if (isNurse && (_requestProvider.currentWorkOrder?.data?.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.waitingForRequesterToConfirm)) {
ServiceRequestBottomSheet.nurseVerifyArrivalBottomSheet(context: context); ServiceRequestBottomSheet.nurseVerifyArrivalBottomSheet(context: context);
} }
_requestProvider.needVisitHelperModel = NeedVisitHelperModel(
workOrderId: _requestProvider.currentWorkOrder?.data?.requestId,
visitDate: _requestProvider.currentWorkOrder?.data?.needAVisitDateTime,
comment: _requestProvider.currentWorkOrder?.data?.needAVisitComment,
);
} }
@override @override
@ -62,10 +68,6 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user; bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user;
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
if (requestDetailProvider.timer != null && requestDetailProvider.timer!.isActive) {
requestDetailProvider.stopTimer();
}
stopTimer(); stopTimer();
return true; return true;
}, },
@ -91,7 +93,7 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
: IconButton( : IconButton(
icon: const Icon(Icons.home), icon: const Icon(Icons.home),
onPressed: () { onPressed: () {
stopTimer(); // stopTimer();
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
@ -126,10 +128,10 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
), ),
), ),
12.height, 12.height,
TabBarView( const TabBarView(
children: [ children: [
ServiceRequestDetailView(), ServiceRequestDetailView(),
const HistoryLogView(), HistoryLogView(),
], ],
).expanded, ).expanded,
], ],

@ -20,6 +20,7 @@ class _ScanQrState extends State<ScanQr> {
// In order to get hot reload to work we need to pause the camera if the platform // In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS. // is android, or resume the camera if the platform is iOS.
@override @override
void reassemble() { void reassemble() {
super.reassemble(); super.reassemble();

Loading…
Cancel
Save