spare part ui implemented

main_production_spare_part
WaseemAbbasi22 2 weeks ago
parent e714fed62c
commit b56b998125

@ -3,12 +3,12 @@ class URLs {
static const String appReleaseBuildNumber = "50";
static const host1 = "https://atomsm.hmg.com"; // production url
// static const host1 = "https://atomsm.hmg.com"; // production url
// static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
// static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
static final String _baseUrl = "$_host/mobile"; // host local UAT
// static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/mobile"; // host local UAT
static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
// static final String _baseUrl = "$_host/v4/mobile"; // v4 for Demo module
// static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation

@ -364,7 +364,10 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
requestDetailProvider.updateSparePartHelperModel(requestDetailProvider.sparePartHelperModel);
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => const SparePartRequest(),
builder: (_) => SparePartRequest(
model: requestDetailProvider.sparePartHelperModel,
provider: requestDetailProvider,
),
));
}
}

@ -668,16 +668,20 @@ class ServiceRequestBottomSheet {
}
void onItemTap({required int index, required BuildContext context}) {
CMDetailProvider requestDetailProvider = Provider.of<CMDetailProvider>(context, listen: false);
switch (index) {
case 0:
Provider.of<CMDetailProvider>(context, listen: false).sparePartHelperModel = SparePartHelperModel();
requestDetailProvider.sparePartHelperModel = SparePartHelperModel();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const SparePartRequest()),
MaterialPageRoute(
builder: (context) => SparePartRequest(
model: requestDetailProvider.sparePartHelperModel,
provider: requestDetailProvider,
)),
);
break;
case 1:
CMDetailProvider requestDetailProvider = Provider.of<CMDetailProvider>(context, listen: false);
requestDetailProvider.activityMaintenanceHelperModel = ActivityMaintenanceHelperModel(
workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId,
id: 0,
@ -804,11 +808,16 @@ class ServiceRequestBottomSheet {
buttonColor: AppColor.primary10,
loading: false,
onPressed: () {
CMDetailProvider provider = Provider.of<CMDetailProvider>(context, listen: false);
Navigator.pop(context);
Provider.of<CMDetailProvider>(context, listen: false).sparePartHelperModel = SparePartHelperModel();
provider.sparePartHelperModel = SparePartHelperModel();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const SparePartRequest()),
MaterialPageRoute(
builder: (context) => SparePartRequest(
model: provider.sparePartHelperModel,
provider: provider,
)),
);
},
).expanded,

@ -338,8 +338,27 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
const Spacer(),
if (!provider.isReadOnlyRequest)
"edit_icon".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)).onPress(() async {
WorkOrderData currentWorkOrderData = provider.currentWorkOrder!.data!;
provider.workOrderCostModel = WorkOrderCostModel(
workOrderId: currentWorkOrderData.requestId,
labourCost: currentWorkOrderData.labourCost,
sparePartCost: currentWorkOrderData.sparePartCost,
travelCost: currentWorkOrderData.travelCost,
qAmount: currentWorkOrderData.qAmount,
prNo: currentWorkOrderData.prNo,
poNo: currentWorkOrderData.poNo,
mrNo: currentWorkOrderData.mrNo,
exchangeCost: currentWorkOrderData.exchangeCost,
);
provider.refreshTimer = false;
await Navigator.push(context, MaterialPageRoute(builder: (context) => CostDetailFormScreen(isEdit: true)));
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CostDetailFormScreen(
isEdit: true,
model: provider.workOrderCostModel,
provider: provider,
)));
provider.refreshTimer = true;
}),
],

@ -1,11 +1,8 @@
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/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/new_models/work_order_detail_model.dart';
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
@ -13,261 +10,189 @@ 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_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart';
class CostDetailFormScreen extends StatefulWidget {
static const String id = "/cost-detail-form-screen";
bool isEdit = false;
final bool isEdit;
final WorkOrderCostModel? model;
final CMDetailProvider provider;
CostDetailFormScreen({Key? key, required this.isEdit}) : super(key: key);
const CostDetailFormScreen({
Key? key,
required this.isEdit,
required this.model,
required this.provider,
}) : super(key: key);
@override
_CostDetailFormScreenState createState() => _CostDetailFormScreenState();
}
class _CostDetailFormScreenState extends State<CostDetailFormScreen> with TickerProviderStateMixin {
CMDetailProvider? _requestDetailProvider;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
}
void assignValues() {
// ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
// _requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
WorkOrderData currentWorkOrderData = _requestDetailProvider!.currentWorkOrder!.data!;
_requestDetailProvider!.workOrderCostModel = WorkOrderCostModel(
workOrderId: currentWorkOrderData.requestId,
labourCost: currentWorkOrderData.labourCost,
sparePartCost: currentWorkOrderData.sparePartCost,
travelCost: currentWorkOrderData.travelCost,
qAmount: currentWorkOrderData.qAmount,
prNo: currentWorkOrderData.prNo,
poNo: currentWorkOrderData.poNo,
mrNo: currentWorkOrderData.mrNo,
exchangeCost: currentWorkOrderData.exchangeCost,
);
}
@override
Widget build(BuildContext context) {
if (_requestDetailProvider == null) {
_requestDetailProvider = Provider.of<CMDetailProvider>(context, listen: false);
assignValues();
}
return Scaffold(
key: _scaffoldKey,
appBar: const DefaultAppBar(title: "Cost Details"),
body: Consumer<CMDetailProvider>(builder: (context, CMDetailProvider requestDetailProvider, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
AppTextFormField(
labelText: "Spare Part Cost",
backgroundColor: AppColor.neutral100,
initialValue: requestDetailProvider.workOrderCostModel?.sparePartCost?.toString(),
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.sparePartCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
initialValue: requestDetailProvider.workOrderCostModel?.labourCost?.toString(),
textAlign: TextAlign.center,
labelText: "Labor Cost",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.labourCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Travel Cost",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: requestDetailProvider.workOrderCostModel?.travelCost?.toString(),
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.travelCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Quot Amount",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: requestDetailProvider.workOrderCostModel?.qAmount?.toString(),
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.qAmount = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "PR No",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: requestDetailProvider.workOrderCostModel?.prNo,
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.prNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "PO No",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: requestDetailProvider.workOrderCostModel?.poNo,
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.poNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "MR No",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: requestDetailProvider.workOrderCostModel?.mrNo,
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.mrNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Exchange Cost",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: requestDetailProvider.workOrderCostModel?.exchangeCost != null ? requestDetailProvider.workOrderCostModel?.exchangeCost.toString() : '',
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
requestDetailProvider.workOrderCostModel?.exchangeCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
],
).toShadowContainer(context).paddingAll(16),
).expanded,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
label: "Update Cost Details",
buttonColor: AppColor.primary10,
onPressed: () async {
if (validateForm(requestDetailProvider: requestDetailProvider)) {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await requestDetailProvider.engineerUpdateCost().then((success) {
Navigator.pop(context);
if (success) {
body: ListenableBuilder(
listenable: widget.provider,
builder: (context, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
AppTextFormField(
labelText: "Spare Part Cost",
backgroundColor: AppColor.neutral100,
initialValue: widget.model?.sparePartCost?.toString(),
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
onChange: (value) {
widget.model?.sparePartCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
initialValue: widget.model?.labourCost?.toString(),
textAlign: TextAlign.center,
labelText: "Labor Cost",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
widget.model?.labourCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Travel Cost",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: widget.model?.travelCost?.toString(),
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
widget.model?.travelCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Quot Amount",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: widget.model?.qAmount?.toString(),
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
widget.model?.qAmount = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "PR No",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: widget.model?.prNo,
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
widget.model?.prNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "PO No",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: widget.model?.poNo,
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
widget.model?.poNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "MR No",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: widget.model?.mrNo,
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
widget.model?.mrNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Exchange Cost",
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
initialValue: widget.model?.exchangeCost != null ? widget.model?.exchangeCost.toString() : '',
textAlign: TextAlign.center,
textInputType: const TextInputType.numberWithOptions(decimal: true),
showShadow: false,
onChange: (value) {
widget.model?.exchangeCost = num.parse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
],
).toShadowContainer(context).paddingAll(16),
).expanded,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
label: "Update Cost Details",
buttonColor: AppColor.primary10,
onPressed: () async {
if (validateForm()) {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await widget.provider.engineerUpdateCost().then((success) {
Navigator.pop(context);
}
});
}
},
if (success) {
Navigator.pop(context);
}
});
}
},
),
),
),
],
);
}),
],
);
},
),
);
}
bool validateForm({required CMDetailProvider requestDetailProvider}) {
bool validateForm() {
bool isValid = true;
if (!widget.isEdit) {
return true;
}
// if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus != null) {
// if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 1 || requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 2) {
// if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.returnToService == null) {
// Fluttertoast.showToast(msg: "Return to service is required ", toastLength: Toast.LENGTH_LONG);
// return false;
// }
// }
// }
return isValid;
}
Widget assetStatusWidget({required BuildContext context, required EngineerUpdateWorkOrderHelperModel workOrderData}) {
return Consumer<EquipmentStatusProvider>(builder: (cxt, snapshot, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
context.translation.assetStatus.bodyText(context).custom(color: AppColor.black20),
8.height,
Wrap(
runSpacing: 8,
spacing: 8,
children: [
for (var element in snapshot.items)
Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 24,
height: 24,
child: Radio(
value: element,
activeColor: Colors.red,
fillColor: WidgetStateColor.resolveWith((states) {
if (states.contains(WidgetState.selected)) return AppColor.primary10;
return AppColor.neutral130;
}),
groupValue: workOrderData.equipmentStatus,
onChanged: (state) {
setState(() {
workOrderData.equipmentStatus = element;
});
}),
),
8.width,
Text(element.name ?? '', style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120)),
],
)
],
).toShimmer(isShow: snapshot.loading, context: context),
],
);
});
}
}

@ -33,15 +33,20 @@ import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class SparePartRequest extends StatefulWidget {
static const String id = "/spare-part-request";
final SparePartHelperModel ?model;
final CMDetailProvider provider;
const SparePartRequest({Key? key}) : super(key: key);
const SparePartRequest({
Key? key,
required this.model,
required this.provider,
}) : super(key: key);
@override
_SparePartRequestState createState() => _SparePartRequestState();
}
class _SparePartRequestState extends State<SparePartRequest> with TickerProviderStateMixin {
CMDetailProvider? _requestDetailProvider;
PartsProvider? _partsProvider;
bool _isLoading = false;
List<SparePart> _spareParts = [];
@ -62,37 +67,40 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
void initState() {
super.initState();
_partsProvider = Provider.of<PartsProvider>(context, listen: false);
_requestDetailProvider = Provider.of<CMDetailProvider>(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,
installQty: _requestDetailProvider?.sparePartHelperModel?.installQty,
returnQty: _requestDetailProvider?.sparePartHelperModel?.returnQty,
activityStatusId: _requestDetailProvider?.sparePartHelperModel?.activityStatusId ?? statusLookup.id,
activityStatus: _requestDetailProvider?.sparePartHelperModel?.activityStatus ?? statusLookup,
comment: _requestDetailProvider?.sparePartHelperModel?.comment ?? '',
// Initialize model with existing values or defaults
widget.provider.sparePartHelperModel = SparePartHelperModel(
id: widget.model?.id ?? 0,
workOrderId: widget.model?.workOrderId ?? widget.provider.currentWorkOrder?.data?.requestId,
sparePartAttachments: widget.model?.sparePartAttachments ?? [],
sparePart: widget.model?.sparePart ?? SparePart(),
quantity: widget.model?.quantity,
installQty: widget.model?.installQty,
returnQty: widget.model?.returnQty,
activityStatusId: widget.model?.activityStatusId ?? statusLookup.id,
activityStatus: widget.model?.activityStatus ?? statusLookup,
comment: widget.model?.comment ?? '',
);
_partQtyController.text = _requestDetailProvider?.sparePartHelperModel?.quantity != null ? _requestDetailProvider!.sparePartHelperModel!.quantity!.round().toString() : '';
_installQtyController.text = _requestDetailProvider?.sparePartHelperModel?.installQty != null ? _requestDetailProvider!.sparePartHelperModel!.installQty!.round().toString() : '';
_returnQtyController.text = _requestDetailProvider?.sparePartHelperModel?.returnQty != null ? _requestDetailProvider!.sparePartHelperModel!.returnQty!.round().toString() : '';
_oracleNoController.text = _requestDetailProvider?.sparePartHelperModel?.sparePart?.oracleCode != null ? _requestDetailProvider!.sparePartHelperModel!.sparePart!.oracleCode! : '';
_descriptionController.text = _requestDetailProvider?.sparePartHelperModel?.comment != null ? _requestDetailProvider!.sparePartHelperModel!.comment! : '';
activityStatus = _requestDetailProvider?.sparePartHelperModel?.activityStatus?.value;
_partQtyController.text = widget.provider.sparePartHelperModel?.quantity != null ? widget.provider.sparePartHelperModel!.quantity!.round().toString() : '';
_installQtyController.text = widget.provider.sparePartHelperModel?.installQty != null ? widget.provider.sparePartHelperModel!.installQty!.round().toString() : '';
_returnQtyController.text = widget.provider.sparePartHelperModel?.returnQty != null ? widget.provider.sparePartHelperModel!.returnQty!.round().toString() : '';
_oracleNoController.text = widget.provider.sparePartHelperModel?.sparePart?.oracleCode != null ? widget.provider.sparePartHelperModel!.sparePart!.oracleCode! : '';
_descriptionController.text = widget.provider.sparePartHelperModel?.comment != null ? widget.provider.sparePartHelperModel!.comment! : '';
activityStatus = widget.provider.sparePartHelperModel?.activityStatus?.value;
scheduleMicrotask(() async {
_isLoading = true;
attachments = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => GenericAttachmentModel(id: e.id!, name: e.name ?? '')).toList() ?? [];
attachments = widget.provider.sparePartHelperModel?.sparePartAttachments?.map((e) => GenericAttachmentModel(id: e.id!, name: e.name ?? '')).toList() ?? [];
setState(() {});
_spareParts = await _partsProvider!.getPartsListByDisplayName(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id);
_spareParts = await _partsProvider!.getPartsListByDisplayName(assetId: widget.provider.currentWorkOrder?.data?.asset?.id);
_isLoading = false;
setState(() {});
});
}
void restValues({required CMDetailProvider requestDetailProvider}) {
requestDetailProvider.sparePartHelperModel = SparePartHelperModel(id: 0, workOrderId: _requestDetailProvider?.currentWorkOrder?.data?.requestId, sparePartAttachments: []);
requestDetailProvider.sparePartHelperModel = SparePartHelperModel(id: 0, workOrderId: widget.provider.currentWorkOrder?.data?.requestId, sparePartAttachments: []);
_partQtyController.clear();
_installQtyController.clear();
_returnQtyController.clear();
@ -130,7 +138,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: IgnorePointer(
ignoring: _requestDetailProvider!.isReadOnlyRequest,
ignoring: widget.provider.isReadOnlyRequest,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
@ -164,7 +172,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
if (part != null) {
requestDetailProvider.sparePartHelperModel?.sparePart = part;
_oracleNoController.text = part.oracleCode ?? '';
requestDetailProvider.updateSparePartHelperModel(_requestDetailProvider?.sparePartHelperModel);
requestDetailProvider.updateSparePartHelperModel(widget.provider.sparePartHelperModel);
}
},
),
@ -307,7 +315,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
label: _requestDetailProvider?.sparePartHelperModel?.id == 0 ? context.translation.addSparePartActivity : context.translation.updateSparePartActivity,
label: widget.provider.sparePartHelperModel?.id == 0 ? context.translation.addSparePartActivity : context.translation.updateSparePartActivity,
buttonColor: AppColor.green70,
onPressed: () {
_onSubmit(requestDetailProvider: requestDetailProvider);
@ -345,7 +353,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
builder: (context) => const AppLazyLoading(),
);
bool success = false;
if (_requestDetailProvider?.sparePartHelperModel?.id == 0) {
if (widget.provider.sparePartHelperModel?.id == 0) {
success = await requestDetailProvider.createActivitySparePart();
} else {
success = await requestDetailProvider.updateActivitySparePart();
@ -356,7 +364,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
id: requestDetailProvider.currentWorkOrder!.data!.requestId!,
);
if (mounted) Navigator.pop(context);
if (_requestDetailProvider?.sparePartHelperModel?.id == 0) {
if (widget.provider.sparePartHelperModel?.id == 0) {
ServiceRequestBottomSheet.addAnotherSpareRequestBottomSheet(context: context);
const SizedBox().flushBar(
context: context,

@ -0,0 +1,207 @@
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/user_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/models/enums/user_types.dart';
import 'package:test_sa/models/helper_data_models/maintenance_request/activity_maintenance_model.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/spare_parts.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/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/cm_module/views/forms/maintenance_request/maintenance_request_main.dart';
import 'package:test_sa/modules/cm_module/views/forms/spare_part/spare_part_request.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/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class PmActivitiesListView extends StatefulWidget {
static const String id = "/activities-list";
const PmActivitiesListView({Key? key}) : super(key: key);
@override
_PmActivitiesListViewState createState() {
return _PmActivitiesListViewState();
}
}
class _PmActivitiesListViewState extends State<PmActivitiesListView> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
List<Activities> reOrderActivities = [];
List<Activities> activities = [];
bool disableNewActivity = false;
@override
Widget build(BuildContext context) {
UserProvider userProvider = Provider.of<UserProvider>(context);
return Scaffold(
appBar: const DefaultAppBar(
title: 'PM Activities',
// actions: [if (!showReorderView) IconButton(onPressed: () => activities.isEmpty ? null : setState(() => showReorderView = true), icon: const Icon(Icons.reorder_rounded))],
),
///TODO replace with pm provider and data from pm provider
body: Consumer<CMDetailProvider>(builder: (context, CMDetailProvider requestDetailProvider, child) {
activities = requestDetailProvider.currentWorkOrder!.data!.activities;
requestDetailProvider.lastVisitedRequestActivityId = (activities.isNotEmpty ? activities.last.id : -1)!;
if (activities.isNotEmpty && (activities.last.activityStatus!.value == 14 || activities.last.activityStatus!.value == 19)) {
disableNewActivity = true;
} else {
disableNewActivity = false;
}
return Column(
children: [
(activities.isEmpty && reOrderActivities.isEmpty)
? NoDataFound(message: context.translation.noDataFound).center.expanded
: ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: activities.length,
separatorBuilder: (czt, index) => 16.height,
itemBuilder: (context, index) {
return sparePartActivityCard(requestDetailProvider: requestDetailProvider, userProvider: userProvider, context: context, activity: activities[index]);
},
).expanded,
if (userProvider.user!.type == UsersTypes.engineer &&
(requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3))
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
label: 'Create New Spare Part',
maxWidth: true,
buttonColor: AppColor.primary10,
loading: requestDetailProvider.isLoading,
disableButton: disableNewActivity,
onPressed: () async {
// ServiceRequestBottomSheet.activityTypeBottomSheet(context: context);
},
))
],
);
}),
);
}
Widget sparePartActivityCard({required CMDetailProvider requestDetailProvider, required UserProvider userProvider, required BuildContext context, required Activities activity}) {
bool showActionButtons = userProvider.user!.userID == requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId &&
userProvider.user!.type == UsersTypes.engineer &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 &&
requestDetailProvider.currentWorkOrder?.data?.status?.value != 3;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StatusLabel(
label: activity.activityStatus?.name,
textColor: AppColor.white10,
backgroundColor: AppColor.primary10,
),
if (showActionButtons)
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"edit_icon".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)).onPress(() {
editSparePartRequest(context: context, requestDetailProvider: requestDetailProvider, activity: activity);
}),
12.width,
"delete_icon".toSvgAsset(height: 24, width: 24).onPress(() async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
int status = await requestDetailProvider.deleteActivitySparePart(id: activity.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,
InfoHeaderWidget(activity.activityType?.cleanupWhitespace.capitalizeFirstOfEach ?? '-'),
InfoTextWidget(
label: context.translation.partName,
value: activity.activitySparePart?.partCatalogItem?.partName,
),
InfoTextWidget(
label: context.translation.partNo,
value: activity.activitySparePart?.partCatalogItem?.partNumber,
showArrow: true,
),
if (activity.activitySparePart?.acitiySparePartAttachments?.isNotEmpty ?? false) ...[
6.height,
const Divider().defaultStyle(context),
FilesList(images: activity.activitySparePart!.acitiySparePartAttachments!.map((toElement) => URLs.getFileUrl(toElement.name!)!).toList()),
],
],
).toShadowContainer(context, showShadow: false).onPress(() {
///Move to cost page ..
// if (showActionButtons) return;
// if (requestDetailProvider.isReadOnlyRequest) {
// editSparePartRequest(context: context, requestDetailProvider: requestDetailProvider, activity: activity);
// } else if (userProvider.user!.userID == requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId) {
// requestDetailProvider.isReadOnlyRequest = true;
// editSparePartRequest(context: context, requestDetailProvider: requestDetailProvider, activity: activity);
// }
});
}
void editSparePartRequest({required BuildContext context, required CMDetailProvider requestDetailProvider, required Activities activity}) async {
requestDetailProvider.sparePartHelperModel = SparePartHelperModel(
id: activity.id,
workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId,
comment: activity.activitySparePart?.comment,
sparePartAttachments: activity.activitySparePart?.acitiySparePartAttachments ?? [],
activityStatus: activity.activityStatus,
sparePart: SparePart(
id: activity.activitySparePart?.partCatalogItem?.id,
partName: activity.activitySparePart?.partCatalogItem?.partName,
partNo: activity.activitySparePart?.partCatalogItem?.partNumber,
oracleCode: activity.activitySparePart?.partCatalogItem?.oracleCode),
quantity: activity.activitySparePart?.quantity,
installQty: activity.activitySparePart?.installQty,
returnQty: activity.activitySparePart?.returnQty,
activityStatusId: activity.activityStatus?.id,
);
requestDetailProvider.updateSparePartHelperModel(requestDetailProvider.sparePartHelperModel);
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => SparePartRequest(
model: requestDetailProvider.sparePartHelperModel,
provider: requestDetailProvider,
),
));
}
}

@ -0,0 +1,127 @@
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/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/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/enums/work_order_next_step.dart';
import 'package:test_sa/models/generic_attachment_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/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cm_module/views/forms/asset_retired/asset_retired.dart';
import 'package:test_sa/modules/cm_module/views/forms/cost/cost_detail_form_screen.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/views/widgets/equipment/asset_detail_page.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/item_views/info_date_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart';
class PmCostDetailsView extends StatefulWidget {
PmCostDetailsView({Key? key}) : super(key: key);
@override
State<PmCostDetailsView> createState() => _PmCostDetailsViewState();
}
class _PmCostDetailsViewState extends State<PmCostDetailsView> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
///TODO: replace with pm provider and data from provider and remove the extra widgets as well.
return Consumer<CMDetailProvider>(builder: (pContext, requestProvider, _) {
bool showCostCard = context.userProvider.user!.type == UsersTypes.engineer &&
!requestProvider.isReadOnlyRequest &&
requestProvider.currentWorkOrder?.data?.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.activity;
return requestProvider.isLoading
? CircularProgressIndicator(color: AppColor.loadingColor(context)).center
: requestProvider.currentWorkOrder == null
? const NoDataFound()
: Column(
children: [
SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showCostCard) ...[
16.height,
costCard(context, requestProvider),
],
],
),
).expanded,
],
);
});
}
Widget costCard(BuildContext context, CMDetailProvider provider) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
InfoHeader16Widget("Cost"),
const Spacer(),
if (!provider.isReadOnlyRequest)
///TODO replace with exact provider and data from provider and remove the extra widgets as well.
"edit_icon".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)).onPress(() async {
WorkOrderData currentWorkOrderData = provider.currentWorkOrder!.data!;
provider.workOrderCostModel = WorkOrderCostModel(
workOrderId: currentWorkOrderData.requestId,
labourCost: currentWorkOrderData.labourCost,
sparePartCost: currentWorkOrderData.sparePartCost,
travelCost: currentWorkOrderData.travelCost,
qAmount: currentWorkOrderData.qAmount,
prNo: currentWorkOrderData.prNo,
poNo: currentWorkOrderData.poNo,
mrNo: currentWorkOrderData.mrNo,
exchangeCost: currentWorkOrderData.exchangeCost,
);
provider.refreshTimer = false;
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CostDetailFormScreen(
isEdit: true,
model: provider.workOrderCostModel,
provider: provider,
)));
provider.refreshTimer = true;
}),
],
),
InfoTextWidget(label: 'Spare Part Cost'.addTranslation, value: provider.currentWorkOrder?.data?.sparePartCost?.toString() ?? '-'),
InfoTextWidget(label: 'Labor Cost'.addTranslation, value: provider.currentWorkOrder?.data?.labourCost?.toString() ?? '-'),
InfoTextWidget(label: 'Travel Cost'.addTranslation, value: provider.currentWorkOrder?.data?.travelCost?.toString() ?? '-'),
InfoTextWidget(label: 'Quot Amount'.addTranslation, value: provider.currentWorkOrder?.data?.qAmount?.toString() ?? '-'),
InfoTextWidget(label: 'PR No'.addTranslation, value: provider.currentWorkOrder?.data?.prNo?.toString() ?? '-'),
InfoTextWidget(label: 'PO No'.addTranslation, value: provider.currentWorkOrder?.data?.poNo?.toString() ?? '-'),
InfoTextWidget(label: 'MR No'.addTranslation, value: provider.currentWorkOrder?.data?.mrNo?.toString() ?? '-'),
InfoTextWidget(label: 'Exchange Cost'.addTranslation, value: provider.currentWorkOrder?.data?.exchangeCost?.toString() ?? '-'),
],
).toShadowContainer(context);
}
}

@ -8,6 +8,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/pm_module/ppm_wo/activities/pm_activities_list_view.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
@ -82,6 +83,20 @@ class _PpmDetailsPageState extends State<PpmDetailsPage> {
textColor: AppColor.getRequestStatusTextColorByName(context, planPreventiveVisit.visitStatus!.name!),
backgroundColor: AppColor.getRequestStatusColorByName(context, planPreventiveVisit.visitStatus!.name!),
),
// "edit_icon".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)).onPress(() {
// if(userProvider!.user!.type == UsersTypes.engineer && (!ppmProvider.isReadOnly)){
// FooterActionButton.footerContainer(
// child: AppFilledButton(
// onPressed: () async {
// await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit)));
// getVisitData();
// },
// label: context.translation.updateWorkOrder,
// ),
// context: context,
// );
// }
// })
],
),
InfoHeader16Widget(planPreventiveVisit.assetName?.cleanupWhitespace.capitalizeFirstOfEach ?? ''),
@ -104,26 +119,28 @@ class _PpmDetailsPageState extends State<PpmDetailsPage> {
).expanded,
if (userProvider!.user!.type == UsersTypes.engineer && (!ppmProvider.isReadOnly)) ...[
FooterActionButton.footerContainer(
child: AppFilledButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit)));
getVisitData();
},
label: context.translation.updateWorkOrder,
child: Column(
children: [
AppFilledButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit)));
getVisitData();
},
label: context.translation.updateWorkOrder,
),
12.height,
AppFilledButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (_) => const PmActivitiesListView()));
getVisitData();
},
buttonColor: AppColor.neutral50,
label: context.translation.activities,
),
],
),
context: context,
)
] else ...[
// FooterActionButton.footerContainer(
// context: context,
// child: AppFilledButton(
// onPressed: () async {
// await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit)));
// getVisitData();
// },
// label: context.translation.viewDetails,
// ),
// )
]
])
: const Center(child: NoDataFound());

Loading…
Cancel
Save