in progress

design_3.0_latest
muhammad.abbasi 1 year ago
parent 58666916cc
commit c2b3288423

@ -27,6 +27,7 @@ class URLs {
static get getSiteAutoCompleteWithoutConditionSites => "$_baseUrl/Customer/GetCustomersAutoCompleteWithoutConditionSites"; // get
static get getDepartments => "$_baseUrl/Customer/GetDepartmentLookup"; // get
static get getAssets => "$_baseUrl/Asset/GetAssets"; // get
static get getFaultDescription => "$_baseUrl/Asset/GetDefectForModelDefinition"; // get
static get getAssetById => "$_baseUrl/Asset/GetAssetById?assetId="; // get
static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2
static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get
@ -41,6 +42,7 @@ class URLs {
static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject';
static get engineerFixRemotlyUrl=> '$_baseUrl/ServiceRequest/EngineerFixRemotly';
static get engineerNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerNeedVisit';
static get engineerUpdateNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateNeedVisit';
static get engineerMarkAsFixUrl=> '$_baseUrl/ServiceRequest/EngineerMarkAsFix';
static get engineerConfirmArriveUrl=> '$_baseUrl/ServiceRequest/EngineerConfirmArrive';
static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder';
@ -107,8 +109,8 @@ class URLs {
static get getPpmService => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get for ppm po reason, in mobile there is no use of it.
static get getServiceReportReasons => "$_baseUrl/Lookups/GetLookupReason?lookupEnum=505";
//TODO use this for testing ahmed create new apis for that
static get getServiceReportReasonsTest => "$_baseUrl/Lookups/GetLookup?lookupEnum=505";
static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303";
static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505";
static get getServiceReportRetirementTypeTest => "$_baseUrl/Lookups/GetLookup?lookupEnum=415";
static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get
static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get
@ -120,7 +122,7 @@ class URLs {
static get getServiceReportPriority => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; // get
static get getServiceReportDefectTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; // get
static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get
static get attachmentBaseUrl => "https://atomsmdev.hmg.com/v2/mobile/Files/DownloadFile?fileName=";
//gas refill
static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get
// todo check edits with backend

@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import '../new_views/app_style/app_color.dart';
@ -30,7 +32,7 @@ extension WidgetExtensions on Widget {
flushbarPosition: FlushbarPosition.TOP,
backgroundColor: backgroundColor ?? AppColor.green70,
title: title,
message: message,
messageText: Text(message,style: AppTextStyles.heading6.copyWith(color: AppColor.white10),),
duration: Duration(seconds: duration ?? 3),
flushbarStyle: FlushbarStyle.GROUNDED,
reverseAnimationCurve: Curves.easeInOut,
@ -41,7 +43,7 @@ extension WidgetExtensions on Widget {
icon: const Icon(
Icons.close,
color: AppColor.white20,
),
).paddingOnly(top: 25),
),
)..show(context);

@ -11,6 +11,8 @@
"requestDetails": "تفاصيل الطلب",
"retirementType": "نوع التقاعد",
"assetRetiredPendingOpManagementApproval": "تم تقاعد الأصل. في انتظار موافقة إدارة العمليات",
"youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm": "لقد قمت بوضع علامة على هذه المشكلة على أنها تم إصلاحها. في انتظار تأكيد مقدم الطلب",
"assetRetirementRequestSubmittedSuccessfully": "تم تقديم طلب تقاعد الأصل بنجاح",
"historyLogs": "سجلات التاريخ",
"exitAlert": "هل انت متاكد من رغبتك في إغلاق التطبيق؟",
"signOut": "تسجيل الخروج",
@ -30,6 +32,7 @@
"attachQuotation": "إرفاق العرض",
"forgetPassword": "نسيت كلمة المرور",
"addSparePartActivity": "إضافة نشاط قطع الغيار",
"updateSparePartActivity": "تحديث نشاط قطع غيار",
"acceptTermsAndConditions": "موافقة علي الشروط والاحكام",
"emailValidateMessage": "البريد الالكتروني غير صحيح",
"nameValidateMessage": "الاسم مطلوب",

@ -10,6 +10,8 @@
"exit": "Exit",
"exitAlert": "Are you sure you want to exit?",
"assetRetiredPendingOpManagementApproval": "Asset Retired. Pending OP Management Approval",
"assetRetirementRequestSubmittedSuccessfully": "Asset retirement request submitted successfully",
"youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm": "You marked this issue as fixed. Waiting for the requester to confirm",
"signOut": "Sign Out",
"logoutAlert": "Are you sure you want to Sign Out?",
"language": "English",
@ -99,6 +101,7 @@
"sparePartDetails": "Spare Part Details",
"attachQuotation": "Attach Quotation",
"addSparePartActivity": "Add Spare Part Activity",
"updateSparePartActivity": "Update Spare Part Activity",
"deviceName": "Asset Name",
"deviceImages": "Asset Images",
"deviceModel": "Asset Model",

@ -51,6 +51,7 @@ import 'package:test_sa/providers/service_request_providers/first_action_provide
import 'package:test_sa/providers/service_request_providers/priority_provider.dart';
import 'package:test_sa/providers/service_request_providers/requested_through_provider.dart';
import 'package:test_sa/providers/service_request_providers/type_of_request_provider.dart';
import 'package:test_sa/providers/work_order/fault_description_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/service_type_provider.dart';
@ -82,6 +83,7 @@ import 'controllers/providers/settings/setting_provider.dart';
import 'dashboard_latest/dashboard_provider.dart';
import 'new_views/pages/new_gas_refill_request_page.dart';
import 'providers/service_request_providers/loan_availability_provider.dart';
import 'providers/service_request_providers/reject_reason_provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@ -201,6 +203,8 @@ class MyApp extends StatelessWidget {
/// Loan availability not required
ChangeNotifierProvider(create: (_) => LoanAvailabilityProvider()),
ChangeNotifierProvider(create: (_) => ReasonProvider()),
ChangeNotifierProvider(create: (_) => RejectReasonProvider()),
ChangeNotifierProvider(create: (_) => FaultDescriptionProvider()),
ChangeNotifierProvider(create: (_) => RetirementTypeProvider()),
///todo deleted

@ -4,6 +4,7 @@ class SparePartHelperModel {
int? id;
int? workOrderId;
int? partCatalogItemId;
int? activityStatusId;
SparePart? sparePart;
num? quantity;
String? comment;
@ -15,6 +16,7 @@ class SparePartHelperModel {
this.partCatalogItemId,
this.quantity,
this.sparePart,
this.activityStatusId,
this.comment,this.sparePartAttachments,
});
@ -25,6 +27,7 @@ class SparePartHelperModel {
data['workOrderId'] = workOrderId;
data['partCatalogItemId'] = sparePart?.id;
data['quantity'] = quantity;
data['activityStatusId'] = activityStatusId;
data['comment'] = comment;
if (sparePartAttachments != null) {
data['acitiySparePartAttachments'] =

@ -1,4 +1,5 @@
import 'package:test_sa/models/fault_description.dart';
import 'package:test_sa/models/lookup.dart';
import '../../new_models/work_order_detail_model.dart';
@ -72,7 +73,7 @@ class EngineerUpdateWorkOrderHelperModel {
num?loanAssetId;
WorkOrderAsset? loanAsset;
Lookup? failureReason;
Lookup? faultDescription;
FaultDescription? faultDescription;
String? solution;
EngineerUpdateWorkOrderHelperModel(
@ -97,10 +98,11 @@ class EngineerUpdateWorkOrderHelperModel {
data['serviceTypeId'] = serviceType?.id;
data['serviceTypeId'] = 65;
data['loanAvailabilityId'] = loanAvailability?.id;
data['loanAssetId'] = loanAsset?.id;
data['loanAssetId'] = loanAssetId;
data['failureReasonId'] = failureReason?.id;
data['faultDescriptionId'] = faultDescription?.id;
data['solution'] = solution;
//TODO this cause issue with the return data
// data['solution'] = solution;
return data;
}
}
@ -132,12 +134,11 @@ class NeedVisitHelperModel {
class EngineerRejectHelperModel {
int? workOrderId;
String? feedback;
int? rejectReasonId;
Lookup? rejectionReason;
EngineerRejectHelperModel({this.workOrderId, this.feedback, this.rejectReasonId,this.rejectionReason});
EngineerRejectHelperModel({this.workOrderId, this.feedback,this.rejectionReason});
Map<String, dynamic> toJson() {
return {'workOrderId': workOrderId, 'feedback': feedback, 'rejectReasonId': rejectReasonId};
return {'workOrderId': workOrderId, 'feedback': feedback, 'rejectReasonId': rejectionReason?.id};
}
}

@ -1,3 +1,5 @@
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/lookup.dart';
class WorkOrderDetail {
@ -124,10 +126,12 @@ class WorkOrderData {
DateTime? needAVisitDateTime;
String?needAVisitComment;
List<WorkOrderHistory> workOrderHistory;
List<dynamic> activities;
List<Activities> activities;
List<dynamic> activityAssetToBeRetireds;
factory WorkOrderData.fromJson(Map<String, dynamic> json) {
print('activities in json is ${json["activities"]}');
return WorkOrderData(
requestId: json["id"],
workOrderNo: json["workOrderNo"],
@ -167,7 +171,7 @@ class WorkOrderData {
solution: json["solution"] == null ? null : Lookup.fromJson(json["solution"]),
totalWorkingHours: json["totalWorkingHours"],
workOrderHistory: json["workOrderHistory"] == null ? [] : List<WorkOrderHistory>.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))),
activities: json["activities"] == null ? [] : List<dynamic>.from(json["activities"]!.map((x) => x)),
activities: json["activities"] == null ? [] : List<Activities>.from(json["activities"]!.map((x) => Activities.fromJson(x))),
needAVisitDateTime: DateTime.tryParse(json["requestedDate"] ?? ""),
needAVisitComment: json["needAVisitComment"],
activityAssetToBeRetireds: json["activityAssetToBeRetireds"] == null ? [] : List<dynamic>.from(json["activityAssetToBeRetireds"]!.map((x) => x)),
@ -215,7 +219,7 @@ class WorkOrderData {
"solution": solution?.toJson(),
"totalWorkingHours": totalWorkingHours,
"workOrderHistory": workOrderHistory.map((x) => x.toJson()).toList(),
"activities": activities.map((x) => x).toList(),
"activities": activities.map((x) => x.toJson()).toList(),
"activityAssetToBeRetireds": activityAssetToBeRetireds.map((x) => x).toList(),
};
Map<String, dynamic> toFixRemotelyJson() {
@ -323,6 +327,141 @@ class AssignedEmployee {
"languageId": languageId,
};
}
class Activities {
int? id;
int? orderNo;
ActivityStatus? activityStatus;
dynamic activityMaintenance;
ActivitySparePart? activitySparePart;
String ?activityType;
Activities(
{this.id,
this.orderNo,
this.activityStatus,
this.activityMaintenance,
this.activityType,
this.activitySparePart});
Activities.fromJson(Map<String, dynamic> json) {
id = json['id'];
orderNo = json['orderNo'];
activityStatus = json['activityStatus'] != null
? ActivityStatus.fromJson(json['activityStatus'])
: null;
activityMaintenance = json['activityMaintenance'];
if(activityMaintenance!=null){
activityType='Maintenance Request';
}
activitySparePart = json['activitySparePart'] != null
? ActivitySparePart.fromJson(json['activitySparePart'])
: null;
if(activitySparePart!=null){
activityType='Spare Part Request';
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['orderNo'] = orderNo;
if (activityStatus != null) {
data['activityStatus'] = activityStatus!.toJson();
}
data['activityMaintenance'] = activityMaintenance;
if (activitySparePart != null) {
data['activitySparePart'] = activitySparePart!.toJson();
}
return data;
}
}
class ActivityStatus {
int? id;
String? name;
int? value;
ActivityStatus({this.id, this.name, this.value});
ActivityStatus.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
value = json['value'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['value'] = this.value;
return data;
}
}
class ActivitySparePart {
int? id;
PartCatalogItem? partCatalogItem;
double? quantity;
List<SparePartAttachments>? acitiySparePartAttachments;
ActivitySparePart(
{this.id,
this.partCatalogItem,
this.quantity,
this.acitiySparePartAttachments});
ActivitySparePart.fromJson(Map<String, dynamic> json) {
id = json['id'];
partCatalogItem = json['partCatalogItem'] != null
? new PartCatalogItem.fromJson(json['partCatalogItem'])
: null;
quantity = json['quantity'];
if (json['acitiySparePartAttachments'] != null) {
acitiySparePartAttachments = <SparePartAttachments>[];
json['acitiySparePartAttachments'].forEach((v) {
acitiySparePartAttachments!.add(SparePartAttachments.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
if (partCatalogItem != null) {
data['partCatalogItem'] = partCatalogItem!.toJson();
}
data['quantity'] = quantity;
if (acitiySparePartAttachments != null) {
data['acitiySparePartAttachments'] =
acitiySparePartAttachments!.map((v) => v.toJson()).toList();
}
return data;
}
}
class PartCatalogItem {
int? id;
String? partName;
String? partNumber;
PartCatalogItem({this.id, this.partName, this.partNumber});
PartCatalogItem.fromJson(Map<String, dynamic> json) {
id = json['id'];
partName = json['partName'];
partNumber = json['partNumber'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['partName'] = this.partName;
data['partNumber'] = this.partNumber;
return data;
}
}
class Site {
Site({

@ -7,6 +7,7 @@ class SparePartsWorkOrders extends Base {
id = json['id'];
sparePart = json['sparePart'] != null ? SparePart.fromJson(json['sparePart']) : null;
qty = json['qty'];
returnQty = json['returnQty'];
installQty = json['installQty'];
}
@ -38,6 +39,7 @@ class SparePart extends Base {
this.id,
this.partNo,
this.partName,
this.oracleCode,
this.assetId,
}) : super(identifier: id?.toString(), name: partName);
@ -46,6 +48,7 @@ class SparePart extends Base {
identifier = id?.toString();
partNo = json['partNo'];
partName = json['partName'];
oracleCode = json['oracleCode'];
name = partName;
assetId = json['assetId'];
}
@ -53,16 +56,18 @@ class SparePart extends Base {
num? id;
String? partNo;
String? partName;
String? oracleCode;
num? assetId;
SparePart copyWith({num? id, String? partNo, String? partName, num? assetId}) =>
SparePart(id: id ?? this.id, partNo: partNo ?? this.partNo, partName: partName ?? this.partName, assetId: assetId ?? this.assetId);
SparePart copyWith({num? id, String? partNo, String? partName, num? assetId,String?oracleCode}) =>
SparePart(id: id ?? this.id,oracleCode: oracleCode?? this.oracleCode, partNo: partNo ?? this.partNo, partName: partName ?? this.partName, assetId: assetId ?? this.assetId);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['partNo'] = partNo;
map['partName'] = partName;
map['oracleCode'] = oracleCode;
map['assetId'] = assetId;
return map;
}

@ -30,6 +30,7 @@ class AppColor {
static const Color neutral130 = Color(0xffE0E0E0);
static const Color neutral140 = Color(0xffE6E6E6);
static const Color neutral150 = Color(0xffA1A1A1);
static const Color neutral160 = Color(0xffE5E5E5);
//background

@ -34,6 +34,7 @@ class AppDrawer extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Consumer<UserProvider>(builder: (context, snapshot, _) {
print('profile photo i got is ${snapshot.user!.profilePhotoName!}');
return CircleAvatar(
radius: 45,
backgroundColor: context.isDark ? AppColor.neutral50 : AppColor.neutral40,

@ -53,8 +53,10 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
if (X != NullableLoadingProvider) {
provider = Provider.of<X>(widget.context, listen: false);
}
print('initial value i got is ${widget.initialValue?.identifier}');
if (widget.initialValue != null) {
final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
print('result value i got is ${result?.length}');
if (result?.isNotEmpty ?? false) _selectedItem = result!.first as T?;
if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
widget.onSelect!(_selectedItem); // Non-null assertion after null check
@ -70,6 +72,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
@override
void didUpdateWidget(covariant SingleItemDropDownMenu<T, X> oldWidget) {
if (widget.initialValue != null) {
final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
if (result?.isNotEmpty ?? false) {
@ -89,7 +92,6 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
@override
Widget build(BuildContext context) {
provider = Provider.of<X>(widget.context, listen: true);
final isEmpty = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.isEmpty ?? true;
return AppLoadingManager(
isLoading: widget.loading ?? ((X == NullableLoadingProvider) ? false : provider?.loading ?? false),

@ -0,0 +1,38 @@
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 RejectReasonProvider extends LoadingListNotifier<Lookup> {
@override
Future getDate() async {
if (loading == true) return -2;
loading = true;
notifyListeners();
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.get(URLs.getServiceReportRejectionReasons);
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;
}
}
}

@ -0,0 +1,41 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/fault_description.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
class FaultDescriptionProvider extends ChangeNotifier {
int? _stateCode;
int? get stateCode => _stateCode;
bool _loading = false;
bool get isLoading => _loading;
set isLoading(bool isLoading) {
_loading = isLoading;
notifyListeners();
}
Future<List<FaultDescription>> getFaultDescriptionList({num? assetId}) async {
late Response response;
try {
response = await ApiManager.instance.get(URLs.getFaultDescription+"?assetId=$assetId",);
List<FaultDescription> list = [];
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
List faultListJson = json.decode(response.body)["data"];
list = faultListJson.map((fault) => FaultDescription.fromJson(fault)).toList();
}
return list;
} catch (error) {
return [];
}
}
}

@ -19,11 +19,9 @@ class ReasonProvider extends LoadingListNotifier<Lookup> {
loading = true;
notifyListeners();
try {
//TODO change this url only used for testing till ahmed make a new api.. getServiceReportReasonsTest replace with getServiceReportReasons
Response response = await ApiManager.instance.get(URLs.getServiceReportReasonsTest+"&serviceRequestId=$serviceRequestId");
Response response = await ApiManager.instance.get(URLs.getServiceReportReasonsNew+"&serviceRequestId=$serviceRequestId");
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();
}

@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:http/src/response.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/helper_data_models/asset_retired/asset_retired_model.dart';
@ -63,11 +64,11 @@ class RequestDetailProvider extends ChangeNotifier {
//UI models
WorkOrderDetail? currentWorkOrder;
AssetRetiredHelperModel? assetRetiredHelperModel=AssetRetiredHelperModel();
SparePartHelperModel? sparePartHelperModel=SparePartHelperModel();
SparePartHelperModel? sparePartHelperModel;
FixRemotelyHelperModel? fixRemotelyHelperModel=FixRemotelyHelperModel();
NeedVisitHelperModel? needVisitHelperModel=NeedVisitHelperModel();
NurseActionHelperModel? nurseActionHelperModel;
EngineerRejectHelperModel? engineerRejectHelperModel;
EngineerRejectHelperModel? engineerRejectHelperModel=EngineerRejectHelperModel();
EngineerUpdateWorkOrderHelperModel? engineerUpdateWorkOrderHelperModel=EngineerUpdateWorkOrderHelperModel();
WorkOrderHelperModel? workOrderHelperModel;
@ -182,125 +183,157 @@ class RequestDetailProvider extends ChangeNotifier {
}
//engineerAcceptWorkOrder......
Future<CommonResponseModel> engineerAcceptWorkOrder({required String id}) async {
Future<int> engineerAcceptWorkOrder({required String id}) async {
Response response;
try {
final body = {
"workOrderId": id,
};
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerAcceptUrl, body: body);
response = await ApiManager.instance.post(URLs.engineerAcceptUrl, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer accept workorder ${commonResponseModel.toJson()}');
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
updateCurrentWorkOrder(currentWorkOrder);
notifyListeners();
isLoading = false;
return commonResponseModel;
return response.statusCode;
}
isLoading = false;
notifyListeners();
return CommonResponseModel();
return response.statusCode;
} catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
return -1;
}
}
//engineerRejectWorkOrder......
Future<CommonResponseModel> engineerRejectWorkOrder() async {
Future<int> engineerRejectWorkOrder() async {
Response response ;
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerRejectUrl, body: engineerRejectHelperModel!.toJson());
response = await ApiManager.instance.post(URLs.engineerRejectUrl, body: engineerRejectHelperModel!.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer reject workorder ${commonResponseModel.toJson()}');
print('engineer reject workOrder response is ${response.body}');
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
updateCurrentWorkOrder(currentWorkOrder);
notifyListeners();
isLoading = false;
return commonResponseModel;
return response.statusCode;
}
isLoading = false;
notifyListeners();
return CommonResponseModel();
return response.statusCode;
} catch (e) {
log("engineer accept [error] : $e");
log("engineer reject [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
return -1;
}
}
//engineerFixRemotelyWorkOrder......
Future<CommonResponseModel> engineerFixRemotely() async {
Future<int> engineerFixRemotely() async {
Response response;
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerFixRemotlyUrl, body: fixRemotelyHelperModel!.toJson());
response = await ApiManager.instance.post(URLs.engineerFixRemotlyUrl, body: fixRemotelyHelperModel!.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer fixremotely workorder ${commonResponseModel.toJson()}');
updateCurrentWorkOrder(WorkOrderDetail.fromJson(json.decode(response.body)));
notifyListeners();
isLoading = false;
return commonResponseModel;
return response.statusCode;
}
isLoading = false;
notifyListeners();
return CommonResponseModel();
return response.statusCode;
} catch (e) {
log("engineer accept [error] : $e");
log("engineer fix remotely [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
return -1;
}
}
//engineerNeedAVisitWorkOrder......
Future<CommonResponseModel> engineerNeedVisit() async {
Future<int> engineerNeedVisit() async {
Response response;
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerNeedVisitUrl, body: needVisitHelperModel!.toJson());
response = await ApiManager.instance.post(URLs.engineerNeedVisitUrl, body: needVisitHelperModel!.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer fixremotely workorder ${commonResponseModel.toJson()}');
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
updateCurrentWorkOrder(currentWorkOrder);
notifyListeners();
isLoading = false;
return commonResponseModel;
return response.statusCode;
}
isLoading = false;
notifyListeners();
return CommonResponseModel();
return response.statusCode;
} catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
return -1;
}
}
//engineerUpdateNeedAVisitWorkOrder......
Future<int> engineerUpdateNeedVisit() async {
Response response;
try {
isLoading = true;
response = await ApiManager.instance.post(URLs.engineerUpdateNeedVisitUrl, body: needVisitHelperModel!.toJson());
stateCode = response.statusCode;
print('body i got is ${needVisitHelperModel?.toJson()}');
print('response i got is ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
updateCurrentWorkOrder(currentWorkOrder);
notifyListeners();
isLoading = false;
return response.statusCode;
}
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return -1;
}
}
//engineerMarkAsFixed......
Future<CommonResponseModel> engineerMarkAsFixed({required int workOrderId,required String feedback}) async {
Future<int> engineerMarkAsFixed({required int workOrderId,required String feedback}) async {
Response response ;
try {
Map<String,dynamic> body = {'workOrderId': workOrderId, 'feedback': feedback};
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerMarkAsFixUrl, body: body);
response = await ApiManager.instance.post(URLs.engineerMarkAsFixUrl, body: body);
stateCode = response.statusCode;
print('engineer mark as fixed response is ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
notifyListeners();
isLoading = false;
return commonResponseModel;
return response.statusCode;
}
isLoading = false;
notifyListeners();
return CommonResponseModel();
return response.statusCode;
} catch (e) {
log("engineer accept [error] : $e");
log("engineer mark as fixed [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
return -1;
}
}
@ -358,13 +391,10 @@ class RequestDetailProvider extends ChangeNotifier {
//engineerUpdateWorkOrder......
Future<void> engineerUpdateWorkOrder() async {
try {
// try {
isLoading = true;
print('body to update work order is ${engineerUpdateWorkOrderHelperModel!.toJson()}');
final response = await ApiManager.instance.post(URLs.engineerUpdateWorkOrderUrl, body: engineerUpdateWorkOrderHelperModel!.toJson());
stateCode = response.statusCode;
print('response of the verify Asset detail is ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
updateCurrentWorkOrder(currentWorkOrder);
@ -373,11 +403,12 @@ class RequestDetailProvider extends ChangeNotifier {
}
isLoading = false;
notifyListeners();
} catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
}
// }
// catch (e) {
// log("engineer update workorder [error] : $e");
// isLoading = false;
// notifyListeners();
// }
}
//Nurse confirm reopen
@ -436,6 +467,7 @@ class RequestDetailProvider extends ChangeNotifier {
body: sparePartHelperModel!.toJson(),
);
stateCode = response.statusCode;
print('update response i got is ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300) {
// request.engineerName = employee.name;
notifyListeners();
@ -462,8 +494,10 @@ class RequestDetailProvider extends ChangeNotifier {
body: body,
);
stateCode = response.statusCode;
print('response of delete activity spare part is ${response.statusCode}');
if (response.statusCode >= 200 && response.statusCode < 300) {
//map to the model...
notifyListeners();
}
isLoading = false;
@ -506,7 +540,6 @@ class RequestDetailProvider extends ChangeNotifier {
URLs.createActivityAssetToBeRetiredUrl,
body: assetRetiredHelperModel!.toJson(),
);
print('response i got is ${response.body}');
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
@ -524,7 +557,6 @@ class RequestDetailProvider extends ChangeNotifier {
}
//get Arrival type......
//TODO create a model when there is data in api...
Future<ArrivalVerificationTypeModel> getArrivalVerificationType() async {
ArrivalVerificationTypeModel arrivalVerificationTypeModel= ArrivalVerificationTypeModel();
try {
@ -553,6 +585,7 @@ class RequestDetailProvider extends ChangeNotifier {
final response = await ApiManager.instance.postWithOutBody(
URLs.sendOtpUrl+ "$workOrderId",
);
print('url for send otp is ${URLs.sendOtpUrl+ "$workOrderId"}');
stateCode = response.statusCode;
print('response i got is ${response.body}');

@ -1,16 +1,20 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/main.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/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/providers/service_request_providers/reject_reason_provider.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
import 'package:test_sa/service_request_latest/views/components/activities_list_view.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/verify_arrival_view.dart';
import 'package:test_sa/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart';
@ -27,16 +31,148 @@ class FooterActionButton {
);
}
static Widget requestDetailsFooterWidget({required WorkOrderNextStepEnum workOrderNextStepStatus, required BuildContext context}) {
static Widget requestDetailsFooterWidget({required WorkOrderNextStepEnum workOrderNextStepStatus, required BuildContext context, required UserProvider userProvider}) {
RequestDetailProvider requestDetailProvider = Provider.of<RequestDetailProvider>(context, listen: false);
switch (workOrderNextStepStatus) {
case WorkOrderNextStepEnum.onlyView:
return const SizedBox();
// TODO: Handle this case.
case WorkOrderNextStepEnum.markedAsFixed:
// TODO: Handle this case.
case WorkOrderNextStepEnum.nTakeAction:
if (userProvider.user?.type == UsersTypes.engineer) {
switch (workOrderNextStepStatus) {
case WorkOrderNextStepEnum.onlyView:
return const SizedBox();
// TODO: Handle this case.
case WorkOrderNextStepEnum.markedAsFixed:
// TODO: Handle this case.
case WorkOrderNextStepEnum.nTakeAction:
// const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: '');
return footerContainer(
child: AppFilledButton(
label: context.translation.close,
// maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
Navigator.pop(context);
},
));
case WorkOrderNextStepEnum.eRejectAccept:
return footerContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
AppFilledButton(
label: context.translation.reject,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
//TODO need to discuss getData is not called by default...
if (context.mounted) {
RejectReasonProvider rejectionReasonProvider = Provider.of<RejectReasonProvider>(context, listen: false);
rejectionReasonProvider.reset();
rejectionReasonProvider.getDate();
}
ServiceRequestBottomSheet.rejectRequestBottomSheet(context: context);
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.accept,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
requestDetailProvider.engineerAcceptWorkOrder(id: requestDetailProvider.currentWorkOrder!.data!.requestId.toString()).whenComplete(() {});
},
).expanded,
],
));
case WorkOrderNextStepEnum.eFixRemotelyNeedVisit:
return footerContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
AppFilledButton(
label: context.translation.needAVisit,
maxWidth: true,
buttonColor: AppColor.neutral50,
onPressed: () async {
ServiceRequestBottomSheet.initialVisitBottomSheet(context: context);
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.fixedRemotely,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context);
},
).expanded,
],
));
case WorkOrderNextStepEnum.eArrived:
return footerContainer(
child: AppFilledButton(
label: context.translation.iHaveArrived,
showIcon: true,
icon: 'arrived_icon'.toSvgAsset(),
buttonColor: AppColor.green70,
onPressed: () async {
Navigator.push(context, MaterialPageRoute(builder: (context) => const VerifyArrivalView()));
},
));
case WorkOrderNextStepEnum.verifyAssetDetail:
return footerContainer(
child: AppFilledButton(
label: context.translation.verify_asset_details,
// maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
Navigator.push(context, MaterialPageRoute(builder: (context) => const VerifyAssetDetails()));
},
));
case WorkOrderNextStepEnum.activity:
return footerContainer(
child: Column(
children: [
AppFilledButton(
label: context.translation.activities,
// maxWidth: true,
buttonColor: AppColor.neutral50,
onPressed: () async {
// ServiceRequestBottomSheet.activityTypeBottomSheet(context: context);
Navigator.push(context, MaterialPageRoute(builder: (context)=>const ActivitiesListView()));
},
),
8.height,
AppFilledButton(
label: context.translation.markAsFixed,
// maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
ServiceRequestBottomSheet.feedBackBottomSheet(context: context);
},
),
],
));
case WorkOrderNextStepEnum.endWorkFlow:
return const SizedBox();
case WorkOrderNextStepEnum.assetRetirementManagementApproval:
return footerContainer(
child: AppFilledButton(
label: context.translation.assetRetiredPendingOpManagementApproval,
buttonColor: AppColor.neutral140,
textColor: AppColor.neutral150,
fontSize: 12.toScreenWidth,
));
}
} else if (userProvider.user?.type == UsersTypes.nurse) {
if (workOrderNextStepStatus == WorkOrderNextStepEnum.nTakeAction) {
return footerContainer(
child: AppFilledButton(
label: context.translation.takeAction,
@ -46,134 +182,8 @@ class FooterActionButton {
ServiceRequestBottomSheet.nurseTakeActionBottomSheet(context: context);
},
));
case WorkOrderNextStepEnum.eRejectAccept:
return footerContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
AppFilledButton(
label: context.translation.reject,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
//TODO need to discuss getData is not called by default...
if (context.mounted) {
ReasonProvider reasonProvider = Provider.of<ReasonProvider>(context, listen: false);
reasonProvider.reset();
// reasonProvider.serviceRequestId = requestDetailProvider.currentServiceRequestId.toString();
reasonProvider.serviceRequestId = '3';
reasonProvider.getDate();
}
ServiceRequestBottomSheet.rejectRequestBottomSheet(context: context);
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.accept,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
requestDetailProvider.engineerAcceptWorkOrder(id: requestDetailProvider.currentWorkOrder!.data!.requestId.toString()).whenComplete(() {
requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!);
});
},
).expanded,
],
));
case WorkOrderNextStepEnum.eFixRemotelyNeedVisit:
return footerContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
AppFilledButton(
label: context.translation.needAVisit,
maxWidth: true,
buttonColor: AppColor.neutral50,
onPressed: () async {
ServiceRequestBottomSheet.initialVisitBottomSheet(context: context);
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.fixedRemotely,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context);
},
).expanded,
],
));
case WorkOrderNextStepEnum.eArrived:
return footerContainer(
child: AppFilledButton(
label: context.translation.iHaveArrived,
showIcon: true,
icon: 'arrived_icon'.toSvgAsset(),
buttonColor: AppColor.green70,
onPressed: () async {
Navigator.push(context, MaterialPageRoute(builder: (context) => const VerifyArrivalView()));
},
));
case WorkOrderNextStepEnum.verifyAssetDetail:
return footerContainer(
child: AppFilledButton(
label: context.translation.verify_asset_details,
// maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
Navigator.push(context, MaterialPageRoute(builder: (context) => const VerifyAssetDetails()));
},
));
case WorkOrderNextStepEnum.activity:
return footerContainer(
child: Column(
children: [
AppFilledButton(
label: context.translation.activities,
// maxWidth: true,
buttonColor: AppColor.neutral50,
onPressed: () async {
ServiceRequestBottomSheet.activityTypeBottomSheet(context: context);
},
),
8.height,
AppFilledButton(
label: context.translation.markAsFixed,
// maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
ServiceRequestBottomSheet.feedBackBottomSheet(context: context);
},
),
],
));
case WorkOrderNextStepEnum.endWorkFlow:
return const SizedBox();
// return footerContainer(
// child: AppFilledButton(
// label: context.translation.close,
// // maxWidth: true,
// buttonColor: AppColor.primary10,
// onPressed: () async {},
// ));
case WorkOrderNextStepEnum.assetRetirementManagementApproval:
return footerContainer(
child: AppFilledButton(
label: context.translation.assetRetiredPendingOpManagementApproval,
buttonColor: AppColor.neutral140,
textColor: AppColor.neutral150,
fontSize: 12.toScreenWidth,
));
}
}
return const SizedBox();
}
}

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
@ -8,13 +10,19 @@ import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/models/service_request/search_work_order.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
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/default_app_bar.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.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/forms/spare_part/spare_part_request.dart';
import 'package:test_sa/views/pages/user/requests/work_order/update_service_report.dart';
import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
@ -27,102 +35,129 @@ class ActivitiesListView extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<dynamic> activities = [];
//TODO add the check for type of activity after completing maintenance activity flow.
List<Activities> activities = [];
UserProvider userProvider = Provider.of<UserProvider>(context);
return Scaffold(
appBar: DefaultAppBar(title: context.translation.activities),
//backgroundColor: const Color(0xfff8f9fb),
body: Consumer<RequestDetailProvider>(builder: (context, RequestDetailProvider requestDetailProvider, child) {
activities = requestDetailProvider.currentWorkOrder!.data!.activities;
return Column(
return Column(
children: [
(activities.isEmpty)
? NoDataFound(message: context.translation.noDataFound).expanded
: ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: activities.length,
separatorBuilder: (czt, index) => 8.height,
itemBuilder: (context, index) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusLabel(
label: activities[index].currentSituation!.name,
textColor: AppColor.getRequestStatusTextColorByName(context, activities[index].currentSituation!.name!),
backgroundColor: AppColor.getRequestStatusColorByName(context, activities[index].currentSituation!.name!),
),
8.height,
//activity type...
Text(
'${activities[index].callRequest!.asset!.modelDefinition!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
),
2.height,
Text(
'${context.translation.workingHours}: ${activities[index].currentSituation?.workingHours}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
2.height,
Text(
'${context.translation.date}: ${activities[index].currentSituation?.date}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
2.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.viewDetails,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
4.width,
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
),
],
).onPress(() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: activities[index], serviceRequest: ServiceRequest())),
);
}).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (userProvider.user!.type == UsersTypes.engineer &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 3)
"edit".toSvgAsset(height: 48, width: 48).onPress(() {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => UpdateServiceReport(request: ServiceRequest(), workOrder: activities[index])),
);
}),
if (userProvider.user!.type == UsersTypes.engineer &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 3)
8.height,
Text(activities[index].visitDate?.toServiceRequestCardFormat ?? "",
textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : const Color(0xFF3B3D4A))),
],
)
],
).toShadowContainer(context);
},
).expanded,
padding: const EdgeInsets.all(16),
itemCount: activities.length,
separatorBuilder: (czt, index) => 8.height,
itemBuilder: (context, index) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StatusLabel(
label: activities[index].activityStatus?.name,
textColor: AppColor.getRequestStatusTextColorByName(context, activities[index].activityStatus?.name),
backgroundColor: AppColor.getRequestStatusColorByName(context, activities[index].activityStatus?.name),
),
"drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160),
if (userProvider.user!.type == UsersTypes.engineer &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 3)
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() {
print('attachments in activity model is ${activities[index].activitySparePart?.acitiySparePartAttachments}');
requestDetailProvider.sparePartHelperModel=SparePartHelperModel(
id: activities[index].id,
workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId,
sparePartAttachments:activities[index].activitySparePart?.acitiySparePartAttachments??[],
sparePart:SparePart(
id: activities[index].activitySparePart?.partCatalogItem?.id,
partName: activities[index].activitySparePart?.partCatalogItem?.partName,
partNo: activities[index].activitySparePart?.partCatalogItem?.partNumber),
quantity: activities[index].activitySparePart?.quantity,
activityStatusId: activities[index].activityStatus?.id,
//TODO commets are missing in api response..
// comment: activities[index].activitySparePart?.description,
);
requestDetailProvider.updateSparePartHelperModel(requestDetailProvider.sparePartHelperModel);
print('model in activity page is ${requestDetailProvider.sparePartHelperModel?.toJson()}');
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const SparePartRequest (),
));
}),
24.width,
"delete_icon".toSvgAsset(height: 21, width: 21).onPress(()async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
int status = await requestDetailProvider.deleteActivitySparePart(id: activities[index].id!, workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!);
if (status == 200) {
await requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!);
Navigator.pop(context);
} else {
Navigator.pop(context);
}
}),
],
)
],
),
6.height,
//activity type...
Text(
'${activities[index].activityType?.cleanupWhitespace.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
),
3.height,
Text(
'${context.translation.partName}: ${activities[index].activitySparePart?.partCatalogItem?.partName}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
2.height,
Text(
'${context.translation.partNo}: ${activities[index].activitySparePart?.partCatalogItem?.partNumber}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
2.height,
//TODO description text not in api.
// Text(
// '${context.translation.date}: ${activities[index].currentSituation?.date}',
// style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
// ),
2.height,
],
).onPress(() {
//TODO write onview detail method..
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: activities[index], serviceRequest: ServiceRequest())),
// );
}).expanded,
],
).toShadowContainer(context);
},
).expanded,
if (userProvider.user!.type == UsersTypes.engineer &&
(requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3))
AppFilledButton(
(requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3))
FooterActionButton.footerContainer(
child: AppFilledButton(
label: context.translation.createNewActivity,
maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
ServiceRequestBottomSheet.activityTypeBottomSheet(context: context);
},
).paddingOnly(start: 16, end: 16, bottom: 16)
))
],
);
}),

@ -10,11 +10,14 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/work_order_next_step.dart';
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/first_action_provider.dart';
import 'package:test_sa/providers/service_request_providers/reject_reason_provider.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart';
@ -174,8 +177,6 @@ class ServiceRequestBottomSheet {
textColor: AppColor.black20,
onPressed: () async {
Navigator.pop(context);
// await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest);
// Navigator.pop(context, true);
},
),
),
@ -185,11 +186,14 @@ class ServiceRequestBottomSheet {
label: context.translation.fixed,
buttonColor: AppColor.green70,
loading: false,
onPressed: () {
onPressed: () async {
//TODO after confirm from backend call the api and reset the model.
// requestDetailProvider.engineerFixRemotely();
// requestDetailProvider.fixRemotelyHelperModel = FixRemotelyHelperModel();
print('model i got is ${requestDetailProvider.fixRemotelyHelperModel?.toJson()}');
requestDetailProvider.fixRemotelyHelperModel?.workOrderId= requestDetailProvider.currentWorkOrder?.data?.requestId;
await requestDetailProvider.engineerFixRemotely();
//TODO context issue to show message..
// const SizedBox().flushBar(context: context, title: '', message: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm);
Navigator.pop(context);
},
),
),
@ -332,10 +336,14 @@ class ServiceRequestBottomSheet {
}
static Future initialVisitBottomSheet({required BuildContext context}) {
TextEditingController _commentController = TextEditingController();
return buildBottomSheetParent(
context: context,
childWidget: Consumer<RequestDetailProvider>(builder: (context, requestDetailProvider, child) {
if(requestDetailProvider.needVisitHelperModel?.comment!=null){
_commentController.text = requestDetailProvider.needVisitHelperModel!.comment!;
}
return Column(
children: [
const SizedBox().indicatorWidget(),
@ -373,74 +381,10 @@ class ServiceRequestBottomSheet {
}
},
),
// if (serviceRequestProvider.currentSelectedRequest?.firstAction?.id == 404 && Provider.of<SettingProvider>(context, listen: false).assetGroup?.id == 1) ...[
// 8.height,
// Row(
// children: [
// ADatePicker(
// label: context.translation.startDate,
// date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.startDate ?? ""),
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// if (selectedDate != null) {
// 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 (selectedDateTime != null) {
// serviceRequestProvider.currentSelectedRequest?.startDate = selectedDateTime?.toIso8601String();
// }
// }
// });
// }
// },
// ).expanded,
// 8.width,
// ADatePicker(
// label: context.translation.endDate,
// date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.endDate ?? ""),
// 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,
// );
// serviceRequestProvider.currentSelectedRequest?.endDate = selectedDateTime?.toIso8601String();
// serviceRequestProvider.currentSelectedRequest?.workingHours = (((DateTime.parse(serviceRequestProvider.currentSelectedRequest!.endDate!)
// .difference(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.startDate!))
// .inSeconds ??
// 0) /
// 60) /
// 60)
// .toStringAsFixed(2);
// }
// });
// },
// ).expanded,
// ],
// )
// ],
8.height,
AppTextFormField(
labelText: context.translation.comments,
controller: _commentController,
backgroundColor: AppColor.neutral100,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
@ -459,171 +403,28 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.primary10,
loading: false,
onPressed: () async {
requestDetailProvider.needVisitHelperModel?.workOrderId= requestDetailProvider.currentWorkOrder!.data!.requestId;
print('payload to set initial visit ${requestDetailProvider.needVisitHelperModel?.toJson()}');
//TODO reset model and call api after confirm form backend...
await requestDetailProvider.engineerNeedVisit().whenComplete((){
Navigator.pop(context);
requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!);
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel();
});
if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) {
requestDetailProvider.updateNeedVisitHelperModel(
NeedVisitHelperModel(
workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId,
visitDate: requestDetailProvider.needVisitHelperModel?.visitDate,
comment: requestDetailProvider.needVisitHelperModel?.comment,
)
);
await requestDetailProvider.engineerUpdateNeedVisit();
}
else {
requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId;
await requestDetailProvider.engineerNeedVisit();
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel();
}
Navigator.pop(context);
},
),
16.height,
],
);
}));
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
return showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.setVisitDate.bottomSheetHeadingTextStyle(context),
),
15.height,
ADatePicker(
label: context.translation.visitDate,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.visitDate ?? ""),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
if (selectedDate != null) {
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 (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.date!))) {
"Visit Date time must be greater then request date".showToast;
return;
}
serviceRequestProvider.currentSelectedRequest?.visitDate = selectedDateTime?.toIso8601String();
}
});
}
},
),
if (serviceRequestProvider.currentSelectedRequest?.firstAction?.id == 404 && Provider.of<SettingProvider>(context, listen: false).assetGroup?.id == 1) ...[
8.height,
Row(
children: [
ADatePicker(
label: context.translation.startDate,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.startDate ?? ""),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
if (selectedDate != null) {
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 (selectedDateTime != null) {
serviceRequestProvider.currentSelectedRequest?.startDate = selectedDateTime?.toIso8601String();
}
}
});
}
},
).expanded,
8.width,
ADatePicker(
label: context.translation.endDate,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.endDate ?? ""),
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,
);
serviceRequestProvider.currentSelectedRequest?.endDate = selectedDateTime?.toIso8601String();
serviceRequestProvider.currentSelectedRequest?.workingHours = (((DateTime.parse(serviceRequestProvider.currentSelectedRequest!.endDate!)
.difference(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.startDate!))
.inSeconds ??
0) /
60) /
60)
.toStringAsFixed(2);
}
});
},
).expanded,
],
)
],
8.height,
AppTextFormField(
labelText: context.translation.comments,
backgroundColor: AppColor.neutral100,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
textInputType: TextInputType.multiline,
alignLabelWithHint: true,
onChange: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
onSaved: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
),
12.height,
AppFilledButton(
label: context.translation.save,
buttonColor: AppColor.primary10,
loading: serviceRequestProvider.isLoading ?? false,
onPressed: () async {
_formKey.currentState?.save();
// await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest);
// Navigator.pop(context, true);
Navigator.of(context).push(MaterialPageRoute(builder: (_) => VerifyArrivalView()));
},
),
16.height,
],
),
),
).bottomSheetContainer(context);
}));
}
static Future rejectRequestBottomSheet({required BuildContext context}) {
@ -639,14 +440,14 @@ class ServiceRequestBottomSheet {
child: context.translation.rejectionReason.heading4(context).paddingOnly(top: 21),
),
15.height,
SingleItemDropDownMenu<Lookup, ReasonProvider>(
SingleItemDropDownMenu<Lookup, RejectReasonProvider>(
context: context,
title: context.translation.reason,
backgroundColor: AppColor.neutral100,
initialValue: requestDetailProvider.engineerRejectHelperModel?.rejectionReason,
onSelect: (value) {
if (value != null) {
requestDetailProvider.engineerRejectHelperModel?.rejectionReason = value;
requestDetailProvider.engineerRejectHelperModel?.rejectReasonId=value.id;
requestDetailProvider.updateEngineerRejectHelperModel(requestDetailProvider.engineerRejectHelperModel);
}
},
@ -675,11 +476,8 @@ class ServiceRequestBottomSheet {
showBorder: true,
loading: requestDetailProvider.isLoading,
onPressed: () async {
requestDetailProvider.engineerRejectHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder?.data?.requestId;
requestDetailProvider.engineerRejectWorkOrder();
//Todo implement backend logic..
// serviceRequestProvider.serviceRequest.device = asset;
// await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.currentSelectedRequest);
Navigator.pop(context, true);
},
),
@ -745,6 +543,7 @@ class ServiceRequestBottomSheet {
void onItemTap({required int index, required BuildContext context}) {
switch (index) {
case 0:
Provider.of<RequestDetailProvider>(context,listen: false).sparePartHelperModel = SparePartHelperModel();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const SparePartRequest()),
@ -914,65 +713,16 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.green70,
loading: false,
onPressed: () {
print('feedback i got is ${feedback}');
//TODO uncommit this after testing...
// requestDetailProvider.engineerMarkAsFixed(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!, feedback:feedback);
Navigator.pop(context);
requestDetailProvider.engineerMarkAsFixed(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!, feedback:feedback);
},
),
],
);
}));
return showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return Form(
// key: _formKey,
child: SingleChildScrollView(
child: StatefulBuilder(builder: (context, setState) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox().indicatorWidget(),
8.height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.feedBack.bottomSheetHeadingTextStyle(context),
),
21.height,
AppTextFormField(
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
labelStyle: AppTextStyles.textFieldLabelStyle,
showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100,
alignLabelWithHint: true,
onChange: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
onSaved: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
),
16.height,
AppFilledButton(
label: context.translation.fixed,
buttonColor: AppColor.green70,
loading: false,
onPressed: () {},
),
],
);
}),
),
)..bottomSheetContainer(context);
}));
}
static Future nurseTakeActionBottomSheet({required BuildContext context}) {
bool acknowledge = false;
Uint8List? newSignature;
@ -1037,7 +787,7 @@ class ServiceRequestBottomSheet {
onPressed: () async {
if (newSignature != null && acknowledge) {
requestDetailProvider.nurseActionHelperModel=NurseActionHelperModel(
workOrderId: int.parse(requestDetailProvider.currentWorkOrder!.data!.workOrderNo!),
workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId,
signatureNurse: nurseSignature,
);
requestDetailProvider.nurseReject();
@ -1056,7 +806,7 @@ class ServiceRequestBottomSheet {
if (newSignature != null && acknowledge) {
//TODO replace provider with new provider and also check workorder id is not correct.
requestDetailProvider.nurseActionHelperModel=NurseActionHelperModel(
workOrderId: int.parse(requestDetailProvider.currentWorkOrder!.data!.workOrderNo!),
workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!,
signatureNurse: nurseSignature,
);
requestDetailProvider.nurseConfirm();

@ -1,42 +1,55 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';
class InitialVisitCard extends StatelessWidget {
const InitialVisitCard({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColor.white10,
),
padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 14.toScreenHeight),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(
DateTime.now().toString().toInitialVisitCardFormat,
textAlign: TextAlign.end,
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() {
//open bottom sheet again with the informations added...
}),
]),
2.height,
context.translation.visitDateAndTime.heading6(context).custom(color: AppColor.neutral120),
8.height,
'Comments for the visit will be visible here for reference'.heading6(context).custom(color: AppColor.neutral120),
return Consumer<RequestDetailProvider>(builder: (context, RequestDetailProvider requestDetailProvider, snapshot) {
],
),
);
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColor.white10,
),
padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 14.toScreenHeight),
margin: EdgeInsets.only(top: 10.toScreenHeight),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(
requestDetailProvider.needVisitHelperModel!.visitDate.toString().toInitialVisitCardFormat,
textAlign: TextAlign.end,
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() {
ServiceRequestBottomSheet.initialVisitBottomSheet(context: context);
}),
]),
2.height,
context.translation.visitDateAndTime.bodyText2(context).custom(color: AppColor.neutral120),
8.height,
if (requestDetailProvider.needVisitHelperModel?.comment != null) ...[
requestDetailProvider.needVisitHelperModel!.comment!.bodyText2(context).custom(
color: AppColor.neutral120,
),
]
],
),
);
});
}
}

@ -12,8 +12,10 @@ import 'package:test_sa/extensions/widget_extensions.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/helper_data_models/asset_retired/asset_retired_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
@ -41,34 +43,29 @@ class WorkOrderDetailView extends StatelessWidget {
return requestProvider.isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: requestProvider.currentWorkOrder == null
? const NoDataFound()
: Stack(
? const NoDataFound()
: Stack(
children: [
Column(
children: [
SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider),
40.height,
// skipForLater(serviceRequestsProvider.currentSelectedRequest),
// 20.height,
//TODO need to get data from api ..
// const InitialVisitCard(),
20.height,
],
),
).expanded,
FooterActionButton.requestDetailsFooterWidget(workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!, context: context),
],
),
// const TimerWidget(),
workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider),
initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider),
20.height,
],
);
),
).expanded,
FooterActionButton.requestDetailsFooterWidget(workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!,userProvider: _userProvider, context: context),
],
),
// const TimerWidget(),
],
);
});
}
@ -223,51 +220,51 @@ class WorkOrderDetailView extends StatelessWidget {
],
).paddingOnly(start: 16, end: 16, top: 16, bottom: 8),
(userProvider.user!.type == UsersTypes.normal_user
? Container(
height: 50,
padding: const EdgeInsets.only(left: 16, right: 16),
alignment: Alignment.center,
width: double.infinity,
decoration: ShapeDecoration(
color: context.isDark ? AppColor.neutral50 : AppColor.neutral30,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
),
child: Row(
children: [
Text(
'${context.translation.commentHere}...',
style: AppTextStyles.heading6.copyWith(
color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6),
),
).expanded,
"comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70),
],
),
)
: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Divider().defaultStyle(context),
16.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.viewComments,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
4.width,
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
),
],
).paddingOnly(bottom: 16, start: 16, end: 16))
? Container(
height: 50,
padding: const EdgeInsets.only(left: 16, right: 16),
alignment: Alignment.center,
width: double.infinity,
decoration: ShapeDecoration(
color: context.isDark ? AppColor.neutral50 : AppColor.neutral30,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
),
child: Row(
children: [
Text(
'${context.translation.commentHere}...',
style: AppTextStyles.heading6.copyWith(
color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6),
),
).expanded,
"comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70),
],
),
)
: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Divider().defaultStyle(context),
16.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.viewComments,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
4.width,
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
),
],
).paddingOnly(bottom: 16, start: 16, end: 16))
.onPress(() {
// showModalBottomSheet(
// context: context,
@ -279,12 +276,13 @@ class WorkOrderDetailView extends StatelessWidget {
// );
}),
//set condition for show asset detail button...
if (workOrder.nextStep!.workOrderNextStepEnum==WorkOrderNextStepEnum.verifyAssetDetail||workOrder.nextStep!.workOrderNextStepEnum==WorkOrderNextStepEnum.activity) ...[
if (workOrder.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.verifyAssetDetail || workOrder.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) ...[
assetRetiredButton(context: context),
]
],
).toShadowContainer(context, padding: 0);
}
Widget assetRetiredButton({required BuildContext context}) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenHeight, vertical: 12.toScreenWidth),
@ -295,10 +293,35 @@ class WorkOrderDetailView extends StatelessWidget {
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
Navigator.push(context, MaterialPageRoute(builder: (context) => const AssetRetired()));
Navigator.push(context, MaterialPageRoute(builder: (context) => const AssetRetired()));
}),
);
}
Widget initialVisitCard({required RequestDetailProvider requestDetailProvider, required UserProvider userProvider}) {
if (requestDetailProvider.currentWorkOrder!.data!.needAVisitDateTime != null &&
userProvider.user?.type == UsersTypes.engineer &&
requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) {
requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel(
workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId,
visitDate: requestDetailProvider.currentWorkOrder?.data?.needAVisitDateTime,
comment: requestDetailProvider.currentWorkOrder?.data?.needAVisitComment,
);
// requestDetailProvider.updateNeedVisitHelperModel(requestDetailProvider.needVisitHelperModel);
return const InitialVisitCard();
} else {
return const SizedBox();
}
}
void showToast({required UserProvider userProvider,required WorkOrderNextStepEnum nextStep,required BuildContext context}){
if(userProvider.user?.type==UsersTypes.engineer){
if(nextStep==WorkOrderNextStepEnum.nTakeAction){
const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: '');
}
}
}
}
// class RequestDetailView extends StatefulWidget {

@ -137,7 +137,7 @@ class _VerifyArrivalViewState extends State<VerifyArrivalView> {
break;
case 2:
//TODO api has error need to fixed by ahmed...
// requestDetailProvider.sendOtp(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!);
requestDetailProvider.sendOtp(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const VerifyOtpView()),

@ -9,13 +9,16 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/fault_description.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart';
import 'package:test_sa/providers/service_request_providers/loan_availability_provider.dart';
import 'package:test_sa/providers/work_order/fault_description_provider.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
@ -42,6 +45,7 @@ class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProv
ReasonProvider? _reasonProvider;
bool _isLoading = false;
Asset? loanAvailabilityAsset;
List<FaultDescription> _faults = [];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@ -65,6 +69,7 @@ class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProv
_loanAvailabilityProvider = Provider.of<LoanAvailabilityProvider>(context, listen: false);
_equipmentStatusProvider = Provider.of<EquipmentStatusProvider>(context, listen: false);
_reasonProvider?.serviceRequestId = _requestDetailProvider?.currentWorkOrder!.data!.requestId.toString();
_faults = await Provider.of<FaultDescriptionProvider>(context,listen: false).getFaultDescriptionList(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id);
_reasonProvider?.getDate();
_equipmentStatusProvider?.getDate();
_loanAvailabilityProvider?.getDate();
@ -75,7 +80,7 @@ class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProv
equipmentStatus: currentWorkOrderData.equipmentStatus,
loanAvailability: currentWorkOrderData.loanAvailablity,
failureReason: currentWorkOrderData.failureReasone,
faultDescription: currentWorkOrderData.problemDescription,
// faultDescription: currentWorkOrderData.problemDescription,
solution: currentWorkOrderData.solution?.name,
returnToService: currentWorkOrderData.returnToService,
serviceType: currentWorkOrderData.serviceType,
@ -184,19 +189,24 @@ class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProv
},
),
8.height,
//TODO replace this with correct provider api will be provided by ahmed with solutions data as well...
// ServiceReportFaultDescription(
// requestId: requestDetailProvider.currentServiceRequestId?.toString(),
// initialValue: requestDetailProvider.engineerUpdateWorkOrderHelperModel.faultDescription,
// onSelect: (status) {
// requestDetailProvider.engineerUpdateWorkOrderHelperModel.faultDescription = status;
// _workPreformedController.text = _subWorkOrders.faultDescription?.workPerformed ?? "";
// },
// ),
SingleItemDropDownMenu<FaultDescription, NullableLoadingProvider>(
context: context,
title: context.translation.faultDescription,
backgroundColor: AppColor.neutral100,
staticData: _faults,
showShadow: true,
initialValue: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.faultDescription,
onSelect: (fault) {
requestDetailProvider.engineerUpdateWorkOrderHelperModel?.faultDescription = fault;
requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution = fault?.workPerformed;
if(mounted){
requestDetailProvider.updateEngineerUpdateWorkOrderHelperModel(requestDetailProvider.engineerUpdateWorkOrderHelperModel);
}
},
),
11.height,
context.translation.solutions.heading6(context).custom(color: AppColor.neutral50),
11.height,
//TODO solution from api...
requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null
? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.heading6(context).custom(color: AppColor.neutral50)
: const SizedBox(),
@ -211,8 +221,6 @@ class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProv
label: context.translation.verify_asset_details,
buttonColor: AppColor.primary10,
onPressed: () async {
//TODO uncommit this when all informations are confirmed...
print('model is ${requestDetailProvider.engineerUpdateWorkOrderHelperModel?.toJson()}');
await requestDetailProvider.engineerUpdateWorkOrder();
Navigator.pop(context);
},

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
@ -16,12 +17,15 @@ import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.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/activities_list_view.dart';
import 'package:test_sa/service_request_latest/views/request_detail_main_view.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../../../models/service_request/spare_parts.dart';
import '../../../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
import '../../../../controllers/validator/validator.dart';
import '../../../../new_views/common_widgets/app_lazy_loading.dart';
class SparePartRequest extends StatefulWidget {
static const String id = "/spare-part-request";
@ -50,24 +54,33 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
super.initState();
_partsProvider = Provider.of<PartsProvider>(context, listen: false);
_requestDetailProvider = Provider.of<RequestDetailProvider>(context, listen: false);
_requestDetailProvider?.sparePartHelperModel = SparePartHelperModel(
id: _requestDetailProvider?.sparePartHelperModel?.id??0,
workOrderId:_requestDetailProvider?.sparePartHelperModel?.workOrderId?? _requestDetailProvider?.currentWorkOrder?.data?.requestId,
sparePartAttachments:_requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?? [],
sparePart:_requestDetailProvider?.sparePartHelperModel?.sparePart?? SparePart(),
quantity: _requestDetailProvider?.sparePartHelperModel?.quantity,
activityStatusId: _requestDetailProvider?.sparePartHelperModel?.activityStatusId,
comment: _requestDetailProvider?.sparePartHelperModel?.comment??'',
);
_partQtyController.text =_requestDetailProvider?.sparePartHelperModel?.quantity!=null? _requestDetailProvider!.sparePartHelperModel!.quantity.toString():'';
_oracleNoController.text = _requestDetailProvider?.sparePartHelperModel?.sparePart?.oracleCode!=null?_requestDetailProvider!.sparePartHelperModel!.sparePart!.oracleCode!:'';
_descriptionController.text =_requestDetailProvider?.sparePartHelperModel?.comment!=null? _requestDetailProvider!.sparePartHelperModel!.comment!:'';
scheduleMicrotask(() async {
_isLoading = true;
_files = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => File(e.name!)).toList() ?? [];
setState(() {});
_spareParts = await _partsProvider!.getPartsList(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id);
_requestDetailProvider?.sparePartHelperModel = SparePartHelperModel(
id: 0,
workOrderId: _requestDetailProvider?.currentWorkOrder?.data?.requestId,
sparePartAttachments: [],
sparePart: SparePart(),
);
_isLoading = false;
setState(() {});
});
// _isLoading = true;
}
void restValues({required RequestDetailProvider requestDetailProvider}) {
requestDetailProvider.sparePartHelperModel = SparePartHelperModel(id: 0, workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId, sparePartAttachments: []);
requestDetailProvider.sparePartHelperModel = SparePartHelperModel(id: 0, workOrderId: _requestDetailProvider?.currentWorkOrder?.data?.requestId, sparePartAttachments: []);
_partQtyController.clear();
_oracleNoController.clear();
_descriptionController.clear();
@ -116,11 +129,11 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
initialValue: requestDetailProvider.sparePartHelperModel?.sparePart,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
onSelect: (part) {
if (part != requestDetailProvider.sparePartHelperModel?.sparePart) {
restValues(requestDetailProvider: requestDetailProvider);
if(part!=null){
requestDetailProvider.sparePartHelperModel?.sparePart = part;
_oracleNoController.text = part.oracleCode??'';
requestDetailProvider.updateSparePartHelperModel(_requestDetailProvider?.sparePartHelperModel);
}
requestDetailProvider.sparePartHelperModel?.sparePart = part;
requestDetailProvider.updateSparePartHelperModel(_requestDetailProvider?.sparePartHelperModel);
},
),
12.height,
@ -146,22 +159,13 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
),
12.height,
AppTextFormField(
controller: _oracleNoController,
labelStyle: AppTextStyles.textFieldLabelStyle,
controller: _oracleNoController,
labelText: context.translation.oracleNo,
textInputType: TextInputType.number,
showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
enable: requestDetailProvider.sparePartHelperModel?.sparePart?.id != null,
validator: (value) => value == null || value.isEmpty
? context.translation.requiredField
: Validator.isNumeric(value)
? null
: context.translation.onlyNumbers,
onSaved: (text) {
//TODO set the values...
// serviceRequestProvider.initialSelectedSparePart. = num.tryParse(text ?? "");
},
enable: false,
),
12.height,
AppTextFormField(
@ -186,6 +190,11 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
files: _files,
buttonIcon: 'quotation_icon'.toSvgAsset(),
buttonColor: AppColor.primary10,
onChange: (List<File> file){
for (var element in file) {
print('path is ${element.path}');
}
},
),
],
).paddingAll(16),
@ -196,16 +205,50 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
).paddingAll(12).expanded,
FooterActionButton.footerContainer(
child: AppFilledButton(
label: context.translation.addSparePartActivity,
label:_requestDetailProvider?.sparePartHelperModel?.id==0? context.translation.addSparePartActivity:context.translation.updateSparePartActivity,
buttonColor: AppColor.green70,
onPressed: () async {
for (var file in _files) {
requestDetailProvider.sparePartHelperModel?.sparePartAttachments
?.add(SparePartAttachments(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
// List<SparePartAttachments> attachmentList = [];
// List<File> localFile = [];
// for (var file in _files) {
// print('loop executed..${file.path}');
// if(_requestDetailProvider?.sparePartHelperModel?.sparePartAttachments!=null){
// for (var attachment in _requestDetailProvider!.sparePartHelperModel!.sparePartAttachments!) {
// if(file.path==attachment.name){
// print('name i got is ${attachment.name}');
// attachmentList.add(attachment);
// }
// }
// }
// else{
// print('file path i got is ${file.path}');
// localFile.add(file);
// }
// attachmentList.add(SparePartAttachments(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
// requestDetailProvider.sparePartHelperModel?.sparePartAttachments
// ?.add(SparePartAttachments(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
// }
// for(var item in localFile){
// attachmentList.add(SparePartAttachments(id: 0, name: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}"));
// }
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
int status = -1;
if(_requestDetailProvider?.sparePartHelperModel?.id==0){
status = await requestDetailProvider.createActivitySparePart();
}
else{
status = await requestDetailProvider.updateActivitySparePart();
}
if (status == 200) {
await requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!);
//this is for hide the dialoge...
Navigator.pop(context);
Navigator.pop(context);
} else {
Navigator.pop(context);
}
print('model i got is ${requestDetailProvider.sparePartHelperModel?.toJson()}');
// TODO Api has issue call this function when it's solved.....
// requestDetailProvider.createActivitySparePart();
},
)),
],

@ -1,6 +1,5 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -347,7 +346,7 @@ class _CreateNewRequestState extends State<CreateNewRequest> with TickerProvider
// return;
// }
_serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList();
// _serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList();
if (_serviceRequest.audio != null) {
if (_isLocalUrl(_serviceRequest.audio!)) {
final File file = File(_serviceRequest.audio!);
@ -355,14 +354,18 @@ class _CreateNewRequestState extends State<CreateNewRequest> with TickerProvider
}
}
List<WorkOrderAttachments> attachement = [];
for (var url in _deviceImages) {
//for(var item in localFile){
// attachmentList.add(SparePartAttachments(id: 0, name: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}"));
// }
for (var item in _deviceImages) {
attachement.add(WorkOrderAttachments(id: 0, name: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}"));
}
_requestDetailProvider.workOrderHelperModel = WorkOrderHelperModel(
assetId: _serviceRequest.deviceId,
priorityId: _serviceRequest.priority?.id,
equipmentStatusId: _serviceRequest.defectType?.id,
voiceNote: _serviceRequest.audio,
workOrderAttachments: attachement,
comments: _serviceRequest.callComments,
//add attachments also...
);

Loading…
Cancel
Save